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.txt154
-rw-r--r--SConstruct4
-rw-r--r--build_files/cmake/Modules/FindPythonLibsUnix.cmake9
-rw-r--r--build_files/cmake/macros.cmake12
-rw-r--r--build_files/scons/config/darwin-config.py7
-rw-r--r--build_files/scons/config/freebsd7-config.py5
-rw-r--r--build_files/scons/config/freebsd8-config.py5
-rw-r--r--build_files/scons/config/freebsd9-config.py5
-rw-r--r--build_files/scons/config/linux-config.py9
-rw-r--r--build_files/scons/config/linuxcross-config.py5
-rw-r--r--build_files/scons/config/win32-mingw-config.py7
-rw-r--r--build_files/scons/config/win32-vc-config.py7
-rw-r--r--build_files/scons/config/win64-mingw-config.py7
-rw-r--r--build_files/scons/config/win64-vc-config.py7
-rw-r--r--build_files/scons/tools/Blender.py5
-rw-r--r--build_files/scons/tools/btools.py10
-rw-r--r--doc/python_api/rst/bge.types.rst28
-rw-r--r--intern/CMakeLists.txt4
-rw-r--r--intern/SConscript3
-rw-r--r--intern/container/CTR_HashedPtr.h6
-rw-r--r--intern/cycles/CMakeLists.txt9
-rw-r--r--intern/cycles/app/CMakeLists.txt4
-rw-r--r--intern/cycles/app/cycles_test.cpp2
-rw-r--r--intern/cycles/blender/CCL_api.h6
-rw-r--r--intern/cycles/blender/addon/__init__.py6
-rw-r--r--intern/cycles/blender/addon/engine.py7
-rw-r--r--intern/cycles/blender/addon/enums.py5
-rw-r--r--intern/cycles/blender/addon/ui.py6
-rw-r--r--intern/cycles/blender/blender_camera.cpp192
-rw-r--r--intern/cycles/blender/blender_object.cpp85
-rw-r--r--intern/cycles/blender/blender_particles.cpp194
-rw-r--r--intern/cycles/blender/blender_python.cpp42
-rw-r--r--intern/cycles/blender/blender_session.cpp55
-rw-r--r--intern/cycles/blender/blender_session.h2
-rw-r--r--intern/cycles/blender/blender_sync.cpp19
-rw-r--r--intern/cycles/blender/blender_sync.h15
-rw-r--r--intern/cycles/blender/blender_util.h44
-rw-r--r--intern/cycles/cmake/external_libs.cmake27
-rw-r--r--intern/cycles/device/device.cpp4
-rw-r--r--intern/cycles/device/device.h2
-rw-r--r--intern/cycles/device/device_cpu.cpp8
-rw-r--r--intern/cycles/device/device_intern.h2
-rw-r--r--intern/cycles/device/device_task.cpp2
-rw-r--r--intern/cycles/kernel/kernel_projection.h2
-rw-r--r--intern/cycles/kernel/osl/osl_globals.h5
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp23
-rw-r--r--intern/cycles/kernel/shaders/node_normal_map.osl4
-rw-r--r--intern/cycles/kernel/svm/svm_geometry.h2
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h23
-rw-r--r--intern/cycles/render/camera.cpp30
-rw-r--r--intern/cycles/render/camera.h5
-rw-r--r--intern/cycles/render/light.cpp8
-rw-r--r--intern/cycles/render/nodes.cpp5
-rw-r--r--intern/cycles/render/osl.cpp16
-rw-r--r--intern/cycles/render/osl.h2
-rw-r--r--intern/cycles/render/particles.cpp3
-rw-r--r--intern/cycles/render/scene.cpp94
-rw-r--r--intern/cycles/render/scene.h10
-rw-r--r--intern/cycles/render/session.cpp18
-rw-r--r--intern/cycles/render/session.h1
-rw-r--r--intern/cycles/util/util_boundbox.h71
-rw-r--r--intern/cycles/util/util_progress.h15
-rw-r--r--intern/cycles/util/util_stats.h11
-rw-r--r--intern/cycles/util/util_task.cpp10
-rw-r--r--intern/cycles/util/util_task.h5
-rw-r--r--intern/cycles/util/util_thread.h3
-rw-r--r--intern/cycles/util/util_transform.cpp7
-rw-r--r--intern/cycles/util/util_transform.h37
-rw-r--r--intern/ghost/CMakeLists.txt1
-rw-r--r--intern/guardedalloc/cpp/mallocn.cpp3
-rw-r--r--intern/itasc/CMakeLists.txt2
-rw-r--r--intern/itasc/kdl/chain.hpp9
-rw-r--r--intern/itasc/kdl/tree.hpp19
-rw-r--r--intern/locale/CMakeLists.txt44
-rw-r--r--intern/locale/SConscript14
-rw-r--r--intern/locale/boost_locale_wrapper.cpp87
-rw-r--r--intern/locale/boost_locale_wrapper.h49
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py4
-rw-r--r--release/scripts/startup/bl_ui/space_image.py2
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py6
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py26
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py2
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py4
-rw-r--r--source/blender/avi/intern/avi.c14
-rw-r--r--source/blender/blenfont/BLF_translation.h26
-rw-r--r--source/blender/blenfont/CMakeLists.txt4
-rw-r--r--source/blender/blenfont/SConscript3
-rw-r--r--source/blender/blenfont/intern/blf.c1
-rw-r--r--source/blender/blenfont/intern/blf_lang.c246
-rw-r--r--source/blender/blenfont/intern/blf_translation.c86
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_lamp.h3
-rw-r--r--source/blender/blenkernel/BKE_mesh.h4
-rw-r--r--source/blender/blenkernel/BKE_multires.h2
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c4
-rw-r--r--source/blender/blenkernel/intern/anim.c115
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c8
-rw-r--r--source/blender/blenkernel/intern/bmfont.c13
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c41
-rw-r--r--source/blender/blenkernel/intern/curve.c14
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c43
-rw-r--r--source/blender/blenkernel/intern/displist.c109
-rw-r--r--source/blender/blenkernel/intern/image.c22
-rw-r--r--source/blender/blenkernel/intern/lamp.c40
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c2
-rw-r--r--source/blender/blenkernel/intern/mesh.c2
-rw-r--r--source/blender/blenkernel/intern/multires.c2
-rw-r--r--source/blender/blenkernel/intern/object.c2
-rw-r--r--source/blender/blenkernel/intern/ocean.c20
-rw-r--r--source/blender/blenkernel/intern/scene.c26
-rw-r--r--source/blender/blenkernel/intern/seqmodifier.c4
-rw-r--r--source/blender/blenkernel/intern/sequencer.c18
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c49
-rw-r--r--source/blender/blenkernel/intern/smoke.c28
-rw-r--r--source/blender/blenkernel/intern/sound.c20
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c3
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c6
-rw-r--r--source/blender/blenlib/BLI_math.h1
-rw-r--r--source/blender/blenlib/BLI_math_interp.h44
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h20
-rw-r--r--source/blender/blenlib/BLI_pbvh.h3
-rw-r--r--source/blender/blenlib/BLI_string_utf8.h1
-rw-r--r--source/blender/blenlib/CMakeLists.txt1
-rw-r--r--source/blender/blenlib/PIL_time.h13
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c6
-rw-r--r--source/blender/blenlib/intern/math_interp.c351
-rw-r--r--source/blender/blenlib/intern/pbvh.c10
-rw-r--r--source/blender/blenlib/intern/string_utf8.c27
-rw-r--r--source/blender/blenlib/intern/voronoi.c6
-rw-r--r--source/blender/blenloader/intern/readfile.c39
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c8
-rw-r--r--source/blender/bmesh/intern/bmesh_decimate_collapse.c102
-rw-r--r--source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c8
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c16
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c78
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h8
-rw-r--r--source/blender/bmesh/operators/bmo_bevel.c1368
-rw-r--r--source/blender/bmesh/operators/bmo_create.c6
-rw-r--r--source/blender/bmesh/operators/bmo_hull.c18
-rw-r--r--source/blender/bmesh/operators/bmo_smooth_laplacian.c4
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c2
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c2
-rw-r--r--source/blender/compositor/nodes/COM_ScaleNode.cpp22
-rw-r--r--source/blender/compositor/nodes/COM_Stabilize2dNode.cpp2
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.cpp17
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.h1
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp55
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersBaseProg.h1
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.cpp51
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.h18
-rw-r--r--source/blender/compositor/operations/COM_TrackPositionOperation.cpp2
-rw-r--r--source/blender/editors/animation/anim_draw.c2
-rw-r--r--source/blender/editors/animation/anim_filter.c20
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c18
-rw-r--r--source/blender/editors/curve/editcurve.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c1046
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c244
-rw-r--r--source/blender/editors/include/ED_gpencil.h1
-rw-r--r--source/blender/editors/include/UI_interface.h2
-rw-r--r--source/blender/editors/include/UI_resources.h6
-rw-r--r--source/blender/editors/interface/interface.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c54
-rw-r--r--source/blender/editors/interface/interface_regions.c4
-rw-r--r--source/blender/editors/interface/interface_templates.c48
-rw-r--r--source/blender/editors/interface/interface_widgets.c6
-rw-r--r--source/blender/editors/interface/resources.c43
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c2
-rw-r--r--source/blender/editors/mesh/editmesh_select.c459
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c118
-rw-r--r--source/blender/editors/object/object_add.c4
-rw-r--r--source/blender/editors/render/render_update.c3
-rw-r--r--source/blender/editors/screen/screendump.c60
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c32
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c8
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c11
-rw-r--r--source/blender/editors/space_clip/clip_draw.c11
-rw-r--r--source/blender/editors/space_clip/clip_ops.c2
-rw-r--r--source/blender/editors/space_clip/clip_utils.c22
-rw-r--r--source/blender/editors/space_graph/space_graph.c6
-rw-r--r--source/blender/editors/space_node/drawnode.c26
-rw-r--r--source/blender/editors/space_node/node_edit.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c7
-rw-r--r--source/blender/editors/space_text/text_draw.c38
-rw-r--r--source/blender/editors/space_text/text_ops.c14
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c34
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c14
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c4
-rw-r--r--source/blender/editors/transform/transform.c25
-rw-r--r--source/blender/editors/transform/transform_conversions.c15
-rw-r--r--source/blender/editors/transform/transform_manipulator.c10
-rw-r--r--source/blender/imbuf/intern/colormanagement.c8
-rw-r--r--source/blender/imbuf/intern/dds/BlockDXT.h36
-rw-r--r--source/blender/imbuf/intern/dds/FlipDXT.cpp6
-rw-r--r--source/blender/imbuf/intern/dds/Stream.h2
-rw-r--r--source/blender/imbuf/intern/divers.c16
-rw-r--r--source/blender/imbuf/intern/imageprocess.c197
-rw-r--r--source/blender/imbuf/intern/indexer.c2
-rw-r--r--source/blender/imbuf/intern/jp2.c2
-rw-r--r--source/blender/imbuf/intern/jpeg.c14
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_stub.cpp34
-rw-r--r--source/blender/imbuf/intern/radiance_hdr.c1
-rw-r--r--source/blender/imbuf/intern/rectop.c2
-rw-r--r--source/blender/imbuf/intern/scaling.c14
-rw-r--r--source/blender/makesdna/DNA_curve_types.h5
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h2
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h5
-rw-r--r--source/blender/makesdna/DNA_object_types.h17
-rw-r--r--source/blender/makesdna/DNA_scene_types.h11
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h18
-rw-r--r--source/blender/makesdna/intern/makesdna.c2
-rw-r--r--source/blender/makesrna/intern/makesrna.c10
-rw-r--r--source/blender/makesrna/intern/rna_access.c8
-rw-r--r--source/blender/makesrna/intern/rna_brush.c4
-rw-r--r--source/blender/makesrna/intern/rna_curve.c5
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c2
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c7
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c23
-rw-r--r--source/blender/makesrna/intern/rna_object.c21
-rw-r--r--source/blender/makesrna/intern/rna_scene.c12
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c39
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c3
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c34
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c7
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_colorSpill.c7
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bump.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c1
-rw-r--r--source/blender/python/generic/py_capi_utils.c2
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h2
-rw-r--r--source/blender/render/intern/include/render_types.h4
-rw-r--r--source/blender/render/intern/source/convertblender.c6
-rw-r--r--source/blender/render/intern/source/external_engine.c14
-rw-r--r--source/blender/render/intern/source/pipeline.c17
-rw-r--r--source/blender/render/intern/source/voxeldata.c2
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c151
-rw-r--r--source/blender/windowmanager/intern/wm_window.c14
-rw-r--r--source/blenderplayer/CMakeLists.txt4
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c4
-rw-r--r--source/creator/CMakeLists.txt20
-rw-r--r--source/gameengine/Converter/BL_ArmatureChannel.cpp2
-rw-r--r--source/gameengine/Converter/BL_ArmatureConstraint.cpp2
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp1
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp266
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp11
-rw-r--r--source/gameengine/Expressions/IntValue.cpp2
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp16
-rw-r--r--source/gameengine/GameLogic/SCA_ILogicBrick.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_PropertySensor.cpp24
-rw-r--r--source/gameengine/GameLogic/SCA_RandomActuator.cpp10
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp7
-rw-r--r--source/gameengine/Ketsji/BL_Material.cpp55
-rw-r--r--source/gameengine/Ketsji/BL_Material.h15
-rw-r--r--source/gameengine/Ketsji/BL_Shader.cpp56
-rw-r--r--source/gameengine/Ketsji/BL_Shader.h6
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp7
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.h2
-rw-r--r--source/gameengine/Ketsji/KX_CharacterWrapper.h2
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.cpp170
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.h4
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.h2
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp33
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h3
-rw-r--r--source/gameengine/Ketsji/KX_VertexProxy.cpp41
-rw-r--r--source/gameengine/Ketsji/KX_VertexProxy.h4
-rw-r--r--source/gameengine/Network/NG_NetworkDeviceInterface.h4
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp5
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h1
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h1
-rw-r--r--source/gameengine/Rasterizer/RAS_ICanvas.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_TexVert.cpp32
-rw-r--r--source/gameengine/Rasterizer/RAS_TexVert.h8
-rw-r--r--source/gameengine/SceneGraph/SG_IObject.h6
-rw-r--r--source/gameengine/VideoTexture/ImageRender.cpp2
285 files changed, 6516 insertions, 2582 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c33f4384a76..d5c1b5c287f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -289,18 +289,14 @@ if(APPLE)
set(OSX_SYSTEM unsupported)
endif()
message(STATUS "Detected system-version: " ${OSX_SYSTEM})
-
- if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
- set(CMAKE_OSX_DEPLOYMENT_TARGET "10.6" CACHE STRING "" FORCE) # 10.6 is our min. target, if you use higher sdk, weak linking happens - with 10.5 we have still not solved problems, build those with 10.5.sdk for now !!!
- endif()
if(${CMAKE_GENERATOR} MATCHES "Xcode")
- ##### workaround for actual official cmake incompatibility with xcode 4.3 #####
+ ##### cmake incompatibility with xcode 4.3 and higher #####
if(${XCODE_VERSION} MATCHES '') # cmake fails due looking for xcode in the wrong path, thus will be empty var
- message("Official cmake does not yet support Xcode 4.3, get a patched version here: http://www.jensverwiebe.de/Blender/CMake%202.8-7patched.zip")
+ message(FATAL_ERROR "Xcode 4.3 and higher must be used with cmake 2.8-8 or higher")
endif()
- ### end workaround for actual official cmake incompatibility with xcode 4.3 ###
+ ### end cmake incompatibility with xcode 4.3 and higher ###
if(${XCODE_VERSION} VERSION_EQUAL 4 OR ${XCODE_VERSION} VERSION_GREATER 4 AND ${XCODE_VERSION} VERSION_LESS 4.3)
# Xcode 4 defaults to the Apple LLVM Compiler.
@@ -315,7 +311,28 @@ if(APPLE)
endif()
message(STATUS "Detected Xcode-version: " ${XCODE_VERSION})
+
+ if(${XCODE_VERSION} VERSION_LESS 4.3)
+ set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk CACHE PATH "" FORCE) # use guaranteed existing sdk
+ else()
+ # note: i don't use xcode-select path on purpose, cause also /Applications/Xcode.app would be allowed
+ # absolute pathes are more foolproof here !
+ set(OSX_SYSROOT_PREFIX /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform)
+ set(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk
+ set(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE)
+ endif()
+ if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
+ set(CMAKE_OSX_DEPLOYMENT_TARGET "10.5" CACHE STRING "" FORCE) # 10.5 is our min. target, if you use higher sdk, weak linking happens
+ endif()
+
+ if(NOT ${CMAKE_GENERATOR} MATCHES "Xcode")
+ # force CMAKE_OSX_DEPLOYMENT_TARGET for makefiles, will not work else ( cmake bug ? )
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
+ add_definitions ("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
+ endif()
+
option(WITH_COCOA "Use Cocoa framework instead of deprecated Carbon" ON)
option(USE_QTKIT "Use QtKit instead of Carbon quicktime (needed for having partial quicktime for 64bit)" OFF)
option(WITH_LIBS10.5 "Use 10.5 libs (needed for 64bit builds)" OFF)
@@ -336,8 +353,8 @@ if(NOT WITH_GAMEENGINE AND WITH_PLAYER)
message(FATAL_ERROR "WITH_PLAYER requires WITH_GAMEENGINE")
endif()
-if(NOT WITH_AUDASPACE AND (WITH_OPENAL OR WITH_SDL OR WITH_JACK OR WITH_GAMEENGINE))
- message(FATAL_ERROR "WITH_OPENAL/WITH_SDL/WITH_JACK/WITH_CODEC_FFMPEG/WITH_GAMEENGINE require WITH_AUDASPACE")
+if(NOT WITH_AUDASPACE AND (WITH_OPENAL OR WITH_JACK OR WITH_GAMEENGINE))
+ message(FATAL_ERROR "WITH_OPENAL/WITH_JACK/WITH_CODEC_FFMPEG/WITH_GAMEENGINE require WITH_AUDASPACE")
endif()
if(NOT WITH_SDL AND WITH_GHOST_SDL)
@@ -372,8 +389,8 @@ if(WITH_CYCLES)
set(WITH_OPENIMAGEIO ON)
endif()
-# auto enable boost for cycles and booleans
-if(WITH_CYCLES OR WITH_MOD_BOOLEAN)
+# 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)
endif()
@@ -589,28 +606,6 @@ if(UNIX AND NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS")
endif()
- if(WITH_INTERNATIONAL)
- find_library(INTL_LIBRARY
- NAMES intl
- PATHS
- /sw/lib
- )
-
- find_library(ICONV_LIBRARY
- NAMES iconv
- PATHS
- /sw/lib
- )
- mark_as_advanced(
- ICONV_LIBRARY
- INTL_LIBRARY
- )
-
- if(INTL_LIBRARY AND ICONV_LIBRARY)
- set(GETTEXT_LIBRARIES ${INTL_LIBRARY} ${ICONV_LIBRARY})
- endif()
- endif()
-
if(WITH_FFTW3)
find_package(Fftw3)
if(NOT FFTW3_FOUND)
@@ -658,7 +653,11 @@ if(UNIX AND NOT APPLE)
else()
set(Boost_USE_MULTITHREADED ON)
endif()
- find_package(Boost 1.34 COMPONENTS filesystem regex system thread)
+ set(__boost_packages filesystem regex system thread)
+ if (WITH_INTERNATIONAL)
+ list(APPEND __boost_packages locale)
+ endif()
+ find_package(Boost 1.34 COMPONENTS ${__boost_packages})
mark_as_advanced(Boost_DIR) # why doesnt boost do this?
endif()
@@ -715,7 +714,7 @@ if(UNIX AND NOT APPLE)
set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
set(LLVM_VERSION "3.0" CACHE STRING "Version of LLVM to use")
set(LLVM_STATIC YES)
- if(LLVM_DIRECTORY)
+ if(EXISTS "${LLVM_DIRECTORY}/bin/llvm-config")
set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config")
else()
set(LLVM_CONFIG llvm-config)
@@ -730,7 +729,7 @@ if(UNIX AND NOT APPLE)
OUTPUT_VARIABLE LLVM_LIB_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
find_library(LLVM_LIBRARY
- NAMES libLLVMAnalysis.a # first of a whole bunch of libs to get
+ NAMES LLVMAnalysis # first of a whole bunch of libs to get
PATHS ${LLVM_LIB_DIR})
message(STATUS "LLVM version = ${LLVM_VERSION}")
message(STATUS "LLVM dir = ${LLVM_DIRECTORY}")
@@ -875,13 +874,6 @@ elseif(WIN32)
add_definitions(-DWIN32)
- if(WITH_INTERNATIONAL)
- set(ICONV ${LIBDIR}/iconv)
- set(ICONV_INCLUDE_DIRS ${ICONV}/include)
- set(ICONV_LIBRARIES iconv)
- set(ICONV_LIBPATH ${ICONV}/lib)
- endif()
-
set(JPEG "${LIBDIR}/jpeg")
set(JPEG_INCLUDE_DIR "${JPEG}/include")
set(JPEG_LIBPATH ${JPEG}/lib) # not cmake defined
@@ -974,13 +966,6 @@ elseif(WIN32)
set(CXX_WARNINGS "${_WARNINGS}")
unset(_WARNINGS)
- if(WITH_INTERNATIONAL)
- set(GETTEXT ${LIBDIR}/gettext)
- set(GETTEXT_INCLUDE_DIRS ${GETTEXT}/include)
- set(GETTEXT_LIBPATH ${GETTEXT}/lib)
- set(GETTEXT_LIBRARIES gnu_gettext)
- endif()
-
if(WITH_MOD_CLOTH_ELTOPO)
set(LAPACK ${LIBDIR}/lapack)
# set(LAPACK_INCLUDE_DIR ${LAPACK}/include)
@@ -1133,6 +1118,11 @@ 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_INTERNATIONAL)
+ set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
+ optimized libboost_locale-${BOOST_POSTFIX}
+ debug libboost_locale-${BOOST_DEBUG_POSTFIX})
+ endif(WITH_INTERNATIONAL)
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
endif()
@@ -1186,16 +1176,8 @@ elseif(WIN32)
add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
-
add_definitions(-DFREE_WINDOWS)
- if(WITH_INTERNATIONAL)
- set(GETTEXT ${LIBDIR}/gettext)
- set(GETTEXT_INCLUDE_DIRS ${GETTEXT}/include)
- set(GETTEXT_LIBPATH ${GETTEXT}/lib)
- set(GETTEXT_LIBRARIES intl)
- endif()
-
set(PNG "${LIBDIR}/png")
set(PNG_INCLUDE_DIR "${PNG}/include")
set(PNG_LIBPATH ${PNG}/lib) # not cmake defined
@@ -1313,6 +1295,11 @@ elseif(WIN32)
debug boost_date_time-${BOOST_DEBUG_POSTFIX} boost_filesystem-${BOOST_DEBUG_POSTFIX}
boost_regex-${BOOST_DEBUG_POSTFIX}
boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX})
+ if(WITH_INTERNATIONAL)
+ set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
+ optimized libboost_locale-${BOOST_POSTFIX}
+ debug libboost_locale-${BOOST_DEBUG_POSTFIX})
+ endif(WITH_CYCLES_OSL)
set(BOOST_LIBPATH ${BOOST}/lib)
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ")
endif()
@@ -1347,16 +1334,6 @@ elseif(APPLE)
set(WITH_LIBS10.5 ON CACHE BOOL "Use 10.5 libs" FORCE) # valid also for 10.6/10.7
endif()
- if(${XCODE_VERSION} VERSION_LESS 4.3)
- set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk CACHE PATH "" FORCE) # use guaranteed existing sdk
- else()
- # note: i don't use xcode-select path on purpose, cause also /Applications/Xcode.app would be allowed
- # absolute pathes are more foolproof here !
- set(OSX_SYSROOT_PREFIX /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform)
- set(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk
- set(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE)
- endif()
-
if(WITH_LIBS10.5)
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-9.x.universal)
else()
@@ -1379,10 +1356,13 @@ elseif(APPLE)
endif()
if(WITH_JACK)
- set(JACK /usr)
- set(JACK_INCLUDE_DIRS ${JACK}/include/jack)
- set(JACK_LIBRARIES jack)
- set(JACK_LIBPATH ${JACK}/lib)
+ find_library(JACK_FRAMEWORK
+ NAMES jackmp
+ )
+ set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers)
+ if(NOT JACK_FRAMEWORK)
+ set(WITH_JACK OFF)
+ endif()
endif()
if(WITH_CODEC_SNDFILE)
@@ -1420,13 +1400,6 @@ elseif(APPLE)
set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
endif()
- if(WITH_INTERNATIONAL)
- set(GETTEXT ${LIBDIR}/gettext)
- set(GETTEXT_INCLUDE_DIRS "${GETTEXT}/include")
- set(GETTEXT_LIBRARIES intl iconv)
- set(GETTEXT_LIBPATH ${GETTEXT}/lib)
- endif()
-
if(WITH_FFTW3)
set(FFTW3 ${LIBDIR}/fftw3)
set(FFTW3_INCLUDE_DIRS ${FFTW3}/include)
@@ -1493,18 +1466,22 @@ elseif(APPLE)
if(WITH_INPUT_NDOF)
# This thread it *should* work and check the framework - campbell
# http://www.cmake.org/pipermail/cmake/2005-December/007740.html
- find_library(3D_CONNEXION_CLIENT_LIBRARY
+ find_library(3DCONNEXION_CLIENT_FRAMEWORK
NAMES 3DconnexionClient
)
- if(NOT 3D_CONNEXION_CLIENT_LIBRARY)
+ if(NOT 3DCONNEXION_CLIENT_FRAMEWORK)
set(WITH_INPUT_NDOF OFF)
endif()
if(WITH_INPUT_NDOF)
- set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework 3DconnexionClient")
+ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework /Library/Frameworks/3DconnexionClient.framework/3DconnexionClient")
endif()
endif()
+ if(WITH_JACK)
+ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework jackmp")
+ endif()
+
else()
set(PLATFORM_CFLAGS "-pipe -funsigned-char")
set(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime")
@@ -1568,6 +1545,10 @@ 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)
+ if (WITH_INTERNATIONAL)
+ list(APPEND BOOST_LIBRARIES boost_locale-mt)
+ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -liconv") # boost_locale needs it !
+ endif()
set(BOOST_LIBPATH ${BOOST}/lib)
set(BOOST_DEFINITIONS)
endif()
@@ -1592,7 +1573,7 @@ elseif(APPLE)
set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
set(LLVM_VERSION "3.1" CACHE STRING "Version of LLVM to use")
set(LLVM_STATIC YES)
- if(LLVM_DIRECTORY)
+ if(EXISTS "${LLVM_DIRECTORY}/bin/llvm-config")
set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config")
else()
set(LLVM_CONFIG llvm-config)
@@ -1607,7 +1588,7 @@ elseif(APPLE)
OUTPUT_VARIABLE LLVM_LIB_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
find_library(LLVM_LIBRARY
- NAMES libLLVMAnalysis.a # first of a whole bunch of libs to get
+ NAMES LLVMAnalysis # first of a whole bunch of libs to get
PATHS ${LLVM_LIB_DIR})
message(STATUS "LLVM version = ${LLVM_VERSION}")
message(STATUS "LLVM dir = ${LLVM_DIRECTORY}")
@@ -1693,6 +1674,11 @@ if(WITH_CYCLES)
endif()
endif()
+if(WITH_INTERNATIONAL)
+ if(NOT WITH_BOOST)
+ message(FATAL_ERROR "Internationalization reqires WITH_BOOST, the library may not have been found. Configure BOOST or disable WITH_INTERNATIONAL")
+ endif()
+endif()
# See TEST_SSE_SUPPORT() for how this is defined.
diff --git a/SConstruct b/SConstruct
index 064ae0bc0b5..b7b27baae5a 100644
--- a/SConstruct
+++ b/SConstruct
@@ -819,10 +819,6 @@ else:
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
dllsources = []
- if not env['OURPLATFORM'] in ('win32-mingw', 'linuxcross'):
- # For MinGW and linuxcross static linking will be used
- dllsources += ['${LCGDIR}/gettext/lib/gnu_gettext.dll']
-
dllsources += ['${BF_ZLIB_LIBPATH}/zlib.dll']
# Used when linking to libtiff was dynamic
# keep it here until compilation on all platform would be ok
diff --git a/build_files/cmake/Modules/FindPythonLibsUnix.cmake b/build_files/cmake/Modules/FindPythonLibsUnix.cmake
index fdf2c29704d..7f272ee5b14 100644
--- a/build_files/cmake/Modules/FindPythonLibsUnix.cmake
+++ b/build_files/cmake/Modules/FindPythonLibsUnix.cmake
@@ -108,9 +108,10 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_
include/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS}
include/${CMAKE_LIBRARY_ARCHITECTURE}/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS}
)
- IF(NOT PYTHON_INCLUDE_CONFIG_DIR AND PYTHON_INCLUDE_DIR)
+ IF((NOT PYTHON_INCLUDE_CONFIG_DIR) AND PYTHON_INCLUDE_DIR)
# Fallback...
- SET(PYTHON_INCLUDE_CONFIG_DIR ${PYTHON_INCLUDE_DIR})
+ UNSET(PYTHON_INCLUDE_CONFIG_DIR CACHE)
+ SET(PYTHON_INCLUDE_CONFIG_DIR ${PYTHON_INCLUDE_DIR} CACHE PATH "")
ENDIF()
ENDIF()
@@ -134,8 +135,9 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_
PATH_SUFFIXES
lib64 lib
)
- IF(NOT PYTHON_LIBPATH AND PYTHON_LIBRARY)
+ IF((NOT PYTHON_LIBPATH) AND PYTHON_LIBRARY)
# Fallback...
+ UNSET(PYTHON_LIBPATH CACHE)
GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH)
ENDIF()
ENDIF()
@@ -177,7 +179,6 @@ INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibsUnix DEFAULT_MSG
PYTHON_LIBRARY PYTHON_LIBPATH PYTHON_INCLUDE_DIR PYTHON_INCLUDE_CONFIG_DIR)
-
IF(PYTHONLIBSUNIX_FOUND)
# Assign cache items
SET(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIR} ${PYTHON_INCLUDE_CONFIG_DIR})
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 3c321cc60be..2d9de5a5792 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -196,10 +196,6 @@ macro(SETUP_LIBDIRS)
if(WITH_PYTHON) # AND NOT WITH_PYTHON_MODULE # WIN32 needs
link_directories(${PYTHON_LIBPATH})
endif()
- if(WITH_INTERNATIONAL)
- link_directories(${ICONV_LIBPATH})
- link_directories(${GETTEXT_LIBPATH})
- endif()
if(WITH_SDL)
link_directories(${SDL_LIBPATH})
endif()
@@ -287,14 +283,6 @@ macro(setup_liblinks
target_link_libraries(${target} ${GLEW_LIBRARY})
endif()
- if(WITH_INTERNATIONAL)
- target_link_libraries(${target} ${GETTEXT_LIBRARIES})
-
- if(WIN32 AND NOT UNIX)
- target_link_libraries(${target} ${ICONV_LIBRARIES})
- endif()
- endif()
-
if(WITH_OPENAL)
target_link_libraries(${target} ${OPENAL_LIBRARY})
endif()
diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py
index afab4131de8..ea7d60a62eb 100644
--- a/build_files/scons/config/darwin-config.py
+++ b/build_files/scons/config/darwin-config.py
@@ -223,11 +223,6 @@ BF_ZLIB_LIB = 'z'
WITH_BF_INTERNATIONAL = True
-BF_GETTEXT = LIBDIR + '/gettext'
-BF_GETTEXT_INC = '${BF_GETTEXT}/include'
-BF_GETTEXT_LIB = 'intl'
-BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
-
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
@@ -297,6 +292,8 @@ 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'
+if WITH_BF_INTERNATIONAL:
+ BF_BOOST_LIB += ' boost_locale-mt'
BF_BOOST_LIBPATH = BF_BOOST + '/lib'
WITH_BF_CYCLES_CUDA_BINARIES = False
diff --git a/build_files/scons/config/freebsd7-config.py b/build_files/scons/config/freebsd7-config.py
index 412b08d895b..61358de12b4 100644
--- a/build_files/scons/config/freebsd7-config.py
+++ b/build_files/scons/config/freebsd7-config.py
@@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z'
WITH_BF_INTERNATIONAL = True
-BF_GETTEXT = '/usr/local'
-BF_GETTEXT_INC = '${BF_GETTEXT}/include'
-BF_GETTEXT_LIB = 'gettextlib'
-BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
-
WITH_BF_GAMEENGINE = False
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
diff --git a/build_files/scons/config/freebsd8-config.py b/build_files/scons/config/freebsd8-config.py
index ece86f799c3..0f6c7f64786 100644
--- a/build_files/scons/config/freebsd8-config.py
+++ b/build_files/scons/config/freebsd8-config.py
@@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z'
WITH_BF_INTERNATIONAL = True
-BF_GETTEXT = '/usr/local'
-BF_GETTEXT_INC = '${BF_GETTEXT}/include'
-BF_GETTEXT_LIB = 'gettextlib'
-BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
-
WITH_BF_GAMEENGINE = False
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
diff --git a/build_files/scons/config/freebsd9-config.py b/build_files/scons/config/freebsd9-config.py
index a31c6da90f0..c0df68f99ad 100644
--- a/build_files/scons/config/freebsd9-config.py
+++ b/build_files/scons/config/freebsd9-config.py
@@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z'
WITH_BF_INTERNATIONAL = True
-BF_GETTEXT = '/usr/local'
-BF_GETTEXT_INC = '${BF_GETTEXT}/include'
-BF_GETTEXT_LIB = 'gettextlib'
-BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
-
WITH_BF_GAMEENGINE = False
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py
index 45f6602e4dd..9bab4bc1dad 100644
--- a/build_files/scons/config/linux-config.py
+++ b/build_files/scons/config/linux-config.py
@@ -89,13 +89,6 @@ BF_ZLIB_LIB = 'z'
WITH_BF_INTERNATIONAL = True
-BF_GETTEXT = '/usr'
-BF_GETTEXT_INC = '${BF_GETTEXT}/include'
-BF_GETTEXT_LIB = 'gettextlib'
-BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
-#WITH_BF_GETTEXT_STATIC = True
-#BF_GETTEXT_LIB_STATIC = '${BF_GETTEXT}/lib/libgettextlib.a'
-
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
@@ -233,6 +226,8 @@ if not os.path.exists(LCGDIR + '/boost'):
BF_BOOST = '/usr'
BF_BOOST_INC = BF_BOOST + '/include'
BF_BOOST_LIB = 'boost_date_time boost_filesystem boost_regex boost_system boost_thread'
+if WITH_BF_INTERNATIONAL:
+ BF_BOOST_LIB += ' boost_locale'
BF_BOOST_LIBPATH = BF_BOOST + '/lib'
WITH_BF_CYCLES = WITH_BF_OIIO and WITH_BF_BOOST
diff --git a/build_files/scons/config/linuxcross-config.py b/build_files/scons/config/linuxcross-config.py
index 6866241793b..63264807720 100644
--- a/build_files/scons/config/linuxcross-config.py
+++ b/build_files/scons/config/linuxcross-config.py
@@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib'
WITH_BF_INTERNATIONAL = True
-BF_GETTEXT = LIBDIR + '/gcc/gettext'
-BF_GETTEXT_INC = '${BF_GETTEXT}/include'
-BF_GETTEXT_LIB = 'intl'
-BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
-
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = False
WITH_BF_OCEANSIM = True
diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py
index 0a72d87bb2a..768722fac32 100644
--- a/build_files/scons/config/win32-mingw-config.py
+++ b/build_files/scons/config/win32-mingw-config.py
@@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib'
WITH_BF_INTERNATIONAL = True
-BF_GETTEXT = LIBDIR + '/gettext'
-BF_GETTEXT_INC = '${BF_GETTEXT}/include'
-BF_GETTEXT_LIB = 'intl'
-BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
-
WITH_BF_OPENJPEG = True
BF_OPENJPEG = '#extern/libopenjpeg'
BF_OPENJPEG_LIB = ''
@@ -169,6 +164,8 @@ WITH_BF_BOOST = True
BF_BOOST = LIBDIR + '/boost'
BF_BOOST_INC = BF_BOOST + '/include'
BF_BOOST_LIB = 'boost_date_time-mgw46-mt-s-1_49 boost_filesystem-mgw46-mt-s-1_49 boost_regex-mgw46-mt-s-1_49 boost_system-mgw46-mt-s-1_49 boost_thread-mgw46-mt-s-1_49'
+if WITH_BF_INTERNATIONAL:
+ BF_BOOST_LIB += ' boost_locale-mgw46-mt-s-1_49'
BF_BOOST_LIBPATH = BF_BOOST + '/lib'
#Ray trace optimization
diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py
index b77ff8e70e0..c093fdb4a99 100644
--- a/build_files/scons/config/win32-vc-config.py
+++ b/build_files/scons/config/win32-vc-config.py
@@ -87,11 +87,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib'
WITH_BF_INTERNATIONAL = True
-BF_GETTEXT = LIBDIR + '/gettext'
-BF_GETTEXT_INC = '${BF_GETTEXT}/include'
-BF_GETTEXT_LIB = 'gnu_gettext'
-BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
-
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
@@ -171,6 +166,8 @@ 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'
+if WITH_BF_INTERNATIONAL:
+ BF_BOOST_LIB += ' libboost_locale-vc90-mt-s-1_49'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
#CUDA
diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py
index 838822bbbcb..bca3df16289 100644
--- a/build_files/scons/config/win64-mingw-config.py
+++ b/build_files/scons/config/win64-mingw-config.py
@@ -80,11 +80,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib'
WITH_BF_INTERNATIONAL = True
-BF_GETTEXT = LIBDIR + '/gettext'
-BF_GETTEXT_INC = '${BF_GETTEXT}/include'
-BF_GETTEXT_LIB = 'intl'
-BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
-
WITH_BF_OPENJPEG = True
BF_OPENJPEG = '#extern/libopenjpeg'
BF_OPENJPEG_LIB = ''
@@ -169,6 +164,8 @@ WITH_BF_BOOST = True
BF_BOOST = LIBDIR + '/boost'
BF_BOOST_INC = BF_BOOST + '/include'
BF_BOOST_LIB = 'boost_date_time-mgw47-mt-s-1_49 boost_date_time-mgw47-mt-sd-1_49 boost_filesystem-mgw47-mt-s-1_49 boost_filesystem-mgw47-mt-sd-1_49 boost_regex-mgw47-mt-s-1_49 boost_regex-mgw47-mt-sd-1_49 boost_system-mgw47-mt-s-1_49 boost_system-mgw47-mt-sd-1_49 boost_thread-mgw47-mt-s-1_49 boost_thread-mgw47-mt-sd-1_49'
+if WITH_BF_INTERNATIONAL:
+ BF_BOOST_LIB += ' boost_locale-mgw47-mt-s-1_49 boost_locale-mgw47-mt-sd-1_49'
BF_BOOST_LIBPATH = BF_BOOST + '/lib'
#Ray trace optimization
diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py
index 4b719469c39..9d3f42f7c7b 100644
--- a/build_files/scons/config/win64-vc-config.py
+++ b/build_files/scons/config/win64-vc-config.py
@@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib'
WITH_BF_INTERNATIONAL = True
-BF_GETTEXT = LIBDIR + '/gettext'
-BF_GETTEXT_INC = '${BF_GETTEXT}/include'
-BF_GETTEXT_LIB = 'gnu_gettext'
-BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
-
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
@@ -169,6 +164,8 @@ 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'
+if WITH_BF_INTERNATIONAL:
+ BF_BOOST_LIB += ' libboost_locale-vc90-mt-s-1_49'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
#CUDA
diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py
index 8443e7afb19..6baa96aae60 100644
--- a/build_files/scons/tools/Blender.py
+++ b/build_files/scons/tools/Blender.py
@@ -173,9 +173,6 @@ def setup_staticlibs(lenv):
if lenv['WITH_BF_FFMPEG'] and lenv['WITH_BF_STATICFFMPEG']:
statlibs += Split(lenv['BF_FFMPEG_LIB_STATIC'])
if lenv['WITH_BF_INTERNATIONAL']:
- libincs += Split(lenv['BF_GETTEXT_LIBPATH'])
- if lenv['WITH_BF_GETTEXT_STATIC']:
- statlibs += Split(lenv['BF_GETTEXT_LIB_STATIC'])
if lenv['WITH_BF_FREETYPE_STATIC']:
statlibs += Split(lenv['BF_FREETYPE_LIB_STATIC'])
if lenv['WITH_BF_OPENAL']:
@@ -252,8 +249,6 @@ def setup_syslibs(lenv):
syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
else:
syslibs.append(lenv['BF_PYTHON_LIB'])
- if lenv['WITH_BF_INTERNATIONAL'] and not lenv['WITH_BF_GETTEXT_STATIC']:
- syslibs += Split(lenv['BF_GETTEXT_LIB'])
if lenv['WITH_BF_OPENAL']:
if not lenv['WITH_BF_STATICOPENAL']:
syslibs += Split(lenv['BF_OPENAL_LIB'])
diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py
index 19652bb7851..90d3f578d98 100644
--- a/build_files/scons/tools/btools.py
+++ b/build_files/scons/tools/btools.py
@@ -116,7 +116,6 @@ 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',
- 'BF_GETTEXT', 'BF_GETTEXT_INC', 'BF_GETTEXT_LIB', 'WITH_BF_GETTEXT_STATIC', 'BF_GETTEXT_LIB_STATIC', 'BF_GETTEXT_LIBPATH',
'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',
@@ -381,15 +380,8 @@ def read_opts(env, cfg, args):
('BF_ZLIB_LIBPATH', 'ZLib library path', ''),
('BF_ZLIB_LIB_STATIC', 'ZLib static library', ''),
- (BoolVariable('WITH_BF_INTERNATIONAL', 'Use Gettext if true', True)),
+ (BoolVariable('WITH_BF_INTERNATIONAL', 'Use Boost::locale if true', True)),
- ('BF_GETTEXT', 'gettext base path', ''),
- ('BF_GETTEXT_INC', 'gettext include path', ''),
- ('BF_GETTEXT_LIB', 'gettext library', ''),
- (BoolVariable('WITH_BF_GETTEXT_STATIC', 'Use static gettext library if true', False)),
- ('BF_GETTEXT_LIB_STATIC', 'static gettext library', ''),
- ('BF_GETTEXT_LIBPATH', 'gettext library path', ''),
-
(BoolVariable('WITH_BF_ICONV', 'Use iconv if true', True)),
('BF_ICONV', 'iconv base path', ''),
('BF_ICONV_INC', 'iconv include path', ''),
diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst
index fdaeb61173f..7ce913a54f3 100644
--- a/doc/python_api/rst/bge.types.rst
+++ b/doc/python_api/rst/bge.types.rst
@@ -1957,6 +1957,28 @@ Types
: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:: transform_uv(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.
@@ -3113,6 +3135,12 @@ Types
: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.
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index cb2fc239859..be797c45ba1 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -65,6 +65,10 @@ if(WITH_CYCLES)
add_subdirectory(cycles)
endif()
+if(WITH_INTERNATIONAL)
+ add_subdirectory(locale)
+endif()
+
# only windows needs utf16 converter
if(WIN32)
add_subdirectory(utfconv)
diff --git a/intern/SConscript b/intern/SConscript
index 59e412333b0..5360ce4ea88 100644
--- a/intern/SConscript
+++ b/intern/SConscript
@@ -30,6 +30,9 @@ if env['WITH_BF_CYCLES']:
if env['WITH_BF_BOOLEAN']:
SConscript(['bsp/SConscript'])
+if env['WITH_BF_INTERNATIONAL']:
+ SConscript(['locale/SConscript'])
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'):
SConscript(['utfconv/SConscript'])
diff --git a/intern/container/CTR_HashedPtr.h b/intern/container/CTR_HashedPtr.h
index b7ac460f270..ee832eee153 100644
--- a/intern/container/CTR_HashedPtr.h
+++ b/intern/container/CTR_HashedPtr.h
@@ -46,13 +46,13 @@ class CTR_HashedPtr
void *m_valptr;
public:
CTR_HashedPtr(void *val) : m_valptr(val) {
- };
+ }
unsigned int hash() const {
return CTR_Hash(m_valptr);
- };
+ }
inline friend bool operator ==(const CTR_HashedPtr & rhs, const CTR_HashedPtr & lhs) {
return rhs.m_valptr == lhs.m_valptr;
- };
+ }
void *getValue() const {
return m_valptr;
}
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 7562ee0a0a5..7495a98aed1 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -44,10 +44,6 @@ if(WITH_CYCLES_OSL)
include_directories(${OSL_INCLUDES})
endif()
-if(WITH_CYCLES_PARTIO)
- add_definitions(-DWITH_PARTIO)
-endif()
-
if(WITH_CYCLES_CUDA_BINARIES)
add_definitions(-DWITH_CUDA_BINARIES)
endif()
@@ -69,7 +65,10 @@ if(WITH_CYCLES_BLENDER)
add_subdirectory(blender)
endif()
-add_subdirectory(app)
+if(WITH_CYCLES_TEST)
+ add_subdirectory(app)
+endif()
+
add_subdirectory(bvh)
add_subdirectory(device)
add_subdirectory(doc)
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index 83b3f731ffe..3fb8aaf934f 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -35,10 +35,6 @@ if(WITH_CYCLES_OSL)
list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES})
endif()
-if(WITH_CYCLES_PARTIO)
- list(APPEND LIBRARIES ${PARTIO_LIBRARIES})
-endif()
-
include_directories(${INC})
include_directories(SYSTEM ${INC_SYS})
diff --git a/intern/cycles/app/cycles_test.cpp b/intern/cycles/app/cycles_test.cpp
index e921cc46fe4..625e8cc1706 100644
--- a/intern/cycles/app/cycles_test.cpp
+++ b/intern/cycles/app/cycles_test.cpp
@@ -326,7 +326,7 @@ using namespace ccl;
int main(int argc, const char **argv)
{
- path_init("../build/bin/2.59/scripts/addons/cycles/");
+ path_init();
options_parse(argc, argv);
diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h
index 469d63d1530..b8a30b71717 100644
--- a/intern/cycles/blender/CCL_api.h
+++ b/intern/cycles/blender/CCL_api.h
@@ -23,12 +23,12 @@
extern "C" {
#endif
-/* returns a list of devices for selection, array is name NULL pointer
+/* returns a list of devices for selection, array is empty identifier
* terminated and must not be freed */
typedef struct CCLDeviceInfo {
- const char *identifier;
- const char *name;
+ char identifier[128];
+ char name[512];
int value;
} CCLDeviceInfo;
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 16697c08b2b..0fad2ac5618 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -48,7 +48,11 @@ class CyclesRender(bpy.types.RenderEngine):
# final render
def update(self, data, scene):
- engine.create(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):
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index e4f80cb4d5d..ca5cbee9325 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -61,6 +61,13 @@ def render(engine):
_cycles.render(engine.session)
+def reset(engine, data, scene):
+ import _cycles
+ data = data.as_pointer()
+ scene = scene.as_pointer()
+ _cycles.reset(engine.session, data, scene)
+
+
def update(engine, data, scene):
import _cycles
_cycles.sync(engine.session)
diff --git a/intern/cycles/blender/addon/enums.py b/intern/cycles/blender/addon/enums.py
index a98a6aab4c4..82b48973ca1 100644
--- a/intern/cycles/blender/addon/enums.py
+++ b/intern/cycles/blender/addon/enums.py
@@ -57,8 +57,7 @@ aperture_types = (
panorama_types = (
('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"),
- ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ignore the sensor dimensions"),
+ ('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 "
- "(for fulldomes use it with a square sensor ratio)"),
+ "Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 9cc58e65bef..4a651eb5aab 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -216,6 +216,10 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
sub.label(text="Viewport:")
sub.prop(cscene, "preview_start_resolution")
+ sub = col.column(align=True)
+ sub.label(text="Final Render:")
+ sub.prop(rd, "use_persistent_data", text="Persistent Images")
+
class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
bl_label = "Layers"
@@ -953,7 +957,7 @@ def draw_device(self, context):
elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL':
layout.prop(cscene, "device")
- if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'None'):
+ if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'):
layout.prop(cscene, "shading_system")
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index af16e210301..61fe7cf254d 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -56,10 +56,8 @@ struct BlenderCamera {
float sensor_width;
float sensor_height;
- float border_left;
- float border_right;
- float border_bottom;
- float border_top;
+ BoundBox2D border;
+ BoundBox2D pano_viewplane;
Transform matrix;
};
@@ -75,8 +73,10 @@ static void blender_camera_init(BlenderCamera *bcam)
bcam->sensor_height = 18.0f;
bcam->sensor_fit = BlenderCamera::AUTO;
bcam->shuttertime = 1.0f;
- bcam->border_right = 1.0f;
- bcam->border_top = 1.0f;
+ bcam->border.right = 1.0f;
+ bcam->border.top = 1.0f;
+ bcam->pano_viewplane.right = 1.0f;
+ bcam->pano_viewplane.top = 1.0f;
}
static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera)
@@ -199,7 +199,7 @@ static Transform blender_camera_matrix(const Transform& tfm, CameraType type)
}
static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height,
- float *left, float *right, float *bottom, float *top, float *aspectratio, float *sensor_size)
+ BoundBox2D *viewplane, float *aspectratio, float *sensor_size)
{
/* dimensions */
float xratio = width*bcam->pixelaspect.x;
@@ -244,32 +244,26 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height,
if(bcam->type == CAMERA_PANORAMA) {
/* set viewplane */
- *left = 0.0f;
- *right = 1.0f;
- *bottom = 0.0f;
- *top = 1.0f;
+ *viewplane = bcam->pano_viewplane;
}
else {
/* set viewplane */
- *left = -xaspect;
- *right = xaspect;
- *bottom = -yaspect;
- *top = yaspect;
+ viewplane->left = -xaspect;
+ viewplane->right = xaspect;
+ viewplane->bottom = -yaspect;
+ viewplane->top = yaspect;
/* zoom for 3d camera view */
- *left *= bcam->zoom;
- *right *= bcam->zoom;
- *bottom *= bcam->zoom;
- *top *= bcam->zoom;
+ *viewplane = (*viewplane) * bcam->zoom;
/* modify viewplane with camera shift and 3d camera view offset */
float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f);
float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f);
- *left += dx;
- *right += dx;
- *bottom += dy;
- *top += dy;
+ viewplane->left += dx;
+ viewplane->right += dx;
+ viewplane->bottom += dy;
+ viewplane->top += dy;
}
}
@@ -281,7 +275,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
/* viewplane */
blender_camera_viewplane(bcam, width, height,
- &cam->left, &cam->right, &cam->bottom, &cam->top, &aspectratio, &sensor_size);
+ &cam->viewplane, &aspectratio, &sensor_size);
/* sensor */
cam->sensorwidth = bcam->sensor_width;
@@ -314,10 +308,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
cam->shuttertime = bcam->shuttertime;
/* border */
- cam->border_left = bcam->border_left;
- cam->border_right = bcam->border_right;
- cam->border_bottom = bcam->border_bottom;
- cam->border_top = bcam->border_top;
+ cam->border = bcam->border;
/* set update flag */
if(cam->modified(prevcam))
@@ -340,10 +331,10 @@ void BlenderSync::sync_camera(BL::Object b_override, int width, int height)
/* 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();
+ 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();
}
/* camera object */
@@ -381,6 +372,9 @@ 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,
+ 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)
{
/* 3d view parameters */
@@ -396,14 +390,25 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL:
if(b_ob) {
blender_camera_from_object(bcam, b_ob, skip_panorama);
- /* magic zoom formula */
- bcam->zoom = (float)b_rv3d.view_camera_zoom();
- bcam->zoom = (1.41421f + bcam->zoom/50.0f);
- bcam->zoom *= bcam->zoom;
- bcam->zoom = 2.0f/bcam->zoom;
-
- /* offset */
- bcam->offset = get_float2(b_rv3d.view_camera_offset());
+ if(!skip_panorama && bcam->type == CAMERA_PANORAMA) {
+ /* in panorama camera view, we map viewplane to camera border */
+ BoundBox2D view_box, cam_box;
+
+ blender_camera_view_subset(b_scene, b_ob, b_v3d, b_rv3d, width, height,
+ &view_box, &cam_box);
+
+ bcam->pano_viewplane = view_box.make_relative_to(cam_box);
+ }
+ else {
+ /* magic zoom formula */
+ bcam->zoom = (float)b_rv3d.view_camera_zoom();
+ bcam->zoom = (1.41421f + bcam->zoom/50.0f);
+ bcam->zoom *= bcam->zoom;
+ bcam->zoom = 2.0f/bcam->zoom;
+
+ /* offset */
+ bcam->offset = get_float2(b_rv3d.view_camera_offset());
+ }
}
}
else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) {
@@ -427,6 +432,37 @@ 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,
+ BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box)
+{
+ BL::RenderSettings r = b_scene.render();
+ BoundBox2D cam, view;
+ float view_aspect, cam_aspect, sensor_size;
+
+ /* get viewport viewplane */
+ BlenderCamera view_bcam;
+ blender_camera_init(&view_bcam);
+ blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true);
+
+ blender_camera_viewplane(&view_bcam, width, height,
+ &view, &view_aspect, &sensor_size);
+
+ /* get camera viewplane */
+ BlenderCamera cam_bcam;
+ blender_camera_init(&cam_bcam);
+ blender_camera_from_object(&cam_bcam, b_ob, true);
+
+ width = (int)(r.resolution_x()*r.resolution_percentage()/100);
+ height = (int)(r.resolution_y()*r.resolution_percentage()/100);
+
+ blender_camera_viewplane(&cam_bcam, width, height,
+ &cam, &cam_aspect, &sensor_size);
+
+ /* return */
+ *view_box = view * (1.0f/view_aspect);
+ *cam_box = cam * (1.0f/cam_aspect);
+}
+
static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d,
BL::RegionView3D b_rv3d, int width, int height)
{
@@ -442,10 +478,10 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp
* assume viewport has got correctly clamped border already
*/
if(b_v3d.use_render_border()) {
- bcam->border_left = b_v3d.render_border_min_x();
- bcam->border_right = b_v3d.render_border_max_x();
- bcam->border_bottom = b_v3d.render_border_min_y();
- bcam->border_top = b_v3d.render_border_max_y();
+ bcam->border.left = b_v3d.render_border_min_x();
+ bcam->border.right = b_v3d.render_border_max_x();
+ bcam->border.bottom = b_v3d.render_border_min_y();
+ bcam->border.top = b_v3d.render_border_max_y();
return;
}
@@ -458,60 +494,20 @@ 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();
-
- float cam_left, cam_right, cam_bottom, cam_top;
- float view_left, view_right, view_bottom, view_top;
- float view_aspect, cam_aspect, sensor_size;
-
- /* get viewport viewplane */
- BlenderCamera view_bcam;
- blender_camera_init(&view_bcam);
- blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true);
-
- blender_camera_viewplane(&view_bcam, width, height,
- &view_left, &view_right, &view_bottom, &view_top, &view_aspect, &sensor_size);
-
- view_left /= view_aspect;
- view_right /= view_aspect;
- view_bottom /= view_aspect;
- view_top /= view_aspect;
+ 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();
- /* get camera viewplane */
- BlenderCamera cam_bcam;
- blender_camera_init(&cam_bcam);
- blender_camera_from_object(&cam_bcam, b_ob, true);
-
- width = (int)(r.resolution_x()*r.resolution_percentage()/100);
- height = (int)(r.resolution_y()*r.resolution_percentage()/100);
-
- blender_camera_viewplane(&cam_bcam, width, height,
- &cam_left, &cam_right, &cam_bottom, &cam_top, &cam_aspect, &sensor_size);
+ /* determine camera viewport subset */
+ BoundBox2D view_box, cam_box;
- cam_left /= cam_aspect;
- cam_right /= cam_aspect;
- cam_bottom /= cam_aspect;
- cam_top /= cam_aspect;
+ blender_camera_view_subset(b_scene, b_ob, b_v3d, b_rv3d, width, height,
+ &view_box, &cam_box);
/* determine viewport subset matching camera border */
- float tmp_left = ((cam_left - view_left) / (view_right - view_left));
- float tmp_right = ((cam_right - view_left) / (view_right - view_left));
- float tmp_bottom = ((cam_bottom - view_bottom) / (view_top - view_bottom));
- float tmp_top = ((cam_top - view_bottom) / (view_top - view_bottom));
-
- bcam->border_left = tmp_left + bcam->border_left*(tmp_right - tmp_left);
- bcam->border_right = tmp_left + bcam->border_right*(tmp_right - tmp_left);
- bcam->border_bottom = tmp_bottom + bcam->border_bottom*(tmp_top - tmp_bottom);
- bcam->border_top = tmp_bottom + bcam->border_top*(tmp_top - tmp_bottom);
-
- /* clamp */
- bcam->border_left = clamp(bcam->border_left, 0.0f, 1.0f);
- bcam->border_right = clamp(bcam->border_right, 0.0f, 1.0f);
- bcam->border_bottom = clamp(bcam->border_bottom, 0.0f, 1.0f);
- bcam->border_top = clamp(bcam->border_top, 0.0f, 1.0f);
+ cam_box = cam_box.make_relative_to(view_box);
+ bcam->border = cam_box.subset(bcam->border).clamp();
}
void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height)
@@ -539,10 +535,10 @@ BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, BL::SpaceView3D b
if(use_border) {
/* border render */
- params.full_x = cam->border_left*width;
- params.full_y = cam->border_bottom*height;
- params.width = (int)(cam->border_right*width) - params.full_x;
- params.height = (int)(cam->border_top*height) - params.full_y;
+ params.full_x = cam->border.left*width;
+ params.full_y = cam->border.bottom*height;
+ params.width = (int)(cam->border.right*width) - params.full_x;
+ params.height = (int)(cam->border.top*height) - params.full_y;
/* survive in case border goes out of view or becomes too small */
params.width = max(params.width, 1);
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 1b920249733..e8fa5c0ff3d 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -86,11 +86,11 @@ static uint object_ray_visibility(BL::Object b_ob)
/* Light */
-void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm)
+void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm)
{
/* test if we need to sync */
Light *light;
- ObjectKey key(b_parent, b_index, b_ob);
+ ObjectKey key(b_parent, persistent_id, b_ob);
if(!light_map.sync(&light, b_ob, b_parent, key))
return;
@@ -196,23 +196,24 @@ void BlenderSync::sync_background_light()
/* Object */
-void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, int particle_id)
+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)
{
BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
/* light is handled separately */
if(object_is_light(b_ob)) {
if(!motion)
- sync_light(b_parent, b_index, b_ob, tfm);
- return;
+ sync_light(b_parent, persistent_id, b_ob, tfm);
+
+ return NULL;
}
/* only interested in object that we can create meshes from */
if(!object_is_mesh(b_ob))
- return;
+ return NULL;
/* key to lookup object */
- ObjectKey key(b_parent, b_index, b_ob);
+ ObjectKey key(b_parent, persistent_id, b_ob);
Object *object;
/* motion vector case */
@@ -234,7 +235,7 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject
sync_mesh_motion(b_ob, object->mesh, motion);
}
- return;
+ return object;
}
/* test if we need to sync */
@@ -248,13 +249,15 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject
/* mesh sync */
object->mesh = sync_mesh(b_ob, object_updated);
+ /* sspecial case not tracked by object update flags */
if(use_holdout != object->use_holdout) {
object->use_holdout = use_holdout;
scene->object_manager->tag_update(scene);
+ object_updated = true;
}
- /* object sync */
- /* transform comparison should not be needed, but duplis don't work perfect
+ /* object sync
+ * transform comparison should not be needed, but duplis don't work perfect
* in the depsgraph and may not signal changes, so this is a workaround */
if(object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) {
object->name = b_ob.name().c_str();
@@ -264,7 +267,15 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject
object->motion.post = tfm;
object->use_motion = false;
- object->random_id = hash_int_2d(hash_string(object->name.c_str()), b_index);
+ /* random number */
+ object->random_id = hash_string(object->name.c_str());
+
+ if(persistent_id) {
+ for(int i = 0; i < OBJECT_PERSISTENT_ID_SIZE; i++)
+ object->random_id = hash_int_2d(object->random_id, persistent_id[i]);
+ }
+ else
+ object->random_id = hash_int_2d(object->random_id, 0);
/* visibility flags for both parent */
object->visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL;
@@ -273,6 +284,10 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject
object->random_id ^= hash_int(hash_string(b_parent.name().c_str()));
}
+ /* make holdout objects on excluded layer invisible for non-camera rays */
+ if(use_holdout && (layer_flag & render_layer.exclude_layer))
+ object->visibility &= ~(PATH_RAY_ALL - PATH_RAY_CAMERA);
+
/* camera flag is not actually used, instead is tested
* against render layer flags */
if(object->visibility & PATH_RAY_CAMERA) {
@@ -289,10 +304,10 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject
object->dupli_uv = make_float2(0.0f, 0.0f);
}
- object->particle_id = particle_id;
-
object->tag_update(scene);
}
+
+ return object;
}
/* Object Loop */
@@ -314,7 +329,9 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
/* object loop */
BL::Scene::objects_iterator b_ob;
BL::Scene b_sce = b_scene;
- int particle_offset = 1; /* first particle is dummy for regular, non-instanced objects */
+
+ /* global particle index counter */
+ int particle_id = 1;
bool cancel = false;
@@ -327,16 +344,14 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
if(!hide) {
progress.set_sync_status("Synchronizing object", (*b_ob).name());
- int num_particles = object_count_particles(*b_ob);
-
if(b_ob->is_duplicator()) {
- hide = true; /* duplicators hidden by default */
+ /* duplicators hidden by default */
+ hide = true;
/* dupli objects */
b_ob->dupli_list_create(b_scene, 2);
BL::Object::dupli_list_iterator b_dup;
- int b_index = 0;
for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
Transform tfm = get_transform(b_dup->matrix());
@@ -345,7 +360,8 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
bool emitter_hide = false;
if(b_dup_ob.is_duplicator()) {
- emitter_hide = true; /* duplicators hidden by default */
+ /* duplicators hidden by default */
+ emitter_hide = true;
/* check if we should render or hide particle emitter */
BL::Object::particle_systems_iterator b_psys;
@@ -355,21 +371,34 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
}
if(!(b_dup->hide() || dup_hide || emitter_hide)) {
- sync_object(*b_ob, b_index, *b_dup, tfm, ob_layer, motion, b_dup->particle_index() + particle_offset);
+ /* 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);
+
+ /* sync possible particle data, note particle_id
+ * starts counting at 1, first is dummy particle */
+ if(!motion && object && sync_dupli_particle(*b_ob, *b_dup, object)) {
+ if(particle_id != object->particle_id) {
+ object->particle_id = particle_id;
+ scene->object_manager->tag_update(scene);
+ }
+
+ particle_id++;
+ }
+
}
-
- ++b_index;
}
b_ob->dupli_list_clear();
}
- /* sync particles and check if we should render or hide particle emitter */
+ /* 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(!motion)
- sync_particles(*b_ob, *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;
}
@@ -377,10 +406,8 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
if(!hide) {
/* object itself */
Transform tfm = get_transform(b_ob->matrix_world());
- sync_object(*b_ob, 0, PointerRNA_NULL, tfm, ob_layer, motion, 0);
+ sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion);
}
-
- particle_offset += num_particles;
}
cancel = progress.get_cancel();
diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp
index c4c6d2f79a3..769cd9f532d 100644
--- a/intern/cycles/blender/blender_particles.cpp
+++ b/intern/cycles/blender/blender_particles.cpp
@@ -17,6 +17,7 @@
*/
#include "mesh.h"
+#include "object.h"
#include "particles.h"
#include "blender_sync.h"
@@ -28,170 +29,57 @@ CCL_NAMESPACE_BEGIN
/* Utilities */
-
-/* Particles Sync */
-
-bool BlenderSync::psys_need_update(BL::ParticleSystem b_psys)
-{
- /* Particle data is only needed for
- * a) Billboard render mode if object's own material uses particle info
- * b) object/group render mode if any dupli object's material uses particle info
- *
- * Note: Meshes have to be synced at this point!
- */
- bool need_update = false;
-
- switch (b_psys.settings().render_type()) {
- /* XXX not implemented yet!
- * billboards/strands would become part of the mesh data (?),
- * so the mesh attributes would store whether particle info is required.
- */
- #if 0
- case BL::ParticleSettings::render_type_BILLBOARD:
- case BL::ParticleSettings::render_type_PATH: { /* for strand rendering */
- BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob.data();
- Mesh *mesh = mesh_map.find(key);
- if(mesh) {
- need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update;
- }
- break;
- }
- #endif
-
- case BL::ParticleSettings::render_type_OBJECT: {
- BL::Object b_dupli_ob = b_psys.settings().dupli_object();
- if(b_dupli_ob) {
- BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data();
- Mesh *mesh = mesh_map.find(key);
- if(mesh) {
- need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update;
- }
- }
- break;
- }
-
- case BL::ParticleSettings::render_type_GROUP: {
- BL::Group b_dupli_group = b_psys.settings().dupli_group();
- if(b_dupli_group) {
- BL::Group::objects_iterator b_gob;
- for (b_dupli_group.objects.begin(b_gob); b_gob != b_dupli_group.objects.end(); ++b_gob) {
- BL::ID key = (BKE_object_is_modified(*b_gob))? *b_gob: b_gob->data();
- Mesh *mesh = mesh_map.find(key);
- if(mesh) {
- need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update;
- }
- }
- }
- break;
- }
-
- default:
- /* avoid compiler warning */
- break;
- }
-
- return need_update;
-}
-
-static bool use_particle_system(BL::ParticleSystem b_psys)
-{
- /* only use duplicator particles? disabled particle info for
- * halo and billboard to reduce particle count.
- * Probably not necessary since particles don't contain a huge amount
- * of data compared to other textures.
- */
- #if 0
- int render_type = b_psys->settings().render_type();
- return (render_type == BL::ParticleSettings::render_type_OBJECT
- || render_type == BL::ParticleSettings::render_type_GROUP);
- #endif
-
- return true;
-}
-
-static bool use_particle(BL::Particle b_pa, bool preview, bool show_unborn, bool use_dead)
-{
- return b_pa.is_exist() && (!preview || b_pa.is_visible()) &&
- (b_pa.alive_state() != BL::Particle::alive_state_UNBORN || show_unborn) &&
- (b_pa.alive_state() != BL::Particle::alive_state_DEAD || use_dead);
-}
-
-static int psys_count_particles(BL::ParticleSystem b_psys, bool preview)
+bool BlenderSync::sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object)
{
- BL::ParticleSystem::particles_iterator b_pa;
- bool show_unborn = b_psys.settings().show_unborn();
- bool use_dead = b_psys.settings().use_dead();
- int num = 0;
+ /* test if this dupli was generated from a particle sytem */
+ BL::ParticleSystem b_psys = b_dup.particle_system();
+ if(!b_psys)
+ return false;
- for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa)
- if(use_particle(*b_pa, preview, show_unborn, use_dead))
- ++num;
+ /* test if we need particle data */
+ if(!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE))
+ return false;
- return num;
-}
+ /* don't handle child particles yet */
+ BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup.persistent_id();
-int BlenderSync::object_count_particles(BL::Object b_ob)
-{
- BL::Object::particle_systems_iterator b_psys;
- int num = 0;
+ if(persistent_id[0] >= b_psys.particles.length())
+ return false;
- for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys)
- if(use_particle_system(*b_psys))
- num += psys_count_particles(*b_psys, preview);
+ /* find particle system */
+ ParticleSystemKey key(b_ob, persistent_id);
+ ParticleSystem *psys;
- return num;
-}
+ bool first_use = !particle_system_map.is_used(key);
+ bool need_update = particle_system_map.sync(&psys, b_ob, b_dup.object(), key);
-void BlenderSync::sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys)
-{
- /* depending on settings the psys may not even be rendered */
- if(!use_particle_system(b_psys))
- return;
-
- /* key to lookup particle system */
- ParticleSystemKey key(b_ob, b_psys);
- ParticleSystem *psys;
-
- /* test if we need to sync */
- bool object_updated = false;
-
- if(particle_system_map.sync(&psys, b_ob, b_ob, key))
- object_updated = true;
-
- bool need_update = psys_need_update(b_psys);
-
- if(object_updated || need_update) {
- bool show_unborn = b_psys.settings().show_unborn();
- bool use_dead = b_psys.settings().use_dead();
+ /* no update needed? */
+ if(!need_update && !object->mesh->need_update && !scene->object_manager->need_update)
+ return true;
- int num = psys_count_particles(b_psys, preview);
+ /* first time used in this sync loop? clear and tag update */
+ if(first_use) {
psys->particles.clear();
- psys->particles.reserve(num);
-
- BL::ParticleSystem::particles_iterator b_pa;
- int index = 0;
-
- for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) {
- if(use_particle(*b_pa, preview, show_unborn, use_dead)) {
- Particle pa;
-
- pa.index = index;
- pa.age = b_scene.frame_current() - b_pa->birth_time();
- pa.lifetime = b_pa->lifetime();
- pa.location = get_float3(b_pa->location());
- pa.rotation = get_float4(b_pa->rotation());
- pa.size = b_pa->size();
- pa.velocity = get_float3(b_pa->velocity());
- pa.angular_velocity = get_float3(b_pa->angular_velocity());
-
- psys->particles.push_back(pa);
- }
-
- ++index;
- }
-
psys->tag_update(scene);
}
+
+ /* add particle */
+ BL::Particle b_pa = b_psys.particles[persistent_id[0]];
+ Particle pa;
+
+ pa.index = persistent_id[0];
+ pa.age = b_scene.frame_current() - b_pa.birth_time();
+ pa.lifetime = b_pa.lifetime();
+ pa.location = get_float3(b_pa.location());
+ pa.rotation = get_float4(b_pa.rotation());
+ pa.size = b_pa.size();
+ pa.velocity = get_float3(b_pa.velocity());
+ pa.angular_velocity = get_float3(b_pa.angular_velocity());
+
+ psys->particles.push_back(pa);
+
+ /* return that this object has particle data */
+ return true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 3b78651a6a1..d164920ceff 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -146,6 +146,32 @@ static PyObject *draw_func(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
+static PyObject *reset_func(PyObject *self, PyObject *args)
+{
+ PyObject *pysession, *pydata, *pyscene;
+
+ if(!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pyscene))
+ return NULL;
+
+ BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
+
+ PointerRNA dataptr;
+ RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pydata), &dataptr);
+ BL::BlendData b_data(dataptr);
+
+ PointerRNA sceneptr;
+ RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr);
+ BL::Scene b_scene(sceneptr);
+
+ Py_BEGIN_ALLOW_THREADS
+
+ session->reset_session(b_data, b_scene);
+
+ Py_END_ALLOW_THREADS
+
+ Py_RETURN_NONE;
+}
+
static PyObject *sync_func(PyObject *self, PyObject *value)
{
Py_BEGIN_ALLOW_THREADS
@@ -258,6 +284,8 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
if(param->validdefault)
default_string = param->sdefault[0];
}
+ else
+ continue;
}
else
continue;
@@ -352,6 +380,7 @@ static PyMethodDef methods[] = {
{"render", render_func, METH_O, ""},
{"draw", draw_func, METH_VARARGS, ""},
{"sync", sync_func, METH_O, ""},
+ {"reset", reset_func, METH_VARARGS, ""},
#ifdef WITH_OSL
{"osl_update_node", osl_update_node_func, METH_VARARGS, ""},
{"osl_compile", osl_compile_func, METH_VARARGS, ""},
@@ -389,14 +418,23 @@ static CCLDeviceInfo *compute_device_list(DeviceType type)
if(info.type == type ||
(info.type == DEVICE_MULTI && info.multi_devices[0].type == type))
{
- CCLDeviceInfo cinfo = {info.id.c_str(), info.description.c_str(), i++};
+ CCLDeviceInfo cinfo;
+
+ strncpy(cinfo.identifier, info.id.c_str(), sizeof(cinfo.identifier));
+ cinfo.identifier[info.id.length()] = '\0';
+
+ strncpy(cinfo.name, info.description.c_str(), sizeof(cinfo.name));
+ cinfo.name[info.description.length()] = '\0';
+
+ cinfo.value = i++;
+
device_list.push_back(cinfo);
}
}
/* null terminate */
if(!device_list.empty()) {
- CCLDeviceInfo cinfo = {NULL, NULL, 0};
+ CCLDeviceInfo cinfo = {"", "", 0};
device_list.push_back(cinfo);
}
}
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 01bd5f013e3..ad43c39469c 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -109,9 +109,53 @@ void BlenderSession::create_session()
session->reset(buffer_params, session_params.samples);
}
+void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
+{
+ b_data = b_data_;
+ 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();
+
+ if(scene->params.modified(scene_params) ||
+ session->params.modified(session_params))
+ {
+ /* 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
+ */
+
+ delete session;
+
+ create_session();
+
+ return;
+ }
+
+ session->progress.reset();
+ scene->reset();
+
+ /* 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->sync_data(b_v3d, b_engine.camera_override());
+ sync->sync_camera(b_engine.camera_override(), width, height);
+
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height);
+ session->reset(buffer_params, session_params.samples);
+}
+
void BlenderSession::free_session()
{
- delete sync;
+ if(sync)
+ delete sync;
+
delete session;
}
@@ -304,6 +348,15 @@ void BlenderSession::render()
/* clear callback */
session->write_render_tile_cb = NULL;
session->update_render_tile_cb = NULL;
+
+ /* free all memory used (host and device), so we wouldn't leave render
+ * engine with extra memory allocated
+ */
+
+ session->device_free();
+
+ delete sync;
+ sync = NULL;
}
void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only)
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index d52e0103bbf..7f3973ae873 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -46,6 +46,8 @@ public:
void create_session();
void free_session();
+ void reset_session(BL::BlendData b_data, BL::Scene b_scene);
+
/* offline render */
void render();
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index c63f72c68c6..9ebdcfd04bd 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -241,6 +241,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
render_layer.use_localview = (b_v3d.local_view() ? true : false);
render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view(), render_layer.use_localview);
render_layer.layer = render_layer.scene_layer;
+ render_layer.exclude_layer = 0;
render_layer.holdout_layer = 0;
render_layer.material_override = PointerRNA_NULL;
render_layer.use_background = true;
@@ -258,10 +259,16 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) {
if((!layer && first_layer) || (layer && b_rlay->name() == layer)) {
render_layer.name = b_rlay->name();
- render_layer.scene_layer = get_layer(b_scene.layers()) & ~get_layer(b_rlay->layers_exclude());
- render_layer.layer = get_layer(b_rlay->layers());
+
render_layer.holdout_layer = get_layer(b_rlay->layers_zmask());
+ render_layer.exclude_layer = get_layer(b_rlay->layers_exclude());
+
+ render_layer.scene_layer = get_layer(b_scene.layers()) & ~render_layer.exclude_layer;
+ render_layer.scene_layer |= render_layer.exclude_layer & render_layer.holdout_layer;
+
+ render_layer.layer = get_layer(b_rlay->layers());
render_layer.layer |= render_layer.holdout_layer;
+
render_layer.material_override = b_rlay->material_override();
render_layer.use_background = b_rlay->use_sky();
render_layer.use_viewport_visibility = false;
@@ -277,6 +284,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
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");
@@ -294,6 +302,8 @@ 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;
+
return params;
}
@@ -379,7 +389,10 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use
params.start_resolution = get_int(cscene, "preview_start_resolution");
/* other parameters */
- params.threads = b_scene.render().threads();
+ if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED)
+ params.threads = b_scene.render().threads();
+ else
+ params.threads = 0;
params.cancel_timeout = get_float(cscene, "debug_cancel_timeout");
params.reset_timeout = get_float(cscene, "debug_reset_timeout");
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 36cd5e684a7..71781bc5459 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -42,6 +42,7 @@ class Film;
class Light;
class Mesh;
class Object;
+class ParticleSystem;
class Scene;
class Shader;
class ShaderGraph;
@@ -80,20 +81,20 @@ private:
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
Mesh *sync_mesh(BL::Object b_ob, bool object_updated);
- void sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion, int particle_id);
- void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm);
+ 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);
+ 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);
void sync_camera_motion(BL::Object b_ob, int motion);
- void sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys);
+
+ /* particles */
+ bool sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object);
/* util */
void find_shader(BL::ID id, vector<uint>& used_shaders, int default_shader);
bool BKE_object_is_modified(BL::Object b_ob);
bool object_is_mesh(BL::Object b_ob);
bool object_is_light(BL::Object b_ob);
- bool psys_need_update(BL::ParticleSystem b_psys);
- int object_count_particles(BL::Object b_ob);
/* variables */
BL::RenderEngine b_engine;
@@ -115,7 +116,8 @@ private:
struct RenderLayerInfo {
RenderLayerInfo()
- : scene_layer(0), layer(0), holdout_layer(0),
+ : scene_layer(0), layer(0),
+ holdout_layer(0), exclude_layer(0),
material_override(PointerRNA_NULL),
use_background(true),
use_viewport_visibility(false),
@@ -126,6 +128,7 @@ private:
uint scene_layer;
uint layer;
uint holdout_layer;
+ uint exclude_layer;
BL::Material material_override;
bool use_background;
bool use_viewport_visibility;
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index df1e99882b8..4feb8b556d5 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -284,6 +284,12 @@ public:
return recalc;
}
+ bool is_used(const K& key)
+ {
+ T *data = find(key);
+ return (data) ? used_set.find(data) != used_set.end() : false;
+ }
+
void used(T *data)
{
/* tag data as still in use */
@@ -343,27 +349,49 @@ protected:
/* Object Key */
+enum { OBJECT_PERSISTENT_ID_SIZE = 8 };
+
struct ObjectKey {
void *parent;
- int index;
+ int id[OBJECT_PERSISTENT_ID_SIZE];
void *ob;
- ObjectKey(void *parent_, int index_, void *ob_)
- : parent(parent_), index(index_), ob(ob_) {}
+ ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_)
+ : parent(parent_), ob(ob_)
+ {
+ if(id_)
+ memcpy(id, id_, sizeof(id));
+ else
+ memset(id, 0, sizeof(id));
+ }
bool operator<(const ObjectKey& k) const
- { return (parent < k.parent || (parent == k.parent && (index < k.index || (index == k.index && ob < k.ob)))); }
+ {
+ return (parent < k.parent) ||
+ (parent == k.parent && (memcmp(id, k.id, sizeof(id)) < 0)) ||
+ (memcmp(id, k.id, sizeof(id)) == 0 && ob < k.ob);
+ }
};
struct ParticleSystemKey {
void *ob;
- void *psys;
+ int id[OBJECT_PERSISTENT_ID_SIZE];
- ParticleSystemKey(void *ob_, void *psys_)
- : ob(ob_), psys(psys_) {}
+ ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE])
+ : ob(ob_)
+ {
+ if(id_)
+ memcpy(id, id_, sizeof(id));
+ else
+ memset(id, 0, sizeof(id));
+ }
bool operator<(const ParticleSystemKey& k) const
- { return (ob < k.ob && psys < k.psys); }
+ {
+ /* first id is particle index, we don't compare that */
+ return (ob < k.ob) ||
+ (ob == k.ob && (memcmp(id+1, k.id+1, sizeof(int)*(OBJECT_PERSISTENT_ID_SIZE-1)) < 0));
+ }
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake
index 332d3d74715..790049898ff 100644
--- a/intern/cycles/cmake/external_libs.cmake
+++ b/intern/cycles/cmake/external_libs.cmake
@@ -18,33 +18,6 @@ else()
endif()
###########################################################################
-# Partio
-
-if(WITH_CYCLES_PARTIO)
-
- set(CYCLES_PARTIO "" CACHE PATH "Path to Partio installation")
-
- message(STATUS "CYCLES_PARTIO = ${CYCLES_PARTIO}")
-
- find_library(PARTIO_LIBRARIES NAMES partio PATHS ${CYCLES_PARTIO}/lib)
- find_path(PARTIO_INCLUDES Partio.h ${CYCLES_PARTIO}/include)
-
- find_package(ZLIB)
-
- if(PARTIO_INCLUDES AND PARTIO_LIBRARIES AND ZLIB_LIBRARIES)
- list(APPEND PARTIO_LIBRARIES ${ZLIB_LIBRARIES})
- set(PARTIO_FOUND TRUE)
- message(STATUS "PARTIO includes = ${PARTIO_INCLUDES}")
- message(STATUS "PARTIO library = ${PARTIO_LIBRARIES}")
- else()
- message(STATUS "PARTIO not found")
- endif()
-
- include_directories(${PARTIO_INCLUDES})
-
-endif()
-
-###########################################################################
# CUDA
if(WITH_CYCLES_CUDA_BINARIES)
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 550da2982a3..c6a2c678bac 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -78,13 +78,13 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w
glDisable(GL_BLEND);
}
-Device *Device::create(DeviceInfo& info, Stats &stats, bool background, int threads)
+Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
{
Device *device;
switch(info.type) {
case DEVICE_CPU:
- device = device_cpu_create(info, stats, threads);
+ device = device_cpu_create(info, stats);
break;
#ifdef WITH_CUDA
case DEVICE_CUDA:
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 95da0a89833..9840687b76a 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -134,7 +134,7 @@ public:
virtual int device_number(Device *sub_device) { return 0; }
/* static */
- static Device *create(DeviceInfo& info, Stats &stats, bool background = true, int threads = 0);
+ static Device *create(DeviceInfo& info, Stats &stats, bool background = true);
static DeviceType type_from_string(const char *name);
static string string_from_type(DeviceType type);
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index 519c458ffdf..bc280616615 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -45,7 +45,7 @@ public:
TaskPool task_pool;
KernelGlobals *kg;
- CPUDevice(Stats &stats, int threads_num) : Device(stats)
+ CPUDevice(Stats &stats) : Device(stats)
{
kg = kernel_globals_create();
@@ -274,7 +274,7 @@ public:
/* split task into smaller ones, more than number of threads for uneven
* workloads where some parts of the image render slower than others */
list<DeviceTask> tasks;
- task.split(tasks, TaskScheduler::num_threads()+1);
+ task.split(tasks, TaskScheduler::num_threads());
foreach(DeviceTask& task, tasks)
task_pool.push(new CPUDeviceTask(this, task));
@@ -291,9 +291,9 @@ public:
}
};
-Device *device_cpu_create(DeviceInfo& info, Stats &stats, int threads)
+Device *device_cpu_create(DeviceInfo& info, Stats &stats)
{
- return new CPUDevice(stats, threads);
+ return new CPUDevice(stats);
}
void device_cpu_info(vector<DeviceInfo>& devices)
diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h
index 02fbac6860e..b49ebba3e8b 100644
--- a/intern/cycles/device/device_intern.h
+++ b/intern/cycles/device/device_intern.h
@@ -23,7 +23,7 @@ CCL_NAMESPACE_BEGIN
class Device;
-Device *device_cpu_create(DeviceInfo& info, Stats &stats, int threads);
+Device *device_cpu_create(DeviceInfo& info, Stats &stats);
Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background);
Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background);
Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address);
diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp
index c85e182d629..b3f02deaf6f 100644
--- a/intern/cycles/device/device_task.cpp
+++ b/intern/cycles/device/device_task.cpp
@@ -101,7 +101,7 @@ void DeviceTask::update_progress(RenderTile &rtile)
if(update_tile_sample) {
double current_time = time_dt();
- if (current_time - last_update_time >= 1.0f) {
+ if (current_time - last_update_time >= 1.0) {
update_tile_sample(rtile);
last_update_time = current_time;
diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h
index 64747bcb42e..6516b9e4d82 100644
--- a/intern/cycles/kernel/kernel_projection.h
+++ b/intern/cycles/kernel/kernel_projection.h
@@ -98,7 +98,7 @@ __device float3 fisheye_to_direction(float u, float v, float fov)
return make_float3(0.0f, 0.0f, 0.0f);
float phi = acosf((r != 0.0f)? u/r: 0.0f);
- float theta = asinf(r) * (fov / M_PI_F);
+ float theta = r * fov * 0.5f;
if(v < 0.0f) phi = -phi;
diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h
index 5d557ffcb07..80ced9dfd62 100644
--- a/intern/cycles/kernel/osl/osl_globals.h
+++ b/intern/cycles/kernel/osl/osl_globals.h
@@ -68,6 +68,11 @@ struct OSLGlobals {
};
static tls_ptr(ThreadData, thread_data);
+ static thread_mutex thread_data_mutex;
+ static volatile int thread_data_users;
+
+ void thread_data_init();
+ void thread_data_free();
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 0c8de058b5b..abf7c041cb3 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -32,9 +32,32 @@
CCL_NAMESPACE_BEGIN
tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data);
+volatile int OSLGlobals::thread_data_users = 0;
+thread_mutex OSLGlobals::thread_data_mutex;
/* Threads */
+void OSLGlobals::thread_data_init()
+{
+ thread_scoped_lock thread_data_lock(thread_data_mutex);
+
+ if(thread_data_users == 0)
+ tls_create(OSLGlobals::ThreadData, thread_data);
+
+ thread_data_users++;
+}
+
+void OSLGlobals::thread_data_free()
+{
+ /* thread local storage delete */
+ thread_scoped_lock thread_data_lock(thread_data_mutex);
+
+ thread_data_users--;
+
+ if(thread_data_users == 0)
+ tls_delete(OSLGlobals::ThreadData, thread_data);
+}
+
void OSLShader::thread_init(KernelGlobals *kg)
{
OSL::ShadingSystem *ss = kg->osl.ss;
diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl
index e238313509e..d101ee870b7 100644
--- a/intern/cycles/kernel/shaders/node_normal_map.osl
+++ b/intern/cycles/kernel/shaders/node_normal_map.osl
@@ -20,6 +20,7 @@
shader node_normal_map(
normal NormalIn = N,
+ float Strength = 1.0,
color Color = color(0.5, 0.5, 1.0),
string space = "Tangent",
string attr_name = "geom:tangent",
@@ -44,5 +45,8 @@ shader node_normal_map(
Normal = normalize(transform("object", "world", vector(mcolor)));
else if (space == "World")
Normal = normalize(vector(mcolor));
+
+ if (Strength != 1.0)
+ Normal = normalize(NormalIn + (Normal - NormalIn)*max(Strength, 0.0));
}
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index 68177493f4e..c4d03c1f948 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -34,7 +34,7 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack,
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.5), (data.x - 0.5), 0.0f);
+ 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)));;
}
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index a9449c0ded9..8ca7dff3970 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -227,12 +227,14 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa
__device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- uint color_offset, normal_offset, space;
- decode_node_uchar4(node.y, &color_offset, &normal_offset, &space, NULL);
+ uint color_offset, strength_offset, normal_offset, space;
+ decode_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &space);
float3 color = stack_load_float3(stack, color_offset);
color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
+ float3 N;
+
if(space == NODE_NORMAL_MAP_TANGENT) {
/* tangent space */
if(sd->object == ~0) {
@@ -257,19 +259,26 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac
tangent = cross(sd->N, normalize(cross(tangent, sd->N)));;
float3 B = sign * cross(sd->N, tangent);
- float3 N = color.x * tangent + color.y * B + color.z * sd->N;
-
- stack_store_float3(stack, normal_offset, normalize(N));
+ N = normalize(color.x * tangent + color.y * B + color.z * sd->N);
}
else {
/* object, world space */
- float3 N = color;
+ N = color;
if(space == NODE_NORMAL_MAP_OBJECT)
object_normal_transform(kg, sd, &N);
- stack_store_float3(stack, normal_offset, normalize(N));
+ N = normalize(N);
+ }
+
+ float strength = stack_load_float(stack, strength_offset);
+
+ if(strength != 1.0f) {
+ strength = max(strength, 0.0f);
+ N = normalize(sd->N + (N - sd->N)*strength);
}
+
+ stack_store_float3(stack, normal_offset, normalize(N));
}
__device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 649936bec04..308ebd0794a 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -55,15 +55,10 @@ Camera::Camera()
width = 1024;
height = 512;
- left = -((float)width/(float)height);
- right = (float)width/(float)height;
- bottom = -1.0f;
- top = 1.0f;
-
- border_left = 0.0f;
- border_right = 1.0f;
- border_bottom = 0.0f;
- border_top = 1.0f;
+ viewplane.left = -((float)width/(float)height);
+ viewplane.right = (float)width/(float)height;
+ viewplane.bottom = -1.0f;
+ viewplane.top = 1.0f;
screentoworld = transform_identity();
rastertoworld = transform_identity();
@@ -95,10 +90,11 @@ void Camera::update()
/* raster to screen */
Transform screentoraster = ndctoraster;
-
+
screentoraster = ndctoraster *
- transform_scale(1.0f/(right - left), 1.0f/(top - bottom), 1.0f) *
- transform_translate(-left, -bottom, 0.0f);
+ transform_scale(1.0f/(viewplane.right - viewplane.left),
+ 1.0f/(viewplane.top - viewplane.bottom), 1.0f) *
+ transform_translate(-viewplane.left, -viewplane.bottom, 0.0f);
Transform rastertoscreen = transform_inverse(screentoraster);
@@ -265,14 +261,8 @@ bool Camera::modified(const Camera& cam)
// modified for progressive render
// (width == cam.width) &&
// (height == cam.height) &&
- (left == cam.left) &&
- (right == cam.right) &&
- (bottom == cam.bottom) &&
- (top == cam.top) &&
- (border_left == cam.border_left) &&
- (border_right == cam.border_right) &&
- (border_bottom == cam.border_bottom) &&
- (border_top == cam.border_top) &&
+ (viewplane == cam.viewplane) &&
+ (border == cam.border) &&
(matrix == cam.matrix) &&
(panorama_type == cam.panorama_type) &&
(fisheye_fov == cam.fisheye_fov) &&
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 1407c86e7c2..4c2de7b50b8 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -21,6 +21,7 @@
#include "kernel_types.h"
+#include "util_boundbox.h"
#include "util_transform.h"
#include "util_types.h"
@@ -65,10 +66,10 @@ public:
/* screen */
int width, height;
- float left, right, bottom, top;
+ BoundBox2D viewplane;
/* border */
- float border_left, border_right, border_bottom, border_top;
+ BoundBox2D border;
/* transformation */
Transform matrix;
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index d77516a1b18..4173da453fd 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -147,6 +147,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
Mesh *mesh = object->mesh;
bool have_emission = false;
+ /* skip if we are not visible for BSDFs */
+ if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT)))
+ continue;
+
/* skip if we have no emission shaders */
foreach(uint sindex, mesh->used_shaders) {
Shader *shader = scene->shaders[sindex];
@@ -183,6 +187,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
Mesh *mesh = object->mesh;
bool have_emission = false;
+ /* skip if we are not visible for BSDFs */
+ if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT)))
+ continue;
+
/* skip if we have no emission shaders */
foreach(uint sindex, mesh->used_shaders) {
Shader *shader = scene->shaders[sindex];
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 4f50de11edf..82afab4dc1a 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -3032,7 +3032,9 @@ NormalMapNode::NormalMapNode()
attribute = ustring("");
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
+ add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
add_input("Color", SHADER_SOCKET_COLOR);
+
add_output("Normal", SHADER_SOCKET_NORMAL);
}
@@ -3055,6 +3057,7 @@ void NormalMapNode::attributes(AttributeRequestSet *attributes)
void NormalMapNode::compile(SVMCompiler& compiler)
{
ShaderInput *color_in = input("Color");
+ ShaderInput *strength_in = input("Strength");
ShaderOutput *normal_out = output("Normal");
int attr = 0, attr_sign = 0;
@@ -3070,11 +3073,13 @@ void NormalMapNode::compile(SVMCompiler& compiler)
}
compiler.stack_assign(color_in);
+ compiler.stack_assign(strength_in);
compiler.stack_assign(normal_out);
compiler.add_node(NODE_NORMAL_MAP,
compiler.encode_uchar4(
color_in->stack_offset,
+ strength_in->stack_offset,
normal_out->stack_offset,
space_enum[space]),
attr, attr_sign);
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 8bdb09eaf70..5fbc7932849 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -45,6 +45,8 @@ CCL_NAMESPACE_BEGIN
OSLShaderManager::OSLShaderManager()
{
+ thread_data_initialized = false;
+
services = new OSLRenderServices();
shading_system_init();
@@ -91,8 +93,6 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
og->background_state = og->surface_state[background_id & SHADER_MASK];
og->use = true;
- tls_create(OSLGlobals::ThreadData, og->thread_data);
-
foreach(Shader *shader, scene->shaders)
shader->need_update = false;
@@ -102,6 +102,11 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
scene->image_manager->set_osl_texture_system((void*)ts);
device_update_common(device, dscene, scene, progress);
+
+ if(!thread_data_initialized) {
+ og->thread_data_init();
+ thread_data_initialized = true;
+ }
}
void OSLShaderManager::device_free(Device *device, DeviceScene *dscene)
@@ -114,12 +119,15 @@ void OSLShaderManager::device_free(Device *device, DeviceScene *dscene)
og->use = false;
og->ss = NULL;
- tls_delete(OSLGlobals::ThreadData, og->thread_data);
-
og->surface_state.clear();
og->volume_state.clear();
og->displacement_state.clear();
og->background_state.reset();
+
+ if(thread_data_initialized) {
+ og->thread_data_free();
+ thread_data_initialized = false;
+ }
}
void OSLShaderManager::texture_system_init()
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index cee37c58d74..b4b3f59e02a 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -73,6 +73,8 @@ protected:
OSLRenderServices *services;
OSL::ErrorHandler errhandler;
set<string> loaded_shaders;
+
+ bool thread_data_initialized;
};
#endif
diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp
index 9f951d9673f..2a1570f7a0d 100644
--- a/intern/cycles/render/particles.cpp
+++ b/intern/cycles/render/particles.cpp
@@ -57,8 +57,7 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene
{
/* count particles.
* adds one dummy particle at the beginning to avoid invalid lookups,
- * in case a shader uses particle info without actual particle data.
- */
+ * in case a shader uses particle info without actual particle data. */
int num_particles = 1;
foreach(ParticleSystem *psys, scene->particle_systems)
num_particles += psys->particles.size();
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 15031b9500c..7834aa701ea 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -44,6 +44,10 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
device = NULL;
memset(&dscene.data, 0, sizeof(dscene.data));
+ /* OSL only works on the CPU */
+ if(device_info_.type != DEVICE_CPU)
+ params.shadingsystem = SceneParams::SVM;
+
camera = new Camera();
filter = new Filter();
film = new Film();
@@ -62,33 +66,11 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
Scene::~Scene()
{
- if(device) camera->device_free(device, &dscene);
- delete camera;
-
- if(device) filter->device_free(device, &dscene);
- delete filter;
-
- if(device) film->device_free(device, &dscene);
- delete film;
-
- if(device) background->device_free(device, &dscene);
- delete background;
-
- if(device) mesh_manager->device_free(device, &dscene);
- delete mesh_manager;
-
- if(device) object_manager->device_free(device, &dscene);
- delete object_manager;
-
- if(device) integrator->device_free(device, &dscene);
- delete integrator;
-
- if(device) shader_manager->device_free(device, &dscene);
- delete shader_manager;
-
- if(device) light_manager->device_free(device, &dscene);
- delete light_manager;
+ free_memory(true);
+}
+void Scene::free_memory(bool final)
+{
foreach(Shader *s, shaders)
delete s;
foreach(Mesh *m, meshes)
@@ -100,11 +82,44 @@ Scene::~Scene()
foreach(ParticleSystem *p, particle_systems)
delete p;
- if(device) image_manager->device_free(device, &dscene);
- delete image_manager;
-
- if(device) particle_system_manager->device_free(device, &dscene);
- delete particle_system_manager;
+ if(device) {
+ camera->device_free(device, &dscene);
+ filter->device_free(device, &dscene);
+ film->device_free(device, &dscene);
+ background->device_free(device, &dscene);
+ integrator->device_free(device, &dscene);
+
+ object_manager->device_free(device, &dscene);
+ mesh_manager->device_free(device, &dscene);
+ shader_manager->device_free(device, &dscene);
+ light_manager->device_free(device, &dscene);
+
+ particle_system_manager->device_free(device, &dscene);
+
+ if(!params.persistent_images || final)
+ image_manager->device_free(device, &dscene);
+ }
+
+ if(final) {
+ delete filter;
+ delete camera;
+ delete film;
+ delete background;
+ delete integrator;
+ delete object_manager;
+ delete mesh_manager;
+ delete shader_manager;
+ delete light_manager;
+ delete particle_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)
@@ -229,5 +244,22 @@ bool Scene::need_reset()
|| particle_system_manager->need_update);
}
+void Scene::reset()
+{
+ shader_manager->add_default(this);
+
+ /* ensure all objects are updated */
+ camera->tag_update();
+ filter->tag_update(this);
+ film->tag_update(this);
+ background->tag_update(this);
+ integrator->tag_update(this);
+}
+
+void Scene::device_free()
+{
+ free_memory(false);
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index bd45c1c04e6..92ef692b4b9 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -120,6 +120,7 @@ public:
bool use_bvh_cache;
bool use_bvh_spatial_split;
bool use_qbvh;
+ bool persistent_images;
SceneParams()
{
@@ -139,7 +140,8 @@ public:
&& bvh_type == params.bvh_type
&& use_bvh_cache == params.use_bvh_cache
&& use_bvh_spatial_split == params.use_bvh_spatial_split
- && use_qbvh == params.use_qbvh); }
+ && use_qbvh == params.use_qbvh
+ && persistent_images == params.persistent_images); }
};
/* Scene */
@@ -198,6 +200,12 @@ public:
bool need_update();
bool need_reset();
+
+ void reset();
+ void device_free();
+
+protected:
+ void free_memory(bool final);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 7303cb52ad8..41212c2db84 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -49,7 +49,7 @@ Session::Session(const SessionParams& params_)
TaskScheduler::init(params.threads);
- device = Device::create(params.device, stats, params.background, params.threads);
+ device = Device::create(params.device, stats, params.background);
if(params.background) {
buffers = NULL;
@@ -818,7 +818,7 @@ bool Session::update_progressive_refine(bool cancel)
double current_time = time_dt();
- if (current_time - last_update_time < 1.0f) {
+ if (current_time - last_update_time < 1.0) {
/* if last sample was processed, we need to write buffers anyway */
if (!write)
return false;
@@ -842,4 +842,18 @@ bool Session::update_progressive_refine(bool cancel)
return write;
}
+void Session::device_free()
+{
+ scene->device_free();
+
+ foreach(RenderBuffers *buffers, tile_buffers)
+ delete buffers;
+
+ tile_buffers.clear();
+
+ /* used from background render only, so no need to
+ * re-create render/display buffers here
+ */
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 7bb0cd1ae01..cfc1502287d 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -130,6 +130,7 @@ public:
void set_samples(int samples);
void set_pause(bool pause);
+ void device_free();
protected:
struct DelayedReset {
thread_mutex mutex;
diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h
index b35c4c12bb8..a0cdf1761ad 100644
--- a/intern/cycles/util/util_boundbox.h
+++ b/intern/cycles/util/util_boundbox.h
@@ -31,6 +31,8 @@ using namespace std;
CCL_NAMESPACE_BEGIN
+/* 3D BoundBox */
+
class BoundBox
{
public:
@@ -160,6 +162,75 @@ __forceinline BoundBox intersect(const BoundBox& a, const BoundBox& b, const Bou
return intersect(a, intersect(b, c));
}
+/* 2D BoundBox */
+
+class BoundBox2D {
+public:
+ float left;
+ float right;
+ float bottom;
+ float top;
+
+ BoundBox2D()
+ : left(0.0f), right(1.0f), bottom(0.0f), top(1.0f)
+ {
+ }
+
+ bool operator==(const BoundBox2D& other) const
+ {
+ return (left == other.left && right == other.right &&
+ bottom == other.bottom && top == other.top);
+ }
+
+ BoundBox2D operator*(float f) const
+ {
+ BoundBox2D result;
+
+ result.left = left*f;
+ result.right = right*f;
+ result.bottom = bottom*f;
+ result.top = top*f;
+
+ return result;
+ }
+
+ BoundBox2D subset(const BoundBox2D& other) const
+ {
+ BoundBox2D subset;
+
+ subset.left = left + other.left*(right - left);
+ subset.right = left + other.right*(right - left);
+ subset.bottom = bottom + other.bottom*(top - bottom);
+ subset.top = bottom + other.top*(top - bottom);
+
+ return subset;
+ }
+
+ BoundBox2D make_relative_to(const BoundBox2D& other) const
+ {
+ BoundBox2D result;
+
+ result.left = ((left - other.left) / (other.right - other.left));
+ result.right = ((right - other.left) / (other.right - other.left));
+ result.bottom = ((bottom - other.bottom) / (other.top - other.bottom));
+ result.top = ((top - other.bottom) / (other.top - other.bottom));
+
+ return result;
+ }
+
+ BoundBox2D clamp(float mn = 0.0f, float mx = 1.0f)
+ {
+ BoundBox2D result;
+
+ result.left = ccl::clamp(left, mn, mx);
+ result.right = ccl::clamp(right, mn, mx);
+ result.bottom = ccl::clamp(bottom, mn, mx);
+ result.top = ccl::clamp(top, mn, mx);
+
+ return result;
+ }
+};
+
CCL_NAMESPACE_END
#endif /* __UTIL_BOUNDBOX_H__ */
diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h
index c97379d8776..03e25d4d132 100644
--- a/intern/cycles/util/util_progress.h
+++ b/intern/cycles/util/util_progress.h
@@ -68,6 +68,21 @@ public:
return *this;
}
+ void reset()
+ {
+ tile = 0;
+ sample = 0;
+ start_time = time_dt();
+ total_time = 0.0f;
+ tile_time = 0.0f;
+ status = "Initializing";
+ substatus = "";
+ sync_status = "";
+ sync_substatus = "";
+ cancel = false;
+ cancel_message = "";
+ }
+
/* cancel */
void set_cancel(const string& cancel_message_)
{
diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h
index 405c81a1e1f..27638015f40 100644
--- a/intern/cycles/util/util_stats.h
+++ b/intern/cycles/util/util_stats.h
@@ -19,31 +19,22 @@
#ifndef __UTIL_STATS_H__
#define __UTIL_STATS_H__
-#include "util_thread.h"
-
CCL_NAMESPACE_BEGIN
class Stats {
public:
- Stats() : lock(), mem_used(0), mem_peak(0) {}
+ Stats() : mem_used(0), mem_peak(0) {}
void mem_alloc(size_t size) {
- lock.lock();
-
mem_used += size;
if(mem_used > mem_peak)
mem_peak = mem_used;
-
- lock.unlock();
}
void mem_free(size_t size) {
- lock.lock();
mem_used -= size;
- lock.unlock();
}
- spin_lock lock;
size_t mem_used;
size_t mem_peak;
};
diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp
index ea0abd6f54f..8c4ec312256 100644
--- a/intern/cycles/util/util_task.cpp
+++ b/intern/cycles/util/util_task.cpp
@@ -168,10 +168,16 @@ void TaskScheduler::init(int num_threads)
if(users == 0) {
do_exit = false;
- /* launch threads that will be waiting for work */
- if(num_threads == 0)
+ if(num_threads == 0) {
+ /* automatic number of threads will be main thread + num cores */
num_threads = system_cpu_thread_count();
+ }
+ else {
+ /* main thread will also work, for fixed threads we count it too */
+ num_threads -= 1;
+ }
+ /* launch threads that will be waiting for work */
threads.resize(num_threads);
thread_level.resize(num_threads);
diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h
index a2f284479c7..b795ca7524b 100644
--- a/intern/cycles/util/util_task.h
+++ b/intern/cycles/util/util_task.h
@@ -94,7 +94,10 @@ public:
static void init(int num_threads = 0);
static void exit();
- static int num_threads() { return threads.size(); }
+ /* number of threads that can work on tasks, main thread counts too */
+ static int num_threads() { return threads.size() + 1; }
+
+ /* test if any session is using the scheduler */
static bool active() { return users != 0; }
protected:
diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h
index 6d1bd0023a7..843764ca9d6 100644
--- a/intern/cycles/util/util_thread.h
+++ b/intern/cycles/util/util_thread.h
@@ -33,9 +33,6 @@ typedef boost::mutex thread_mutex;
typedef boost::mutex::scoped_lock thread_scoped_lock;
typedef boost::condition_variable thread_condition_variable;
-/* use boost for spinlocks as well */
-typedef boost::detail::spinlock spin_lock;
-
/* own pthread based implementation, to avoid boost version conflicts with
* dynamically loaded blender plugins */
diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp
index 70ee13d96d7..4eee024990f 100644
--- a/intern/cycles/util/util_transform.cpp
+++ b/intern/cycles/util/util_transform.cpp
@@ -251,6 +251,13 @@ void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *
transform_decompose(&decomp->pre, &motion->pre);
transform_decompose(&decomp->mid, mid);
transform_decompose(&decomp->post, &motion->post);
+
+ /* ensure rotation around shortest angle, negated quaternions are the same
+ * but this means we don't have to do the check in quat_interpolate */
+ if(dot(decomp->mid.x, decomp->post.x) < 0.0f)
+ decomp->mid.x = -decomp->mid.x;
+ if(dot(decomp->pre.x, decomp->mid.x) < 0.0f)
+ decomp->pre.x = -decomp->pre.x;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h
index df525542207..65162ebf4e6 100644
--- a/intern/cycles/util/util_transform.h
+++ b/intern/cycles/util/util_transform.h
@@ -39,16 +39,16 @@ typedef struct Transform {
#endif
} Transform;
+/* transform decomposed in rotation/translation/scale. we use the same data
+ * structure as Transform, and tightly pack decomposition into it. first the
+ * rotation (4), then translation (3), then 3x3 scale matrix (9) */
+
typedef struct MotionTransform {
Transform pre;
Transform mid;
Transform post;
} MotionTransform;
-/* transform decomposed in rotation/translation/scale. we use the same data
- * structure as Transform, and tightly pack decomposition into it. first the
- * rotation (4), then translation (3), then 3x3 scale matrix (9) */
-
/* Functions */
__device_inline float3 transform_perspective(const Transform *t, const float3 a)
@@ -303,13 +303,11 @@ __device_inline Transform transform_clear_scale(const Transform& tfm)
__device_inline float4 quat_interpolate(float4 q1, float4 q2, float t)
{
+ /* note: this does not ensure rotation around shortest angle, q1 and q2
+ * are assumed to be matched already in transform_motion_decompose */
float costheta = dot(q1, q2);
- /* rotate around shortest angle */
- if(costheta < 0.0f) {
- costheta = -costheta;
- q1 = -q1;
- }
+ /* possible optimization: it might be possible to precompute theta/qperp */
if(costheta > 0.9995f) {
/* linear interpolation in degenerate case */
@@ -318,14 +316,17 @@ __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t)
else {
/* slerp */
float theta = acosf(clamp(costheta, -1.0f, 1.0f));
- float thetap = theta * t;
float4 qperp = normalize(q2 - q1 * costheta);
+ float thetap = theta * t;
return q1 * cosf(thetap) + qperp * sinf(thetap);
}
}
__device_inline Transform transform_quick_inverse(Transform M)
{
+ /* possible optimization: can we avoid doing this altogether and construct
+ * the inverse matrix directly from negated translation, transposed rotation,
+ * scale can be inverted but what about shearing? */
Transform R;
float det = M.x.x*(M.z.z*M.y.y - M.z.y*M.y.z) - M.y.x*(M.z.z*M.x.y - M.z.y*M.x.z) + M.z.x*(M.y.z*M.x.y - M.y.y*M.x.z);
@@ -380,10 +381,17 @@ __device_inline void transform_compose(Transform *tfm, const Transform *decomp)
tfm->w = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
}
+/* Disabled for now, need arc-length parametrization for constant speed motion.
+ * #define CURVED_MOTION_INTERPOLATE */
+
__device void transform_motion_interpolate(Transform *tfm, const MotionTransform *motion, float t)
{
+ /* possible optimization: is it worth it adding a check to skip scaling?
+ * it's probably quite uncommon to have scaling objects. or can we skip
+ * just shearing perhaps? */
Transform decomp;
+#ifdef CURVED_MOTION_INTERPOLATE
/* 3 point bezier curve interpolation for position */
float3 Ppre = float4_to_float3(motion->pre.y);
float3 Pmid = float4_to_float3(motion->mid.y);
@@ -395,13 +403,18 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform
decomp.y.x = P.x;
decomp.y.y = P.y;
decomp.y.z = P.z;
+#endif
/* linear interpolation for rotation and scale */
if(t < 0.5f) {
t *= 2.0f;
decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t);
+#ifdef CURVED_MOTION_INTERPOLATE
decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w;
+#else
+ decomp.y = (1.0f - t)*motion->pre.y + t*motion->mid.y;
+#endif
decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z;
decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w;
}
@@ -409,7 +422,11 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform
t = (t - 0.5f)*2.0f;
decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t);
+#ifdef CURVED_MOTION_INTERPOLATE
decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w;
+#else
+ decomp.y = (1.0f - t)*motion->mid.y + t*motion->post.y;
+#endif
decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z;
decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w;
}
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index e52ac0af2ed..ea09987c564 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -189,7 +189,6 @@ elseif(APPLE)
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerCocoa.mm
-
intern/GHOST_NDOFManagerCocoa.h
)
endif()
diff --git a/intern/guardedalloc/cpp/mallocn.cpp b/intern/guardedalloc/cpp/mallocn.cpp
index da77f0e1c83..8b05d25018f 100644
--- a/intern/guardedalloc/cpp/mallocn.cpp
+++ b/intern/guardedalloc/cpp/mallocn.cpp
@@ -28,6 +28,9 @@
#include <new>
#include "../MEM_guardedalloc.h"
+void *operator new(size_t size, const char *str) throw(std::bad_alloc);
+void *operator new[](size_t size, const char *str) throw(std::bad_alloc);
+
/* not default but can be used when needing to set a string */
void *operator new(size_t size, const char *str) throw(std::bad_alloc)
{
diff --git a/intern/itasc/CMakeLists.txt b/intern/itasc/CMakeLists.txt
index 99c64d956cb..bc3ea0cf24c 100644
--- a/intern/itasc/CMakeLists.txt
+++ b/intern/itasc/CMakeLists.txt
@@ -22,7 +22,7 @@
# Contributor(s): Jacques Beaurain.
#
# ***** END GPL LICENSE BLOCK *****
-
+remove_strict_flags()
set(INC
)
diff --git a/intern/itasc/kdl/chain.hpp b/intern/itasc/kdl/chain.hpp
index 24e40858bff..fde9d4ed23e 100644
--- a/intern/itasc/kdl/chain.hpp
+++ b/intern/itasc/kdl/chain.hpp
@@ -35,11 +35,16 @@ namespace KDL {
*/
class Chain {
private:
-#if !defined(__APPLE__)
+#if defined(__APPLE__)
+# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5
+ std::vector<Segment> segments;
+# else
// Eigen allocator is needed for alignment of Eigen data types
std::vector<Segment, Eigen::aligned_allocator<Segment> > segments;
+# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */
#else
- std::vector<Segment> segments;
+ // Eigen allocator is needed for alignment of Eigen data types
+ std::vector<Segment, Eigen::aligned_allocator<Segment> > segments;
#endif
unsigned int nrOfJoints;
unsigned int nrOfSegments;
diff --git a/intern/itasc/kdl/tree.hpp b/intern/itasc/kdl/tree.hpp
index 4da764ac6d6..a020c6cf2cf 100644
--- a/intern/itasc/kdl/tree.hpp
+++ b/intern/itasc/kdl/tree.hpp
@@ -27,19 +27,30 @@
#include <string>
#include <map>
-#if !defined(__APPLE__)
-#include <Eigen/Core>
+#if defined(__APPLE__)
+# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5
+ //no include
+# else
+# include <Eigen/Core>
+# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */
+#else
+# include <Eigen/Core>
#endif
namespace KDL
{
//Forward declaration
class TreeElement;
-#if !defined(__APPLE__)
+#if defined(__APPLE__)
+# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5
+ typedef std::map<std::string,TreeElement> SegmentMap;
+# else
// Eigen allocator is needed for alignment of Eigen data types
typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<std::string, TreeElement> > > SegmentMap;
+# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */
#else
- typedef std::map<std::string,TreeElement> SegmentMap;
+ // Eigen allocator is needed for alignment of Eigen data types
+ typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<std::string, TreeElement> > > SegmentMap;
#endif
class TreeElement
{
diff --git a/intern/locale/CMakeLists.txt b/intern/locale/CMakeLists.txt
new file mode 100644
index 00000000000..f3356bcda49
--- /dev/null
+++ b/intern/locale/CMakeLists.txt
@@ -0,0 +1,44 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2012, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Bastien Montagne.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+)
+
+set(INC_SYS
+)
+
+set(SRC
+ boost_locale_wrapper.cpp
+)
+
+if(WITH_INTERNATIONAL)
+ list(APPEND INC_SYS
+ ${BOOST_INCLUDE_DIR}
+ )
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
+blender_add_lib(bf_intern_locale "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/locale/SConscript b/intern/locale/SConscript
new file mode 100644
index 00000000000..4a1357b76e4
--- /dev/null
+++ b/intern/locale/SConscript
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+Import('env')
+
+sources = env.Glob('*.cpp')
+
+incs = '.'
+defs = []
+
+if env['WITH_BF_INTERNATIONAL']:
+ defs.append('WITH_INTERNATIONAL')
+ incs += ' ' + env['BF_BOOST_INC']
+
+env.BlenderLib( 'bf_intern_locale', sources, Split(incs), defs, libtype=['extern','player'], priority=[10, 185])
diff --git a/intern/locale/boost_locale_wrapper.cpp b/intern/locale/boost_locale_wrapper.cpp
new file mode 100644
index 00000000000..ec2976f19b9
--- /dev/null
+++ b/intern/locale/boost_locale_wrapper.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) 2012, Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#include <boost/locale.hpp>
+
+#include "boost_locale_wrapper.h"
+
+static std::string messages_path;
+static std::string default_domain;
+
+void bl_locale_init(const char *_messages_path, const char *_default_domain)
+{
+ // Avoid using ICU backend, we do not need its power and it's rather heavy!
+ boost::locale::localization_backend_manager lman = boost::locale::localization_backend_manager::global();
+#if defined (_WIN32)
+ lman.select("winapi");
+#else
+ lman.select("posix");
+#endif
+ boost::locale::localization_backend_manager::global(lman);
+
+ messages_path = _messages_path;
+ default_domain = _default_domain;
+}
+
+void bl_locale_set(const char *locale)
+{
+ boost::locale::generator gen;
+ // Specify location of dictionaries.
+ gen.add_messages_path(messages_path);
+ gen.add_messages_domain(default_domain);
+ //gen.set_default_messages_domain(default_domain);
+
+ if (locale && locale[0]) {
+ std::locale::global(gen(locale));
+ }
+ else {
+ std::locale::global(gen(""));
+ }
+ // Note: boost always uses "C" LC_NUMERIC by default!
+}
+
+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
+ // once deleted (which happens as soons they are out of scope of this func).
+ typedef boost::locale::message_format<char> char_message_facet;
+ try {
+ std::locale l;
+ char_message_facet const &facet = std::use_facet<char_message_facet>(l);
+ char const *r = facet.get(0, msgctxt, msgid);
+ if(r)
+ return r;
+ return msgid;
+ }
+ catch(std::exception const &e) {
+// std::cout << "boost_locale_pgettext: " << e.what() << " \n";
+ return msgid;
+ }
+}
+
diff --git a/intern/locale/boost_locale_wrapper.h b/intern/locale/boost_locale_wrapper.h
new file mode 100644
index 00000000000..e7956d216f1
--- /dev/null
+++ b/intern/locale/boost_locale_wrapper.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) 2012, Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file locale/boost_locale_wrapper.h
+ * \ingroup locale
+ * A thin C wrapper around boost::locale...
+ */
+
+#ifndef __BOOST_LOCALE_WRAPPER_H__
+#define __BOOST_LOCALE_WRAPPER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BOOST_LOCALE_WRAPPER_H__ */
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index a8f4aa30e95..7747ef45c4d 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -174,11 +174,14 @@ class DATA_PT_geometry_curve(CurveButtonsPanel, Panel):
col.prop(curve, "bevel_object", text="")
col = layout.column(align=True)
- col.active = (curve.bevel_object is not None)
- col.prop(curve, "use_fill_caps")
col.prop(curve, "bevel_factor_start")
col.prop(curve, "bevel_factor_end")
+ row = col.row()
+ row.active = (curve.bevel_object is not None)
+ row.prop(curve, "use_fill_caps")
+ row.prop(curve, "use_map_taper")
+
class DATA_PT_pathanim(CurveButtonsPanelCurve, Panel):
bl_label = "Path Animation"
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 902358813df..ea8ffbe6c9f 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -625,6 +625,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "wrap_method", text="")
if md.wrap_method == 'PROJECT':
+ col.prop(md, "project_limit", text="Limit")
split = layout.split(percentage=0.25)
col = split.column()
@@ -642,8 +643,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.label(text="Cull Faces:")
col.prop(md, "cull_face", expand=True)
- layout.label(text="Auxiliary Target:")
- layout.prop(md, "auxiliary_target", text="")
+ layout.prop(md, "auxiliary_target")
elif md.wrap_method == 'NEAREST_SURFACEPOINT':
layout.prop(md, "use_keep_above_surface")
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 5302ad9b471..18eb8f8d9dd 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -684,7 +684,7 @@ class IMAGE_PT_paint(Panel, ImagePaintPanel):
if brush:
col = layout.column()
- col.template_color_wheel(brush, "color", value_slider=True)
+ col.template_color_picker(brush, "color", value_slider=True)
col.prop(brush, "color", text="")
row = col.row(align=True)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index cba45d4c2b7..ad4074d9744 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -31,21 +31,21 @@ def act_strip(context):
def draw_color_balance(layout, color_balance):
col = layout.column()
col.label(text="Lift:")
- col.template_color_wheel(color_balance, "lift", value_slider=True, cubic=True)
+ col.template_color_picker(color_balance, "lift", value_slider=True, cubic=True)
row = col.row()
row.prop(color_balance, "lift", text="")
row.prop(color_balance, "invert_lift", text="Inverse")
col = layout.column()
col.label(text="Gamma:")
- col.template_color_wheel(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True)
+ col.template_color_picker(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True)
row = col.row()
row.prop(color_balance, "gamma", text="")
row.prop(color_balance, "invert_gamma", text="Inverse")
col = layout.column()
col.label(text="Gain:")
- col.template_color_wheel(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True)
+ col.template_color_picker(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True)
row = col.row()
row.prop(color_balance, "gain", text="")
row.prop(color_balance, "invert_gain", text="Inverse")
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 455bf210ac2..1a66d67bce5 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -422,7 +422,7 @@ class USERPREF_PT_system(Panel):
col.separator()
col.separator()
- if hasattr(system, "compute_device"):
+ if hasattr(system, "compute_device_type"):
col.label(text="Compute Device:")
col.row().prop(system, "compute_device_type", expand=True)
sub = col.row()
@@ -446,6 +446,7 @@ class USERPREF_PT_system(Panel):
#~ col.prop(system, "use_antialiasing")
col.label(text="Window Draw Method:")
col.prop(system, "window_draw_method", text="")
+ col.prop(system, "multi_sample", text="")
col.label(text="Text Draw Options:")
col.prop(system, "use_text_antialiasing")
col.label(text="Textures:")
@@ -728,6 +729,29 @@ class USERPREF_PT_theme(Panel):
colsub = padding.column()
colsub.row().prop(ui, "header")
+ col.separator()
+ col.separator()
+
+ ui = theme.user_interface
+ col.label("Axis Colors:")
+
+ row = col.row()
+
+ subsplit = row.split(percentage=0.95)
+
+ padding = subsplit.split(percentage=0.15)
+ colsub = padding.column()
+ colsub = padding.column()
+ 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':
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 01e9e627f76..26d99b02729 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -168,6 +168,8 @@ class VIEW3D_MT_transform(VIEW3D_MT_transform_base):
# generic...
layout = self.layout
+ layout.operator("transform.shrink_fatten", text="Shrink Fatten")
+
layout.separator()
layout.operator("transform.translate", text="Move Texture Space").texture_space = True
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 9bb8255356c..91132a72b07 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -633,7 +633,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
elif context.image_paint_object and brush:
col = layout.column()
- col.template_color_wheel(brush, "color", value_slider=True)
+ col.template_color_picker(brush, "color", value_slider=True)
col.prop(brush, "color", text="")
row = col.row(align=True)
@@ -681,7 +681,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
# Vertex Paint Mode #
elif context.vertex_paint_object and brush:
col = layout.column()
- col.template_color_wheel(brush, "color", value_slider=True)
+ col.template_color_picker(brush, "color", value_slider=True)
col.prop(brush, "color", text="")
row = col.row(align=True)
diff --git a/source/blender/avi/intern/avi.c b/source/blender/avi/intern/avi.c
index e1732b0caae..d6301b723a7 100644
--- a/source/blender/avi/intern/avi.c
+++ b/source/blender/avi/intern/avi.c
@@ -665,13 +665,13 @@ AviError AVI_open_movie(const char *name, AviMovie *movie)
}
}
-/* Some AVI's have offset entries in absolute coordinates
- * instead of an offset from the movie beginning... this is...
- * wacky, but we need to handle it. The wacky offset always
- * starts at movi_offset it seems... so we'll check that.
- * Note the the offset needs an extra 4 bytes for some
- * undetermined reason */
-
+ /* Some AVI's have offset entries in absolute coordinates
+ * instead of an offset from the movie beginning... this is...
+ * wacky, but we need to handle it. The wacky offset always
+ * starts at movi_offset it seems... so we'll check that.
+ * Note the the offset needs an extra 4 bytes for some
+ * undetermined reason */
+
if (movie->entries[0].Offset == movie->movi_offset)
movie->read_offset = 4;
}
diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h
index b01ce93cb65..d0b5d824bb3 100644
--- a/source/blender/blenfont/BLF_translation.h
+++ b/source/blender/blenfont/BLF_translation.h
@@ -35,16 +35,6 @@
#define TEXT_DOMAIN_NAME "blender"
-/* blf_translation.c */
-
-#ifdef WITH_INTERNATIONAL
-unsigned char *BLF_get_unifont(int *unifont_size);
-void BLF_free_unifont(void);
-#endif
-
-const char *BLF_gettext(const char *msgid);
-const char *BLF_pgettext(const char *context, const char *message);
-
/* blf_lang.c */
/* Search the path directory to the locale files, this try all
@@ -61,17 +51,23 @@ void BLF_lang_set(const char *);
/* Get the current locale (short code, e.g. es_ES). */
const char *BLF_lang_get(void);
-/* Set the current encoding name. */
-void BLF_lang_encoding(const char *str);
-
/* 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
+
+const char *BLF_pgettext(const char *msgctxt, const char *msgid);
+
/* translation */
int BLF_translate_iface(void);
int BLF_translate_tooltips(void);
-const char *BLF_translate_do_iface(const char *contex, const char *msgid);
-const char *BLF_translate_do_tooltip(const char *contex, const char *msgid);
+const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid);
+const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid);
/* The "translation-marker" macro. */
diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt
index 022dfd282b0..90baef14a74 100644
--- a/source/blender/blenfont/CMakeLists.txt
+++ b/source/blender/blenfont/CMakeLists.txt
@@ -31,6 +31,7 @@ set(INC
../makesrna
../imbuf
../../../intern/guardedalloc
+ ../../../intern/locale
)
set(INC_SYS
@@ -54,9 +55,6 @@ set(SRC
)
if(WITH_INTERNATIONAL)
- list(APPEND INC_SYS
- ${GETTEXT_INCLUDE_DIRS}
- )
add_definitions(-DWITH_INTERNATIONAL)
endif()
diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript
index 075da58b116..c0591c877ef 100644
--- a/source/blender/blenfont/SConscript
+++ b/source/blender/blenfont/SConscript
@@ -4,11 +4,10 @@ Import ('env')
sources = env.Glob('intern/*.c')
-incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../blenloader'
+incs = '. intern #/intern/guardedalloc #/intern/locale ../blenkernel ../blenlib ../blenloader'
incs += ' ../makesdna ../makesrna ../imbuf ../editors/include'
incs += ' #/extern/glew/include'
incs += ' ' + env['BF_FREETYPE_INC']
-incs += ' ' + env['BF_GETTEXT_INC']
defs = ['GLEW_STATIC']
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index f3cc92e7a27..778b6c11e5a 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -28,7 +28,6 @@
* \ingroup blf
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c
index 501f8cd2958..0ed48623dd5 100644
--- a/source/blender/blenfont/intern/blf_lang.c
+++ b/source/blender/blenfont/intern/blf_lang.c
@@ -28,20 +28,17 @@
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "BKE_global.h"
-
-#include "BLF_api.h"
#include "BLF_translation.h" /* own include */
#ifdef WITH_INTERNATIONAL
-#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-#include "libintl.h"
+#include "boost_locale_wrapper.h"
+
+#include "BKE_global.h"
#include "DNA_userdef_types.h"
@@ -49,52 +46,33 @@
#include "MEM_guardedalloc.h"
-#include "BLI_string.h"
-#include "BLI_utildefines.h"
-#include "BLI_path_util.h"
#include "BLI_fileops.h"
#include "BLI_linklist.h"
+#include "BLI_path_util.h"
#include "BLI_string.h"
-
-#define SYSTEM_ENCODING_DEFAULT "UTF-8"
-#define FONT_SIZE_DEFAULT 12
+#include "BLI_utildefines.h"
/* Locale options. */
-static char global_messagepath[1024];
-static char global_language[32];
-static char global_encoding_name[32];
-
static const char **locales = NULL;
-static char **long_locales = NULL; /* XXX Temp fix until we get a final solution with modern intl lib under windows! */
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] : "")
-#define LONG_LOCALE(_id) (long_locales ? long_locales[_id] : "")
static void free_locales(void)
{
if (locales) {
int idx = num_locales_menu - 1; /* Last item does not need to be freed! */
while (idx--) {
- MEM_freeN((void*)locales_menu[idx].identifier);
- MEM_freeN((void*)locales_menu[idx].name);
- MEM_freeN((void*)locales_menu[idx].description); /* Also frees locales's relevant value! */
- }
-
- idx = num_locales;
- while (idx--) {
- if (long_locales[idx]) {
- MEM_freeN(long_locales[idx]);
- }
+ MEM_freeN((void *)locales_menu[idx].identifier);
+ MEM_freeN((void *)locales_menu[idx].name);
+ MEM_freeN((void *)locales_menu[idx].description); /* Also frees locales's relevant value! */
}
MEM_freeN(locales);
locales = NULL;
- MEM_freeN(long_locales);
- long_locales = NULL;
}
if (locales_menu) {
MEM_freeN(locales_menu);
@@ -140,7 +118,6 @@ static void fill_locales(void)
/* 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__);
- long_locales = MEM_callocN(num_locales * sizeof(char*), __func__);
while (line) {
int id;
char *loc, *sep1, *sep2, *sep3;
@@ -163,26 +140,28 @@ static void fill_locales(void)
sep2++;
sep3 = strchr(sep2, ':');
+
if (sep3) {
locales_menu[idx].identifier = loc = BLI_strdupn(sep2, sep3 - sep2);
+ }
+ else {
+ locales_menu[idx].identifier = loc = BLI_strdup(sep2);
+ }
- if (id == 0) {
- /* The DEFAULT item... */
- if (BLI_strnlen(loc, 2)) {
- locales[id] = locales_menu[idx].description = BLI_strdup("");
- long_locales[id] = BLI_strdup("");
- }
- /* Menu "label", not to be stored in locales! */
- else {
- locales_menu[idx].description = BLI_strdup("");
- }
+ if (id == 0) {
+ /* The DEFAULT item... */
+ if (BLI_strnlen(loc, 2)) {
+ locales[id] = locales_menu[idx].description = BLI_strdup("");
}
+ /* Menu "label", not to be stored in locales! */
else {
- locales[id] = locales_menu[idx].description = BLI_strdup(loc);
- long_locales[id] = BLI_strdup(sep3 + 1);
+ locales_menu[idx].description = BLI_strdup("");
}
- idx++;
}
+ else {
+ locales[id] = locales_menu[idx].description = BLI_strdup(loc);
+ }
+ idx++;
}
}
@@ -207,15 +186,12 @@ void BLF_lang_init(void)
{
char *messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale");
- BLI_strncpy(global_encoding_name, SYSTEM_ENCODING_DEFAULT, sizeof(global_encoding_name));
-
if (messagepath) {
- BLI_strncpy(global_messagepath, messagepath, sizeof(global_messagepath));
+ bl_locale_init(messagepath, TEXT_DOMAIN_NAME);
fill_locales();
}
else {
printf("%s: 'locale' data path for translations not found, continuing\n", __func__);
- global_messagepath[0] = '\0';
}
}
@@ -224,159 +200,37 @@ void BLF_lang_free(void)
free_locales();
}
-/* Get LANG/LANGUAGE environment variable. */
-static void get_language_variable(const char *varname, char *var, const size_t maxlen)
-{
- char *env = getenv(varname);
-
- if (env) {
- char *s;
-
- /* Store defaul locale. */
- BLI_strncpy(var, env, maxlen);
-
- /* Use first language as default. */
- s = strchr(var, ':');
- if (s)
- s[0] = 0;
- }
-}
-
-/* Get language to be used based on locale (which might be empty when using default language) and
- * LANG environment variable.
- */
-static void get_language(const char *locale, const char *lang, char *language, const size_t maxlen)
-{
- if (locale[0]) {
- BLI_strncpy(language, locale, maxlen);
- }
- else {
- char *s;
-
- BLI_strncpy(language, lang, maxlen);
-
- s = strchr(language, '.');
- if (s)
- s[0] = 0;
- }
-}
-
-/* XXX WARNING!!! In osx somehow the previous function call jumps in this one??? (ton, ppc) */
void BLF_lang_set(const char *str)
{
- char *locreturn;
- int ok = TRUE;
int ulang = ULANGUAGE;
+ const char *short_locale = str ? str : LOCALE(ulang);
+ const char *short_locale_utf8 = NULL;
if ((U.transopts & USER_DOTRANSLATE) == 0)
return;
-#if defined(_WIN32) && !defined(FREE_WINDOWS)
- {
- const char *long_locale = str ? str : LONG_LOCALE(ulang);
- if (long_locale) {
- char *envStr;
-
- if (ulang)
- envStr = BLI_sprintfN("LANG=%s", long_locale);
- else /* Use system setting. */
- envStr = BLI_sprintfN("LANG=%s", getenv("LANG"));
-
- gettext_putenv(envStr);
- MEM_freeN(envStr);
- }
-
- locreturn = setlocale(LC_ALL, long_locale);
-
- if (locreturn == NULL) {
- if (G.debug & G_DEBUG)
- printf("Could not change locale to %s\n", long_locale);
-
- ok = FALSE;
- }
- }
-#else
- {
- const char *short_locale = str ? str : LOCALE(ulang);
- static char default_lang[64] = "\0";
- static char default_language[64] = "\0";
-
- if (default_lang[0] == 0)
- get_language_variable("LANG", default_lang, sizeof(default_lang));
-
- if (default_language[0] == 0)
- get_language_variable("LANGUAGE", default_language, sizeof(default_language));
-
- if (short_locale[0]) {
- char *short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale);
-
- if (G.debug & G_DEBUG)
- printf("Setting LANG and LANGUAGE to %s\n", short_locale_utf8);
-
- locreturn = setlocale(LC_ALL, short_locale_utf8);
-
- if (locreturn != NULL) {
- BLI_setenv("LANG", short_locale_utf8);
- BLI_setenv("LANGUAGE", short_locale_utf8);
- }
- else {
- if (G.debug & G_DEBUG)
- printf("Setting LANG and LANGUAGE to %s\n", short_locale);
-
- locreturn = setlocale(LC_ALL, short_locale);
-
- if (locreturn != NULL) {
- BLI_setenv("LANG", short_locale);
- BLI_setenv("LANGUAGE", short_locale);
- }
- }
-
- if (G.debug & G_DEBUG && locreturn == NULL)
- printf("Could not change locale to %s nor %s\n", short_locale, short_locale_utf8);
-
- MEM_freeN(short_locale_utf8);
+ /* We want to avoid locales like '.UTF-8'! */
+ if (short_locale[0]) {
+ /* Hurrey! encoding needs to be placed *before* variant! */
+ char *variant = strchr(short_locale, '@');
+ if (variant) {
+ char *locale = BLI_strdupn(short_locale, variant - short_locale);
+ short_locale_utf8 = BLI_sprintfN("%s.UTF-8%s", locale, variant);
+ MEM_freeN(locale);
}
else {
- if (G.debug & G_DEBUG)
- printf("Setting LANG=%s and LANGUAGE=%s\n", default_lang, default_language);
-
- BLI_setenv("LANG", default_lang);
- BLI_setenv("LANGUAGE", default_language);
- locreturn = setlocale(LC_ALL, "");
-
- if (G.debug & G_DEBUG && locreturn == NULL)
- printf("Could not reset locale\n");
- }
-
- if (locreturn == NULL) {
- char language[65];
-
- get_language(short_locale, default_lang, language, sizeof(language));
-
- if (G.debug & G_DEBUG)
- printf("Fallback to LANG=%s and LANGUAGE=%s\n", default_lang, language);
-
- /* Fallback to default settings. */
- BLI_setenv("LANG", default_lang);
- BLI_setenv("LANGUAGE", language);
-
- locreturn = setlocale(LC_ALL, "");
-
- ok = FALSE;
+ short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale);
}
}
-#endif
-
- if (ok) {
- /*printf("Change locale to %s\n", locreturn ); */
- BLI_strncpy(global_language, locreturn, sizeof(global_language));
+ else {
+ short_locale_utf8 = short_locale;
}
- setlocale(LC_NUMERIC, "C");
+ bl_locale_set(short_locale_utf8);
- textdomain(TEXT_DOMAIN_NAME);
- bindtextdomain(TEXT_DOMAIN_NAME, global_messagepath);
- bind_textdomain_codeset(TEXT_DOMAIN_NAME, global_encoding_name);
+ if (short_locale[0]) {
+ MEM_freeN((void*)short_locale_utf8);
+ }
}
const char *BLF_lang_get(void)
@@ -385,12 +239,6 @@ const char *BLF_lang_get(void)
return LOCALE(uilang);
}
-void BLF_lang_encoding(const char *str)
-{
- BLI_strncpy(global_encoding_name, str, sizeof(global_encoding_name));
- /* bind_textdomain_codeset(TEXT_DOMAIN_NAME, encoding_name); */
-}
-
#undef LOCALE
#undef ULANGUAGE
@@ -406,12 +254,6 @@ void BLF_lang_free(void)
return;
}
-void BLF_lang_encoding(const char *str)
-{
- (void)str;
- return;
-}
-
void BLF_lang_set(const char *str)
{
(void)str;
diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blenfont/intern/blf_translation.c
index 9c863da9eba..5d4b631688a 100644
--- a/source/blender/blenfont/intern/blf_translation.c
+++ b/source/blender/blenfont/intern/blf_translation.c
@@ -31,18 +31,11 @@
#include <stdlib.h>
#include <string.h>
-#ifdef WITH_INTERNATIONAL
-#include <libintl.h>
-#include <locale.h>
-
-#define GETTEXT_CONTEXT_GLUE "\004"
+#include "BLF_translation.h"
-/* needed for windows version of gettext */
-#ifndef LC_MESSAGES
-# define LC_MESSAGES 1729
-#endif
+#ifdef WITH_INTERNATIONAL
-#endif
+#include "boost_locale_wrapper.h"
#include "MEM_guardedalloc.h"
@@ -52,11 +45,8 @@
#include "BLI_path_util.h"
#include "BLI_fileops.h"
-#include "BLF_translation.h"
-
#include "DNA_userdef_types.h" /* For user settings. */
-#ifdef WITH_INTERNATIONAL
static const char unifont_filename[] = "droidsans.ttf.gz";
static unsigned char *unifont_ttf = NULL;
static int unifont_size = 0;
@@ -90,55 +80,19 @@ void BLF_free_unifont(void)
#endif
-const char *BLF_gettext(const char *msgid)
+const char *BLF_pgettext(const char *msgctxt, const char *msgid)
{
#ifdef WITH_INTERNATIONAL
- if (msgid && msgid[0])
- return gettext(msgid);
+ if (msgid && msgid[0]) {
+ return bl_locale_pgettext(msgctxt, msgid);
+ }
return "";
#else
+ (void)msgctxt;
return msgid;
#endif
}
-const char *BLF_pgettext(const char *context, const char *message)
-{
-#ifdef WITH_INTERNATIONAL
- char static_msg_ctxt_id[1024];
- char *dynamic_msg_ctxt_id = NULL;
- char *msg_ctxt_id;
- const char *translation;
-
- size_t overall_length = strlen(context) + strlen(message) + sizeof(GETTEXT_CONTEXT_GLUE) + 1;
-
- if (!message || !context || !message[0])
- return "";
-
- if (overall_length > sizeof(static_msg_ctxt_id)) {
- dynamic_msg_ctxt_id = malloc(overall_length);
- msg_ctxt_id = dynamic_msg_ctxt_id;
- }
- else {
- msg_ctxt_id = static_msg_ctxt_id;
- }
-
- sprintf(msg_ctxt_id, "%s%s%s", context, GETTEXT_CONTEXT_GLUE, message);
-
- translation = (char *)dcgettext(TEXT_DOMAIN_NAME, msg_ctxt_id, LC_MESSAGES);
-
- if (dynamic_msg_ctxt_id)
- free(dynamic_msg_ctxt_id);
-
- if (translation == msg_ctxt_id)
- translation = message;
-
- return translation;
-#else
- (void)context;
- return message;
-#endif
-}
-
int BLF_translate_iface(void)
{
#ifdef WITH_INTERNATIONAL
@@ -157,36 +111,32 @@ int BLF_translate_tooltips(void)
#endif
}
-const char *BLF_translate_do_iface(const char *context, const char *msgid)
+const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid)
{
#ifdef WITH_INTERNATIONAL
if (BLF_translate_iface()) {
- if (context)
- return BLF_pgettext(context, msgid);
- else
- return BLF_gettext(msgid);
+ return BLF_pgettext(msgctxt, msgid);
}
- else
+ else {
return msgid;
+ }
#else
- (void)context;
+ (void)msgctxt;
return msgid;
#endif
}
-const char *BLF_translate_do_tooltip(const char *context, const char *msgid)
+const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid)
{
#ifdef WITH_INTERNATIONAL
if (BLF_translate_tooltips()) {
- if (context)
- return BLF_pgettext(context, msgid);
- else
- return BLF_gettext(msgid);
+ return BLF_pgettext(msgctxt, msgid);
}
- else
+ else {
return msgid;
+ }
#else
- (void)context;
+ (void)msgctxt;
return msgid;
#endif
}
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index e7033d8648d..3c210877de7 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 264
-#define BLENDER_SUBVERSION 8
+#define BLENDER_SUBVERSION 9
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 262
diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h
index 3acd4d1986e..244decf9d52 100644
--- a/source/blender/blenkernel/BKE_lamp.h
+++ b/source/blender/blenkernel/BKE_lamp.h
@@ -37,6 +37,7 @@ extern "C" {
#endif
struct Lamp;
+struct Scene;
struct Lamp *BKE_lamp_add(const char *name) WARN_UNUSED;
struct Lamp *BKE_lamp_copy(struct Lamp *la) WARN_UNUSED;
@@ -44,6 +45,8 @@ struct Lamp *localize_lamp(struct Lamp *la) WARN_UNUSED;
void BKE_lamp_make_local(struct Lamp *la);
void BKE_lamp_free(struct Lamp *la);
+void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 2f889084d0e..e53d0efffbd 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -283,9 +283,9 @@ typedef struct 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 create_vert_edge_map(MeshElemMap **map, int **mem,
- const struct MEdge *medge, int totvert, int totedge);
+ const struct MEdge *medge, int totvert, int totedge);
/* vertex level transformations & checks (no derived mesh) */
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 8fa20eb2cc2..bee2c374f27 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -48,7 +48,7 @@ struct Scene;
void multires_customdata_delete(struct Mesh *me);
void multires_set_tot_level(struct Object *ob,
- struct MultiresModifierData *mmd, int lvl);
+ struct MultiresModifierData *mmd, int lvl);
void multires_mark_as_modified(struct Object *ob, enum MultiresModifiedFlags flags);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index fd92b7b5d69..cca425a63d8 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -1680,8 +1680,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
nextmask &= ~CD_MASK_ORCO;
DM_set_only_copy(orcodm, nextmask | CD_MASK_ORIGINDEX |
- (mti->requiredDataMask ?
- mti->requiredDataMask(ob, md) : 0));
+ (mti->requiredDataMask ?
+ mti->requiredDataMask(ob, md) : 0));
ndm = mti->applyModifier(md, ob, orcodm, app_flags & ~MOD_APPLY_USECACHE);
if (ndm) {
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index dffe26bd782..f5c0660371b 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -76,8 +76,8 @@
/* --------------------- */
/* forward declarations */
-static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index,
- int level, short flag);
+static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4],
+ int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag);
/* ******************************************************************** */
/* Animation Visualization */
@@ -706,31 +706,45 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua
#define DUPLILIST_FOR_RENDER 2
#define DUPLILIST_ANIMATED 4
-static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, short flag)
+static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay,
+ int persistent_id[MAX_DUPLI_RECUR], int level, int index, int type, short flag)
{
DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject");
-
+ int i;
+
BLI_addtail(lb, dob);
dob->ob = ob;
copy_m4_m4(dob->mat, mat);
copy_m4_m4(dob->omat, ob->obmat);
dob->origlay = ob->lay;
- dob->index = index;
- dob->particle_index = par_index;
dob->type = type;
dob->animated = (type == OB_DUPLIGROUP) && (flag & DUPLILIST_ANIMATED);
ob->lay = lay;
+
+ /* set persistent id, which is an array with a persistent index for each level
+ * (particle number, vertex number, ..). by comparing this we can find the same
+ * dupli object between frames, which is needed for motion blur. last level
+ * goes first in the array. */
+ dob->persistent_id[0] = index;
+ for (i = 1; i < level; i++)
+ dob->persistent_id[i] = persistent_id[level - 1 - i];
+
+ /* metaballs never draw in duplis, they are instead merged into one by the basis
+ * mball outside of the group. this does mean that if that mball is not in the
+ * scene, they will not show up at all, limitation that should be solved once. */
+ if (ob->type == OB_MBALL)
+ dob->no_draw = TRUE;
return dob;
}
-static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index,
+static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR],
int level, short flag)
{
DupliObject *dob;
Group *group;
GroupObject *go;
- float mat[4][4], tmat[4][4];
+ float mat[4][4], tmat[4][4], id;
if (ob->dup_group == NULL) return;
group = ob->dup_group;
@@ -750,7 +764,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde
if (group_is_animated(ob, group))
flag |= DUPLILIST_ANIMATED;
- for (go = group->gobject.first; go; go = go->next) {
+ for (go = group->gobject.first, id = 0; go; go = go->next, id++) {
/* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
if (go->ob != ob) {
@@ -764,7 +778,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde
mult_m4_m4m4(mat, ob->obmat, go->ob->obmat);
}
- dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, par_index, OB_DUPLIGROUP, flag);
+ dob = new_dupli_object(lb, go->ob, mat, ob->lay, persistent_id, level, id, OB_DUPLIGROUP, flag);
/* check the group instance and object layers match, also that the object visible flags are ok. */
if ((dob->origlay & group->layer) == 0 ||
@@ -773,20 +787,17 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde
{
dob->no_draw = TRUE;
}
- else {
- dob->no_draw = FALSE;
- }
if (go->ob->transflag & OB_DUPLI) {
copy_m4_m4(dob->ob->obmat, dob->mat);
- object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, flag);
+ object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, persistent_id, level + 1, id, flag);
copy_m4_m4(dob->ob->obmat, dob->omat);
}
}
}
}
-static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, short flag)
+static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR], int level, short flag)
{
extern int enable_cu_speed; /* object.c */
Object copyob;
@@ -834,7 +845,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra);
- dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, par_index, OB_DUPLIFRAMES, flag);
+ dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, persistent_id, level, scene->r.cfra, OB_DUPLIFRAMES, flag);
copy_m4_m4(dob->omat, copyob.obmat);
}
}
@@ -865,7 +876,7 @@ typedef struct VertexDupliData {
Scene *scene;
Object *ob, *par;
float (*orco)[3];
- int par_index;
+ int *persistent_id;
} VertexDupliData;
/* ------------- */
@@ -902,7 +913,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
origlay = vdd->ob->lay;
- dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, vdd->par_index, OB_DUPLIVERTS, vdd->flag);
+ dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, vdd->persistent_id, vdd->level, index, OB_DUPLIVERTS, vdd->flag);
/* restore the original layer so that each dupli will have proper dob->origlay */
vdd->ob->lay = origlay;
@@ -914,12 +925,12 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
float tmpmat[4][4];
copy_m4_m4(tmpmat, vdd->ob->obmat);
copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
- object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->flag);
+ object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->persistent_id, vdd->level + 1, index, vdd->flag);
copy_m4_m4(vdd->ob->obmat, tmpmat);
}
}
-static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index,
+static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR],
int level, short flag)
{
Object *ob, *ob_iter;
@@ -1004,7 +1015,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
vdd.scene = scene;
vdd.par = par;
copy_m4_m4(vdd.pmat, pmat);
- vdd.par_index = par_index;
+ vdd.persistent_id = persistent_id;
/* mballs have a different dupli handling */
if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */
@@ -1043,7 +1054,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
dm->release(dm);
}
-static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index,
+static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR],
int level, short flag)
{
Object *ob, *ob_iter;
@@ -1186,7 +1197,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
copy_m4_m4(tmat, obmat);
mul_m4_m4m3(obmat, tmat, mat);
- dob = new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED));
+ dob = new_dupli_object(lb, ob, obmat, par->lay, persistent_id, level, a, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED));
if (flag & DUPLILIST_FOR_RENDER) {
w = 1.0f / (float)mp->totloop;
@@ -1209,7 +1220,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
float tmpmat[4][4];
copy_m4_m4(tmpmat, ob->obmat);
copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */
- object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, flag);
+ object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, persistent_id, level + 1, a, flag);
copy_m4_m4(ob->obmat, tmpmat);
}
}
@@ -1229,7 +1240,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
dm->release(dm);
}
-static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys,
+static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR], ParticleSystem *psys,
int level, short flag)
{
GroupObject *go;
@@ -1244,7 +1255,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
float ctime, pa_time, scale = 1.0f;
float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0;
float (*obmat)[4], (*oldobmat)[4];
- int a, b, counter, index, hair = 0;
+ int a, b, hair = 0;
int totpart, totchild, totgroup = 0 /*, pa_num */;
int no_draw_flag = PARS_UNEXIST;
@@ -1360,8 +1371,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
else
a = totpart;
- index = 0;
- for (pa = psys->particles, counter = 0; a < totpart + totchild; a++, pa++, counter++) {
+ for (pa = psys->particles; a < totpart + totchild; a++, pa++) {
if (a < totpart) {
/* handle parent particle */
if (pa->flag & no_draw_flag)
@@ -1456,7 +1466,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
else
copy_m4_m4(mat, tmat);
- dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, index, OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED));
+ dob = new_dupli_object(lb, go->ob, mat, par->lay, persistent_id, level, a, OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED));
+ dob->particle_system = psys;
copy_m4_m4(dob->omat, obcopylist[b].obmat);
if (flag & DUPLILIST_FOR_RENDER)
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
@@ -1516,14 +1527,12 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
if (part->draw & PART_DRAW_GLOBAL_OB)
add_v3_v3v3(mat[3], mat[3], vec);
- dob = new_dupli_object(lb, ob, mat, ob->lay, counter, index, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED));
+ dob = new_dupli_object(lb, ob, mat, ob->lay, persistent_id, level, a, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED));
+ dob->particle_system = psys;
copy_m4_m4(dob->omat, oldobmat);
if (flag & DUPLILIST_FOR_RENDER)
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
}
-
- /* only counts visible particles */
- index++;
}
/* restore objects since they were changed in BKE_object_where_is_calc_time */
@@ -1570,7 +1579,7 @@ static Object *find_family_object(Object **obar, char *family, char ch)
}
-static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, short flag)
+static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int persistent_id[MAX_DUPLI_RECUR], int level, short flag)
{
Object *ob, *obar[256] = {NULL};
Curve *cu;
@@ -1609,7 +1618,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde
copy_m4_m4(obmat, par->obmat);
copy_v3_v3(obmat[3], vec);
- new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIVERTS, flag);
+ new_dupli_object(lb, ob, obmat, par->lay, persistent_id, level, a, OB_DUPLIVERTS, flag);
}
}
@@ -1618,8 +1627,8 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde
/* ------------- */
-static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index,
- int level, short flag)
+static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4],
+ int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag)
{
if ((ob->transflag & OB_DUPLI) == 0)
return;
@@ -1636,34 +1645,45 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
}
}
+ /* keep track of persistent id */
+ if (level > 0)
+ persistent_id[level - 1] = index;
+
if (ob->transflag & OB_DUPLIPARTS) {
ParticleSystem *psys = ob->particlesystem.first;
- for (; psys; psys = psys->next)
- new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, flag);
+ int psysid = 0;
+
+ /* particle system take up one level in id, the particles another */
+ for (; psys; psys = psys->next, psysid++) {
+ persistent_id[level] = psysid;
+ new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, psys, level + 2, flag);
+ }
+
+ persistent_id[level] = 0;
}
else if (ob->transflag & OB_DUPLIVERTS) {
if (ob->type == OB_MESH) {
- vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag);
+ vertex_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, level + 1, flag);
}
else if (ob->type == OB_FONT) {
if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */
- font_duplilist(duplilist, scene, ob, par_index, level + 1, flag);
+ font_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag);
}
}
}
else if (ob->transflag & OB_DUPLIFACES) {
if (ob->type == OB_MESH)
- face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag);
+ face_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, level + 1, flag);
}
else if (ob->transflag & OB_DUPLIFRAMES) {
if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */
- frames_duplilist(duplilist, scene, ob, par_index, level + 1, flag);
+ frames_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag);
}
}
else if (ob->transflag & OB_DUPLIGROUP) {
DupliObject *dob;
- group_duplilist(duplilist, scene, ob, par_index, level + 1, flag); /* now recursive */
+ group_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag); /* now recursive */
if (level == 0) {
for (dob = duplilist->first; dob; dob = dob->next)
@@ -1671,6 +1691,10 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
copy_m4_m4(dob->ob->obmat, dob->mat);
}
}
+
+ /* clear persistent id */
+ if (level > 0)
+ persistent_id[level - 1] = 0;
}
/* Returns a list of DupliObject
@@ -1678,13 +1702,14 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update, int for_render)
{
ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist");
+ int persistent_id[MAX_DUPLI_RECUR] = {0};
int flag = 0;
if (update) flag |= DUPLILIST_DO_UPDATE;
if (for_render) flag |= DUPLILIST_FOR_RENDER;
duplilist->first = duplilist->last = NULL;
- object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, flag);
+ object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, persistent_id, 0, 0, flag);
return duplilist;
}
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 1aec4195354..9c94e267a7e 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -782,7 +782,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
ANIMDATA_NODETREE_IDS_CB(mainptr->tex.first, Tex);
/* lamps */
- ANIMDATA_IDS_CB(mainptr->lamp.first);
+ ANIMDATA_NODETREE_IDS_CB(mainptr->lamp.first, Lamp);
/* materials */
ANIMDATA_NODETREE_IDS_CB(mainptr->mat.first, Material);
@@ -824,7 +824,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
ANIMDATA_IDS_CB(mainptr->mask.first);
/* worlds */
- ANIMDATA_IDS_CB(mainptr->world.first);
+ ANIMDATA_NODETREE_IDS_CB(mainptr->world.first, World);
/* scenes */
ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene);
@@ -872,7 +872,7 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha
RENAMEFIX_ANIM_NODETREE_IDS(mainptr->tex.first, Tex);
/* lamps */
- RENAMEFIX_ANIM_IDS(mainptr->lamp.first);
+ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->lamp.first, Lamp);
/* materials */
RENAMEFIX_ANIM_NODETREE_IDS(mainptr->mat.first, Material);
@@ -914,7 +914,7 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha
RENAMEFIX_ANIM_IDS(mainptr->mask.first);
/* worlds */
- RENAMEFIX_ANIM_IDS(mainptr->world.first);
+ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->world.first, World);
/* linestyles */
RENAMEFIX_ANIM_IDS(mainptr->linestyle.first);
diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c
index df7fb2c1807..0495e729937 100644
--- a/source/blender/blenkernel/intern/bmfont.c
+++ b/source/blender/blenkernel/intern/bmfont.c
@@ -247,12 +247,13 @@ int locateGlyph(bmFont *bmfont, unsigned short unicode)
return(current);
}
-void matrixGlyph(ImBuf * ibuf, unsigned short unicode,
- float *centerx, float *centery,
- float *sizex, float *sizey,
- float *transx, float *transy,
- float *movex, float *movey,
- float *advance)
+void matrixGlyph(
+ ImBuf * ibuf, unsigned short unicode,
+ float *centerx, float *centery,
+ float *sizex, float *sizey,
+ float *transx, float *transy,
+ float *movex, float *movey,
+ float *advance)
{
int index;
bmFont *bmfont;
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 2e0b3a3c64a..3ade51d13eb 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -828,8 +828,6 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm,
mcol = DM_get_tessface_data_layer(dm, colType);
}
- printf("%s: %p(%d/%d)\n", __func__, mcol, CD_ID_MCOL, colType);
-
cdDM_update_normals_from_pbvh(dm);
/* back-buffer always uses legacy since VBO's would need the
@@ -1956,12 +1954,11 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
/* avoid this where possiblem, takes extra memory */
if (use_tessface) {
- int *polyindex;
BM_mesh_elem_index_ensure(bm, BM_FACE);
index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- for (i = 0; i < dm->numTessFaceData; i++, index++, polyindex++) {
+ for (i = 0; i < dm->numTessFaceData; i++, index++) {
MFace *mf = &mface[i];
const BMLoop **l = em_looptris[i];
efa = l[0]->f;
@@ -2257,6 +2254,11 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm)
* this is a really horribly written function. ger. - joeedh
*
* note, CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces.
+ *
+ * Note: This function is currently only used by the Mirror modifier, so it
+ * skips any faces that have all vertices merged (to avoid creating pairs
+ * of faces sharing the same set of vertices). If used elsewhere, it may
+ * be necessary to make this functionality optional.
*/
DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
{
@@ -2300,14 +2302,11 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
newv[i] = newv[vtargetmap[i]];
}
}
-
- /* find-replace merged vertices with target vertices */
- ml = cddm->mloop;
- for (i = 0; i < totloop; i++, ml++) {
- if (vtargetmap[ml->v] != -1) {
- ml->v = vtargetmap[ml->v];
- }
- }
+
+ /* Don't remap vertices in cddm->mloop, because we need to know the original
+ * indices in order to skip faces with all vertices merged.
+ * The "update loop indices..." section further down remaps vertices in mloop.
+ */
/* now go through and fix edges and faces */
med = cddm->medge;
@@ -2341,6 +2340,24 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
ml = cddm->mloop + mp->loopstart;
+ /* skip faces with all vertices merged */
+ {
+ int all_vertices_merged = TRUE;
+
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ if (vtargetmap[ml->v] == -1) {
+ all_vertices_merged = FALSE;
+ break;
+ }
+ }
+
+ if (UNLIKELY(all_vertices_merged)) {
+ continue;
+ }
+ }
+
+ ml = cddm->mloop + mp->loopstart;
+
c = 0;
for (j = 0; j < mp->totloop; j++, ml++) {
med = cddm->medge + ml->e;
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 67aaaceaa38..f2cd695d64a 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -1117,12 +1117,12 @@ void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float *
sumdiv += *fp;
}
if (sumdiv != 0.0f) if (sumdiv < 0.999f || sumdiv > 1.001f) {
- /* is normalizing needed? */
- fp = sum;
- for (i = istart; i <= iend; i++, fp++) {
- *fp /= sumdiv;
- }
+ /* is normalizing needed? */
+ fp = sum;
+ for (i = istart; i <= iend; i++, fp++) {
+ *fp /= sumdiv;
}
+ }
/* one! (1.0) real point */
fp = sum;
@@ -2481,8 +2481,8 @@ void BKE_curve_bevelList_make(Object *ob)
else
bevp2 = bevp1 + 1;
- inp = (bevp1->vec[0] - bevp0->vec[0]) * (bevp0->vec[1] - bevp2->vec[1]) +
- (bevp0->vec[1] - bevp1->vec[1]) * (bevp0->vec[0] - bevp2->vec[0]);
+ inp = ((bevp1->vec[0] - bevp0->vec[0]) * (bevp0->vec[1] - bevp2->vec[1]) +
+ (bevp0->vec[1] - bevp1->vec[1]) * (bevp0->vec[0] - bevp2->vec[0]));
if (inp > 0.0f)
sd->dir = 1;
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 44b3917df7f..9d3a7ec57cf 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -45,6 +45,7 @@
#include "DNA_anim_types.h"
#include "DNA_camera_types.h"
#include "DNA_group_types.h"
+#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
@@ -350,8 +351,8 @@ static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node
/* XXX: forward def for material driver handling... */
static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma);
-/* recursive handling for material nodetree drivers */
-static void dag_add_material_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree)
+/* recursive handling for shader nodetree drivers */
+static void dag_add_shader_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree)
{
bNode *n;
@@ -367,7 +368,7 @@ static void dag_add_material_nodetree_driver_relations(DagForest *dag, DagNode *
dag_add_material_driver_relations(dag, node, (Material *)n->id);
}
else if (n->type == NODE_GROUP) {
- dag_add_material_nodetree_driver_relations(dag, node, (bNodeTree *)n->id);
+ dag_add_shader_nodetree_driver_relations(dag, node, (bNodeTree *)n->id);
}
}
}
@@ -386,18 +387,41 @@ static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Mat
ma->id.flag |= LIB_DOIT;
/* material itself */
- if (ma->adt) {
+ if (ma->adt)
dag_add_driver_relation(ma->adt, dag, node, 1);
- }
/* textures */
// TODO...
//dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id);
/* material's nodetree */
- if (ma->nodetree) {
- dag_add_material_nodetree_driver_relations(dag, node, ma->nodetree);
- }
+ if (ma->nodetree)
+ dag_add_shader_nodetree_driver_relations(dag, node, ma->nodetree);
+}
+
+/* recursive handling for lamp drivers */
+static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *la)
+{
+ /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited
+ * already (see build_dag()). This assumes la->id.flag & LIB_DOIT isn't set by anything else
+ * in the meantime... [#32017]
+ */
+ if (la->id.flag & LIB_DOIT)
+ return;
+ else
+ la->id.flag |= LIB_DOIT;
+
+ /* lamp itself */
+ if (la->adt)
+ dag_add_driver_relation(la->adt, dag, node, 1);
+
+ /* textures */
+ // TODO...
+ //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id);
+
+ /* lamp's nodetree */
+ if (la->nodetree)
+ 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)
@@ -647,6 +671,8 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
}
}
}
+ else if(ob->type == OB_LAMP)
+ dag_add_lamp_driver_relations(dag, node, ob->data);
/* particles */
psys = ob->particlesystem.first;
@@ -817,6 +843,7 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask)
/* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later [#32017] */
tag_main_idcode(bmain, ID_MA, FALSE);
+ tag_main_idcode(bmain, ID_LA, FALSE);
/* add base node for scene. scene is always the first node in DAG */
scenenode = dag_add_node(dag, sce);
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index e13d05d0a2f..a78a9af54ae 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -630,7 +630,7 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis
* - first point left, last point right
* - based on subdivided points in original curve, not on points in taper curve (still)
*/
-float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
+static float displist_calc_taper(Scene *scene, Object *taperobj, float fac)
{
DispList *dl;
@@ -643,7 +643,6 @@ float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
dl = taperobj->disp.first;
}
if (dl) {
- float fac = ((float)cur) / (float)(tot - 1);
float minx, dx, *fp;
int a;
@@ -671,6 +670,13 @@ float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
return 1.0;
}
+float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
+{
+ float fac = ((float)cur) / (float)(tot - 1);
+
+ return displist_calc_taper(scene, taperobj, fac);
+}
+
void BKE_displist_make_mball(Scene *scene, Object *ob)
{
if (!ob || ob->type != OB_MBALL)
@@ -1240,7 +1246,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
}
}
-static void rotateBevelPiece(Curve *cu, BevPoint *bevp, DispList *dlb, float widfac, float fac, float **data_r)
+static void rotateBevelPiece(Curve *cu, BevPoint *bevp, BevPoint *nbevp, DispList *dlb, float bev_blend, float widfac, float fac, float **data_r)
{
float *fp, *data = *data_r;
int b;
@@ -1248,22 +1254,48 @@ static void rotateBevelPiece(Curve *cu, BevPoint *bevp, DispList *dlb, float wid
fp = dlb->verts;
for (b = 0; b < dlb->nr; b++, fp += 3, data += 3) {
if (cu->flag & CU_3D) {
- float vec[3];
+ float vec[3], quat[4];
vec[0] = fp[1] + widfac;
vec[1] = fp[2];
vec[2] = 0.0;
- mul_qt_v3(bevp->quat, vec);
+ if (nbevp == NULL) {
+ copy_v3_v3(data, bevp->vec);
+ copy_qt_qt(quat, bevp->quat);
+ }
+ else {
+ interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend);
+ interp_qt_qtqt(quat, bevp->quat, nbevp->quat, bev_blend);
+ }
+
+ mul_qt_v3(quat, vec);
- data[0] = bevp->vec[0] + fac * vec[0];
- data[1] = bevp->vec[1] + fac * vec[1];
- data[2] = bevp->vec[2] + fac * vec[2];
+ data[0] += fac * vec[0];
+ data[1] += fac * vec[1];
+ data[2] += fac * vec[2];
}
else {
- data[0] = bevp->vec[0] + fac * (widfac + fp[1]) * bevp->sina;
- data[1] = bevp->vec[1] + fac * (widfac + fp[1]) * bevp->cosa;
- data[2] = bevp->vec[2] + fac * fp[2];
+ float sina, cosa;
+
+ if (nbevp == NULL) {
+ copy_v3_v3(data, bevp->vec);
+ sina = bevp->sina;
+ cosa = bevp->cosa;
+ }
+ else {
+ interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend);
+
+ /* perhaps we need to interpolate angles instead. but the thing is
+ * cosa and sina are not actually sine and cosine
+ */
+ sina = nbevp->sina * bev_blend + bevp->sina * (1.0f - bev_blend);
+ cosa = nbevp->cosa * bev_blend + bevp->cosa * (1.0f - bev_blend);
+ }
+
+ data[0] += fac * (widfac + fp[1]) * sina;
+ data[1] += fac * (widfac + fp[1]) * cosa;
+ data[2] += fac * fp[2];
}
}
@@ -1399,8 +1431,8 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
firstblend = 1.0f - (bevfac1 * (bl->nr - 1) - (int)(bevfac1 * (bl->nr - 1)));
lastblend = bevfac2 * (bl->nr - 1) - (int)(bevfac2 * (bl->nr - 1));
- if (steps > bl->nr) {
- steps = bl->nr;
+ if (start + steps > bl->nr) {
+ steps = bl->nr - start;
lastblend = 1.0f;
}
@@ -1438,7 +1470,29 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
fac = bevp->radius;
}
else {
- fac = BKE_displist_calc_taper(scene, cu->taperobj, i, bl->nr);
+ float len, taper_fac;
+
+ if (cu->flag & CU_MAP_TAPER) {
+ len = (steps - 3) + firstblend + lastblend;
+
+ if (a == 0)
+ taper_fac = 0.0f;
+ else if (a == steps - 1)
+ taper_fac = 1.0f;
+ else
+ taper_fac = ((float) a - (1.0f - firstblend)) / len;
+ }
+ else {
+ len = bl->nr - 1;
+ taper_fac = (float) i / len;
+
+ if (a == 0)
+ taper_fac += (1.0f - firstblend) / len;
+ else if (a == steps - 1)
+ taper_fac -= (1.0f - lastblend) / len;
+ }
+
+ fac = displist_calc_taper(scene, cu->taperobj, taper_fac);
}
if (bevp->split_tag) {
@@ -1446,27 +1500,12 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
}
/* rotate bevel piece and write in data */
- rotateBevelPiece(cu, bevp, dlb, widfac, fac, &data);
-
- if (a == 1 || a == steps - 1) {
- float *cur_fp = cur_data, *prev_fp = cur_data - 3 * dlb->nr;
- int b;
-
- for (b = 0; b < dlb->nr; b++, prev_fp += 3, cur_fp += 3) {
- float cur[3], prev[3];
-
- copy_v3_v3(cur, cur_fp);
- copy_v3_v3(prev, prev_fp);
-
- if (a == 1)
- interp_v3_v3v3(prev, cur_fp, prev_fp, firstblend);
- if (a == steps - 1)
- interp_v3_v3v3(cur, prev_fp, cur_fp, lastblend);
-
- copy_v3_v3(cur_fp, cur);
- copy_v3_v3(prev_fp, prev);
- }
- }
+ if (a == 0)
+ rotateBevelPiece(cu, bevp, bevp + 1, dlb, 1.0f - firstblend, widfac, fac, &data);
+ else if (a == steps - 1)
+ rotateBevelPiece(cu, bevp, bevp - 1, dlb, 1.0f - lastblend, widfac, fac, &data);
+ else
+ rotateBevelPiece(cu, bevp, NULL, dlb, 0.0f, widfac, fac, &data);
if (cu->bevobj && (cu->flag & CU_FILL_CAPS)) {
if (a == 1)
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index ef751ce3493..55d37c91859 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1561,7 +1561,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* also a little of space to the background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
- x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
+ x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
/* and draw the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
@@ -1578,7 +1578,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* and space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
- 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
+ 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.note);
@@ -1594,7 +1594,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* and space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
- 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
+ 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.date);
@@ -1610,7 +1610,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* and space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
- 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
+ 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.rendertime);
@@ -1625,7 +1625,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* extra space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
- x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
+ x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
@@ -1641,7 +1641,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* extra space for background */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
- x - BUFF_MARGIN_X, y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
+ x - BUFF_MARGIN_X, y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
@@ -1656,7 +1656,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* extra space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
- x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
+ x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
@@ -1671,7 +1671,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* extra space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
- x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
+ x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.camera);
@@ -1684,7 +1684,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* extra space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
- x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
+ x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.cameralens);
}
@@ -1697,7 +1697,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* extra space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
- x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
+ x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
@@ -1713,7 +1713,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* extra space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
- x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
+ x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.strip);
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 4782d09a7c8..2f37db846f3 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -33,9 +33,12 @@
#include "MEM_guardedalloc.h"
+#include "DNA_anim_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
+#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "BLI_listbase.h"
@@ -73,7 +76,7 @@ Lamp *BKE_lamp_add(const char *name)
la->soft = 3.0f;
la->compressthresh = 0.05f;
la->ray_samp = la->ray_sampy = la->ray_sampz = 1;
- la->area_size = la->area_sizey = la->area_sizez = 1.0f;
+ la->area_size = la->area_sizey = la->area_sizez = 0.1f;
la->buffers = 1;
la->buftype = LA_SHADBUF_HALFWAY;
la->ray_samp_method = LA_SAMP_HALTON;
@@ -232,3 +235,38 @@ void BKE_lamp_free(Lamp *la)
la->id.icon_id = 0;
}
+/* Calculate all drivers for lamps, see material_drivers_update for why this is a bad hack */
+
+static void lamp_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime)
+{
+ bNode *node;
+
+ /* nodetree itself */
+ if (ntree->adt && ntree->adt->drivers.first)
+ BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS);
+
+ /* nodes */
+ for (node = ntree->nodes.first; node; node = node->next)
+ if (node->id && node->type == NODE_GROUP)
+ lamp_node_drivers_update(scene, (bNodeTree *)node->id, ctime);
+}
+
+void lamp_drivers_update(Scene *scene, Lamp *la, float ctime)
+{
+ /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited already
+ * (see BKE_scene_update_tagged()). This assumes la->id.flag & LIB_DOIT isn't set by anything else
+ * in the meantime... [#32017] */
+ if (la->id.flag & LIB_DOIT)
+ return;
+ else
+ la->id.flag |= LIB_DOIT;
+
+ /* lamp itself */
+ if (la->adt && la->adt->drivers.first)
+ BKE_animsys_evaluate_animdata(scene, &la->id, la->adt, ctime, ADT_RECALC_DRIVERS);
+
+ /* nodes */
+ if (la->nodetree)
+ lamp_node_drivers_update(scene, la->nodetree, ctime);
+}
+
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index e67df9c6419..7d89678d36f 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -245,7 +245,7 @@ static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int e
}
else {
bucket->segments = MEM_reallocN(bucket->segments,
- (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments));
+ (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments));
}
bucket->alloc_segment += alloc_delta;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 6d44473583f..068059dc29a 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -2388,7 +2388,7 @@ void create_vert_poly_map(MeshElemMap **map, int **mem,
* 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)
+ const MEdge *medge, int totvert, int totedge)
{
int i, *indices;
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 66f2ff12258..c737dccc5d2 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -984,7 +984,7 @@ static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *gri
/* Construct 3x3 tangent-space matrix in 'mat' */
static void grid_tangent_matrix(float mat[3][3], const CCGKey *key,
- int x, int y, CCGElem *grid)
+ int x, int y, CCGElem *grid)
{
grid_tangent(key, x, y, 0, grid, mat[0]);
normalize_v3(mat[0]);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 04dae942d5b..7e3808512b6 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2664,6 +2664,8 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
}
}
}
+ else if (ob->type == OB_LAMP)
+ lamp_drivers_update(scene, ob->data, ctime);
/* particles */
if (ob->particlesystem.first) {
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 7bc736d394e..e694a7e7eb3 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -183,7 +183,7 @@ MINLINE float catrom(float p0, float p1, float p2, float p3, float f)
MINLINE float omega(float k, float depth)
{
- return sqrt(GRAVITY * k * tanh(k * depth));
+ return sqrtf(GRAVITY * k * tanhf(k * depth));
}
// modified Phillips spectrum
@@ -256,8 +256,8 @@ static void add_comlex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl
static void mul_complex_f(fftw_complex res, fftw_complex cmpl, float f)
{
- res[0] = cmpl[0] * f;
- res[1] = cmpl[1] * f;
+ res[0] = cmpl[0] * (double)f;
+ res[1] = cmpl[1] * (double)f;
}
static void mul_complex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl2)
@@ -289,8 +289,8 @@ static void exp_complex(fftw_complex res, fftw_complex cmpl)
{
float r = expf(cmpl[0]);
- res[0] = cos(cmpl[1]) * r;
- res[1] = sin(cmpl[1]) * r;
+ res[0] = cosf(cmpl[1]) * r;
+ res[1] = sinf(cmpl[1]) * r;
}
float BKE_ocean_jminus_to_foam(float jminus, float coverage)
@@ -462,7 +462,7 @@ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j)
i = abs(i) % oc->_M;
j = abs(j) % oc->_N;
- ocr->disp[1] = oc->_do_disp_y ? oc->_disp_y[i * oc->_N + j] : 0.0f;
+ ocr->disp[1] = oc->_do_disp_y ? (float)oc->_disp_y[i * oc->_N + j] : 0.0f;
if (oc->_do_chop) {
ocr->disp[0] = oc->_disp_x[i * oc->_N + j];
@@ -546,7 +546,7 @@ 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.0 ? 0.0 : 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));
}
}
@@ -568,7 +568,7 @@ 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.0 ? 0.0 : 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));
}
}
@@ -589,7 +589,7 @@ 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, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : 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));
}
}
@@ -616,7 +616,7 @@ 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, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : 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));
}
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 49b405379eb..3ce66f23d81 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -58,8 +58,10 @@
#include "BKE_anim.h"
#include "BKE_animsys.h"
+#include "BKE_action.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_idprop.h"
@@ -117,6 +119,24 @@ void free_qtcodecdata(QuicktimeCodecData *qcd)
}
}
+static void remove_sequencer_fcurves(Scene *sce)
+{
+ AnimData *adt = BKE_animdata_from_id(&sce->id);
+
+ if (adt && adt->action) {
+ FCurve *fcu, *nextfcu;
+
+ for (fcu = adt->action->curves.first; fcu; fcu = nextfcu) {
+ nextfcu = fcu->next;
+
+ if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
+ action_groups_remove_channel(adt->action, fcu);
+ free_fcurve(fcu);
+ }
+ }
+ }
+}
+
Scene *BKE_scene_copy(Scene *sce, int type)
{
Scene *scen;
@@ -181,6 +201,10 @@ Scene *BKE_scene_copy(Scene *sce, int type)
BLI_strncpy(scen->sequencer_colorspace_settings.name, sce->sequencer_colorspace_settings.name,
sizeof(scen->sequencer_colorspace_settings.name));
+
+ /* remove animation used by sequencer */
+ if (type != SCE_COPY_FULL)
+ remove_sequencer_fcurves(scen);
}
/* tool settings */
@@ -1057,6 +1081,7 @@ void BKE_scene_update_tagged(Main *bmain, Scene *scene)
* when trying to find materials with drivers that need evaluating [#32017]
*/
tag_main_idcode(bmain, ID_MA, FALSE);
+ tag_main_idcode(bmain, ID_LA, FALSE);
/* update all objects: drivers, matrices, displists, etc. flags set
* by depgraph or manual, no layer check here, gets correct flushed
@@ -1126,6 +1151,7 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
* when trying to find materials with drivers that need evaluating [#32017]
*/
tag_main_idcode(bmain, ID_MA, FALSE);
+ tag_main_idcode(bmain, ID_LA, FALSE);
/* BKE_object_handle_update() on all objects, groups and sets */
scene_update_tagged_recursive(bmain, sce, sce);
diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c
index b0dcad64722..609724e802f 100644
--- a/source/blender/blenkernel/intern/seqmodifier.c
+++ b/source/blender/blenkernel/intern/seqmodifier.c
@@ -349,9 +349,9 @@ static void hue_correct_apply_threaded(int width, int height, unsigned char *rec
hsv_to_rgb(hsv[0], hsv[1], hsv[2], result, result + 1, result + 2);
if (mask_rect_float)
- copy_v3_v3(mask, mask_rect_float + pixel_index);
+ copy_v3_v3(mask, mask_rect_float + pixel_index);
else if (mask_rect)
- rgb_uchar_to_float(mask, mask_rect + pixel_index);
+ rgb_uchar_to_float(mask, mask_rect + pixel_index);
result[0] = pixel[0] * (1.0f - mask[0]) + result[0] * mask[0];
result[1] = pixel[1] * (1.0f - mask[1]) + result[1] * mask[1];
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index af0cab98fe0..547ca96e10a 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -2344,6 +2344,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
int do_seq;
int have_seq = FALSE;
Scene *scene;
+ int is_thread_main = BLI_thread_is_main();
/* don't refer to seq->scene above this point!, it can be NULL */
if (seq->scene == NULL) {
@@ -2373,7 +2374,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
/* prevent eternal loop */
do_seq = context.scene->r.scemode & R_DOSEQ;
- context.scene->r.scemode &= ~R_DOSEQ;
+ scene->r.scemode &= ~R_DOSEQ;
#ifdef DURIAN_CAMERA_SWITCH
/* stooping to new low's in hackyness :( */
@@ -2383,10 +2384,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
(void)oldmarkers;
#endif
- if ((sequencer_view3d_cb && do_seq_gl && camera) &&
- (BLI_thread_is_main() == TRUE) &&
- ((have_seq == FALSE) || (scene == context.scene)))
- {
+ if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) {
char err_out[256] = "unknown";
/* for old scened this can be uninitialized,
* should probably be added to do_versions at some point if the functionality stays */
@@ -2405,8 +2403,12 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
Render *re = RE_GetRender(scene->id.name);
RenderResult rres;
- /* XXX: this if can be removed when sequence preview rendering uses the job system */
- if (is_rendering || context.scene != scene) {
+ /* XXX: this if can be removed when sequence preview rendering uses the job system
+ *
+ * disable rendered preview for sequencer while rendering -- it's very much possible
+ * that preview render will went into conflict with final render
+ */
+ if (!is_thread_main || is_rendering == FALSE) {
if (re == NULL)
re = RE_NewRender(scene->id.name);
@@ -2440,7 +2442,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
}
/* restore */
- context.scene->r.scemode |= do_seq;
+ scene->r.scemode |= do_seq;
scene->r.cfra = oldcfra;
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 96faec389df..72db34d339c 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -56,33 +56,16 @@
#include "BKE_mesh.h"
#include "BKE_tessmesh.h"
-/* Util macros */
-#define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n"))
-
-/* Benchmark macros */
-#if !defined(_WIN32) && 0
-
-#include <sys/time.h>
-
-#define BENCH(a) \
- do { \
- double _t1, _t2; \
- struct timeval _tstart, _tend; \
- clock_t _clock_init = clock(); \
- gettimeofday ( &_tstart, NULL); \
- (a); \
- gettimeofday ( &_tend, NULL); \
- _t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 ); \
- _t2 = ( double ) _tend.tv_sec + ( double ) _tend.tv_usec/ ( 1000*1000 ); \
- printf("%s: %fs (real) %fs (cpu)\n", #a, _t2-_t1, (float)(clock()-_clock_init)/CLOCKS_PER_SEC);\
- } while (0)
-
+/* for timing... */
+#if 0
+# include "PIL_time.h"
#else
-
-#define BENCH(a) (a)
-
+# define TIMEIT_BENCH(expr, id) (expr)
#endif
+/* Util macros */
+#define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n"))
+
/* get derived mesh */
/* TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? */
DerivedMesh *object_get_derived_final(Object *ob)
@@ -143,7 +126,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
BVHTreeNearest nearest = NULL_BVHTreeNearest;
- BENCH(bvhtree_from_mesh_verts(&treeData, calc->target, 0.0, 2, 6));
+ TIMEIT_BENCH(bvhtree_from_mesh_verts(&treeData, calc->target, 0.0, 2, 6), bvhtree_verts);
if (treeData.tree == NULL) {
OUT_OF_MEMORY();
return;
@@ -294,6 +277,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
/* Options about projection direction */
const char use_normal = calc->smd->shrinkOpts;
+ const float proj_limit_squared = calc->smd->projLimit * calc->smd->projLimit;
float proj_axis[3] = {0.0f, 0.0f, 0.0f};
/* Raycast and tree stuff */
@@ -410,6 +394,13 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
treeData.raycast_callback, &treeData);
}
+ /* don't set the initial dist (which is more efficient),
+ * because its calculated in the targets space, we want the dist in our own space */
+ if (proj_limit_squared != 0.0f) {
+ if (len_squared_v3v3(hit.co, co) > proj_limit_squared) {
+ hit.index = -1;
+ }
+ }
if (hit.index != -1) {
madd_v3_v3v3fl(hit.co, hit.co, tmp_no, calc->keepDist);
@@ -437,7 +428,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
BVHTreeNearest nearest = NULL_BVHTreeNearest;
/* Create a bvh-tree of the given target */
- BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 2, 6));
+ TIMEIT_BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 2, 6), bvhtree_faces);
if (treeData.tree == NULL) {
OUT_OF_MEMORY();
return;
@@ -584,15 +575,15 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
if (calc.target) {
switch (smd->shrinkType) {
case MOD_SHRINKWRAP_NEAREST_SURFACE:
- BENCH(shrinkwrap_calc_nearest_surface_point(&calc));
+ TIMEIT_BENCH(shrinkwrap_calc_nearest_surface_point(&calc), deform_surface);
break;
case MOD_SHRINKWRAP_PROJECT:
- BENCH(shrinkwrap_calc_normal_projection(&calc));
+ TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc), deform_project);
break;
case MOD_SHRINKWRAP_NEAREST_VERTEX:
- BENCH(shrinkwrap_calc_nearest_vertex(&calc));
+ TIMEIT_BENCH(shrinkwrap_calc_nearest_vertex(&calc), deform_vertex);
break;
}
}
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index f9925a41177..d96bece2b11 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -262,21 +262,21 @@ static void smoke_set_domain_from_derivedmesh(SmokeDomainSettings *sds, Object *
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.5);
- sds->base_res[2] = (int)(size[2] * scale + 0.5);
+ 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])) {
scale = res / size[1];
sds->scale = size[1] / ob->size[1];
- sds->base_res[0] = (int)(size[0] * scale + 0.5);
+ sds->base_res[0] = (int)(size[0] * scale + 0.5f);
sds->base_res[1] = res;
- sds->base_res[2] = (int)(size[2] * scale + 0.5);
+ sds->base_res[2] = (int)(size[2] * scale + 0.5f);
}
else {
scale = res / size[2];
sds->scale = size[2] / ob->size[2];
- sds->base_res[0] = (int)(size[0] * scale + 0.5);
- sds->base_res[1] = (int)(size[1] * scale + 0.5);
+ sds->base_res[0] = (int)(size[0] * scale + 0.5f);
+ sds->base_res[1] = (int)(size[1] * scale + 0.5f);
sds->base_res[2] = res;
}
@@ -1581,7 +1581,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value
if (fuel && fuel[index]) {
/* instead of using 1.0 for all new fuel add slight falloff
* to reduce flow blockiness */
- float value = 1.0f - pow(1.0f - emission_value, 2.0f);
+ float value = 1.0f - powf(1.0f - emission_value, 2.0f);
if (value > react[index]) {
float f = fuel_flow / fuel[index];
@@ -1944,9 +1944,9 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds,
mul_v3_fl(retvel, mag);
// TODO dg - do in force!
- force_x[index] = MIN2(MAX2(-1.0, retvel[0] * 0.2), 1.0);
- force_y[index] = MIN2(MAX2(-1.0, retvel[1] * 0.2), 1.0);
- force_z[index] = MIN2(MAX2(-1.0, retvel[2] * 0.2), 1.0);
+ force_x[index] = min_ff(max_ff(-1.0f, retvel[0] * 0.2f), 1.0f);
+ force_y[index] = min_ff(max_ff(-1.0f, retvel[1] * 0.2f), 1.0f);
+ force_z[index] = min_ff(max_ff(-1.0f, retvel[2] * 0.2f), 1.0f);
}
}
}
@@ -1999,7 +1999,7 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *
/* adapt timestep for different framerates, dt = 0.1 is at 25fps */
dt = DT_DEFAULT * (25.0f / fps);
// maximum timestep/"CFL" constraint: dt < 5.0 *dx / maxVel
- maxVel = (sds->dx * 5.0);
+ maxVel = (sds->dx * 5.0f);
#if 0
for (i = 0; i < size; i++) {
@@ -2009,7 +2009,7 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *
}
#endif
- maxVelMag = sqrt(maxVelMag) * dt * sds->time_scale;
+ maxVelMag = sqrtf(maxVelMag) * dt * sds->time_scale;
totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */
totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
@@ -2286,7 +2286,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix
const size_t index = smoke_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]);
// T_ray *= T_vox
- *tRay *= exp(input[index] * correct);
+ *tRay *= expf(input[index] * correct);
if (result[index] < 0.0f)
{
@@ -2386,7 +2386,7 @@ static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene)
float light[3];
int a, z, slabsize = sds->res[0] * sds->res[1], size = sds->res[0] * sds->res[1] * sds->res[2];
float *density = smoke_get_density(sds->fluid);
- float correct = -7.0 * sds->dx;
+ float correct = -7.0f * sds->dx;
if (!get_lamp(scene, light)) return;
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index aad205bb5bf..af9d21d8cbc 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -353,17 +353,17 @@ void sound_load(struct Main *bmain, bSound *sound)
}
// XXX unused currently
#if 0
- break;
+ break;
+ }
+ case SOUND_TYPE_BUFFER:
+ if (sound->child_sound && sound->child_sound->handle)
+ sound->handle = AUD_bufferSound(sound->child_sound->handle);
+ break;
+ case SOUND_TYPE_LIMITER:
+ if (sound->child_sound && sound->child_sound->handle)
+ sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end);
+ break;
}
- case SOUND_TYPE_BUFFER:
- if (sound->child_sound && sound->child_sound->handle)
- sound->handle = AUD_bufferSound(sound->child_sound->handle);
- break;
- case SOUND_TYPE_LIMITER:
- if (sound->child_sound && sound->child_sound->handle)
- sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end);
- break;
-}
#endif
if (sound->flags & SOUND_FLAGS_MONO) {
void *handle = AUD_monoSound(sound->handle);
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 469b012f9c3..f76b480c423 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -3025,7 +3025,8 @@ 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);
+ BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces,
+ ccgdm->gridFlagMats, ccgdm->gridHidden);
}
ccgdm->pbvh = ob->sculpt->pbvh;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 3a8a14290dc..da9c919c109 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -478,9 +478,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
c->time_base.den = 2997;
c->time_base.num = 100;
}
- else if ((double) ((int) rd->frs_sec_base) ==
- rd->frs_sec_base)
- {
+ else if ((float) ((int) rd->frs_sec_base) == rd->frs_sec_base) {
c->time_base.den = rd->frs_sec;
c->time_base.num = (int) rd->frs_sec_base;
}
@@ -999,7 +997,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i
}
#ifdef WITH_AUDASPACE
- write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / rd->frs_sec_base));
+ write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
#endif
return success;
}
diff --git a/source/blender/blenlib/BLI_math.h b/source/blender/blenlib/BLI_math.h
index 89c37daae84..db2fed433da 100644
--- a/source/blender/blenlib/BLI_math.h
+++ b/source/blender/blenlib/BLI_math.h
@@ -58,6 +58,7 @@
#include "BLI_math_rotation.h"
#include "BLI_math_vector.h"
#include "BLI_math_geom.h"
+#include "BLI_math_interp.h"
#endif /* __BLI_MATH_H__ */
diff --git a/source/blender/blenlib/BLI_math_interp.h b/source/blender/blenlib/BLI_math_interp.h
new file mode 100644
index 00000000000..21975763779
--- /dev/null
+++ b/source/blender/blenlib/BLI_math_interp.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) 2012 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef BLI_MATH_INTERP
+#define BLI_MATH_INTERP
+
+void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height,
+ int components, float u, float v);
+
+void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height,
+ int components, float u, float v);
+
+void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width, int height,
+ int components, float u, float v);
+
+void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height,
+ int components, float u, float v);
+
+#endif
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 0783a7981ea..f51bd1cf840 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -36,14 +36,18 @@ extern "C" {
/********************************* Init **************************************/
-#define MAT4_UNITY {{ 1.0, 0.0, 0.0, 0.0}, \
- { 0.0, 1.0, 0.0, 0.0}, \
- { 0.0, 0.0, 1.0, 0.0}, \
- { 0.0, 0.0, 0.0, 1.0}}
-
-#define MAT3_UNITY {{ 1.0, 0.0, 0.0}, \
- { 0.0, 1.0, 0.0}, \
- { 0.0, 0.0, 1.0}}
+#define MAT4_UNITY { \
+ { 1.0, 0.0, 0.0, 0.0}, \
+ { 0.0, 1.0, 0.0, 0.0}, \
+ { 0.0, 0.0, 1.0, 0.0}, \
+ { 0.0, 0.0, 0.0, 1.0} \
+}
+
+#define MAT3_UNITY { \
+ { 1.0, 0.0, 0.0}, \
+ { 0.0, 1.0, 0.0}, \
+ { 0.0, 0.0, 1.0} \
+}
void zero_m3(float R[3][3]);
void zero_m4(float R[4][4]);
diff --git a/source/blender/blenlib/BLI_pbvh.h b/source/blender/blenlib/BLI_pbvh.h
index 9483d068bb9..59ecdb359c9 100644
--- a/source/blender/blenlib/BLI_pbvh.h
+++ b/source/blender/blenlib/BLI_pbvh.h
@@ -153,7 +153,8 @@ 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,
- struct DMGridAdjacency *gridadj, void **gridfaces);
+ struct DMGridAdjacency *gridadj, void **gridfaces,
+ struct DMFlagMat *flagmats, unsigned int **grid_hidden);
/* vertex deformer */
float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3];
diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h
index 73f138a750d..ecbc4cb1cd4 100644
--- a/source/blender/blenlib/BLI_string_utf8.h
+++ b/source/blender/blenlib/BLI_string_utf8.h
@@ -37,6 +37,7 @@ int BLI_utf8_invalid_byte(const char *str, int length);
int BLI_utf8_invalid_strip(char *str, int length);
int BLI_str_utf8_size(const char *p); /* warning, can return -1 on bad chars */
+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);
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 3aa0ffc3eaa..cd3a934d816 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -71,6 +71,7 @@ set(SRC
intern/math_color_inline.c
intern/math_geom.c
intern/math_geom_inline.c
+ intern/math_interp.c
intern/math_matrix.c
intern/math_rotation.c
intern/math_vector.c
diff --git a/source/blender/blenlib/PIL_time.h b/source/blender/blenlib/PIL_time.h
index b8f895c5c82..c3e7e8486d9 100644
--- a/source/blender/blenlib/PIL_time.h
+++ b/source/blender/blenlib/PIL_time.h
@@ -20,7 +20,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -76,6 +76,17 @@ void PIL_sleep_ms(int ms);
fflush(stdout); \
} (void)0
+/**
+ * Given some function/expression:
+ * TIMEIT_BENCH(some_function(), some_unique_description);
+ */
+#define TIMEIT_BENCH(expr, id) \
+ { \
+ TIMEIT_START(id); \
+ (expr); \
+ TIMEIT_END(id); \
+ } (void)0
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index f520b2318e5..4c8bd43ef73 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -164,7 +164,11 @@ MINLINE void linearrgb_to_srgb_ushort4_predivide(unsigned short srgb[4], const f
for (i = 0; i < 3; ++i) {
t = linear[i] * inv_alpha;
- srgb[i] = (t < 1.0f) ? (unsigned short) (to_srgb_table_lookup(t) * alpha) : FTOUSHORT(linearrgb_to_srgb(t) * 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]);
diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c
new file mode 100644
index 00000000000..59a1c1f649c
--- /dev/null
+++ b/source/blender/blenlib/intern/math_interp.c
@@ -0,0 +1,351 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if 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): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#include <math.h>
+
+#include "BLI_math.h"
+
+/**************************************************************************
+ * INTERPOLATIONS
+ *
+ * Reference and docs:
+ * http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms
+ ***************************************************************************/
+
+/* BICUBIC Interpolation functions
+ * More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation
+ * function assumes out to be zero'ed, only does RGBA */
+
+static float P(float k)
+{
+ float p1, p2, p3, p4;
+ p1 = MAX2(k + 2.0f, 0);
+ p2 = MAX2(k + 1.0f, 0);
+ p3 = MAX2(k, 0);
+ p4 = MAX2(k - 1.0f, 0);
+ return (float)(1.0f / 6.0f) * (p1 * p1 * p1 - 4.0f * p2 * p2 * p2 + 6.0f * p3 * p3 * p3 - 4.0f * p4 * p4 * p4);
+}
+
+
+#if 0
+/* older, slower function, works the same as above */
+static float P(float k)
+{
+ return (float)(1.0f / 6.0f) * (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * pow(MAX2(k, 0), 3.0f) - 4.0f * pow(MAX2(k - 1.0f, 0), 3.0f));
+}
+#endif
+
+static void vector_from_float(const float *data, float vector[4], int components)
+{
+ if (components == 1) {
+ vector[0] = data[0];
+ }
+ else if (components == 3) {
+ copy_v3_v3(vector, data);
+ }
+ else {
+ copy_v4_v4(vector, data);
+ }
+}
+
+static void vector_from_byte(const unsigned char *data, float vector[4], int components)
+{
+ if (components == 1) {
+ vector[0] = data[0];
+ }
+ else if (components == 3) {
+ vector[0] = data[0];
+ vector[1] = data[1];
+ vector[2] = data[2];
+ }
+ else {
+ vector[0] = data[0];
+ vector[1] = data[1];
+ vector[2] = data[2];
+ vector[3] = data[3];
+ }
+}
+
+/* BICUBIC INTERPOLATION */
+BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, const float *float_buffer,
+ unsigned char *byte_output, float *float_output, int width, int height,
+ int components, float u, float v)
+{
+ int i, j, n, m, x1, y1;
+ float a, b, w, wx, wy[4], out[4];
+
+ /* sample area entirely outside image? */
+ if (ceil(u) < 0 || floor(u) > width - 1 || ceil(v) < 0 || floor(v) > height - 1) {
+ return;
+ }
+
+ i = (int)floor(u);
+ j = (int)floor(v);
+ a = u - i;
+ b = v - j;
+
+ zero_v4(out);
+
+/* Optimized and not so easy to read */
+
+ /* avoid calling multiple times */
+ wy[0] = P(b - (-1));
+ wy[1] = P(b - 0);
+ wy[2] = P(b - 1);
+ wy[3] = P(b - 2);
+
+ for (n = -1; n <= 2; n++) {
+ x1 = i + n;
+ CLAMP(x1, 0, width - 1);
+ wx = P(n - a);
+ for (m = -1; m <= 2; m++) {
+ float data[4];
+
+ y1 = j + m;
+ CLAMP(y1, 0, height - 1);
+ /* normally we could do this */
+ /* w = P(n-a) * P(b-m); */
+ /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */
+ w = wx * wy[m + 1];
+
+ if (float_output) {
+ const float *float_data = float_buffer + width * y1 * 4 + 4 * x1;
+
+ vector_from_float(float_data, data, components);
+ }
+ else {
+ const unsigned char *byte_data = byte_buffer + width * y1 * 4 + 4 * x1;
+
+ vector_from_byte(byte_data, data, components);
+ }
+
+ if (components == 1) {
+ out[0] += data[0] * w;
+ }
+ else if (components == 3) {
+ out[0] += data[0] * w;
+ out[1] += data[1] * w;
+ out[2] += data[2] * w;
+ }
+ else {
+ out[0] += data[0] * w;
+ out[1] += data[1] * w;
+ out[2] += data[2] * w;
+ out[3] += data[3] * w;
+ }
+ }
+ }
+
+/* Done with optimized part */
+
+#if 0
+ /* older, slower function, works the same as above */
+ for (n = -1; n <= 2; n++) {
+ for (m = -1; m <= 2; m++) {
+ x1 = i + n;
+ y1 = j + m;
+ if (x1 > 0 && x1 < width && y1 > 0 && y1 < height) {
+ float data[4];
+
+ if (float_output) {
+ const float *float_data = float_buffer + width * y1 * 4 + 4 * x1;
+
+ vector_from_float(float_data, data, components);
+ }
+ else {
+ const unsigned char *byte_data = byte_buffer + width * y1 * 4 + 4 * x1;
+
+ vector_from_byte(byte_data, data, components);
+ }
+
+ if (components == 1) {
+ out[0] += data[0] * P(n - a) * P(b - m);
+ }
+ else if (components == 3) {
+ out[0] += data[0] * P(n - a) * P(b - m);
+ out[1] += data[1] * P(n - a) * P(b - m);
+ out[2] += data[2] * P(n - a) * P(b - m);
+ }
+ else {
+ out[0] += data[0] * P(n - a) * P(b - m);
+ out[1] += data[1] * P(n - a) * P(b - m);
+ out[2] += data[2] * P(n - a) * P(b - m);
+ out[3] += data[3] * P(n - a) * P(b - m);
+ }
+ }
+ }
+ }
+#endif
+
+ if (float_output) {
+ if (components == 1) {
+ float_output[0] = out[0];
+ }
+ else if (components == 3) {
+ copy_v3_v3(float_output, out);
+ }
+ else {
+ copy_v4_v4(float_output, out);
+ }
+ }
+ else {
+ if (components == 1) {
+ byte_output[0] = out[0];
+ }
+ else if (components == 3) {
+ byte_output[0] = out[0];
+ byte_output[1] = out[1];
+ byte_output[2] = out[2];
+ }
+ else {
+ byte_output[0] = out[0];
+ byte_output[1] = out[1];
+ byte_output[2] = out[2];
+ byte_output[3] = out[3];
+ }
+ }
+}
+
+void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height,
+ int components, float u, float v)
+{
+ bicubic_interpolation(NULL, buffer, NULL, output, width, height, components, u, v);
+}
+
+void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height,
+ int components, float u, float v)
+{
+ bicubic_interpolation(buffer, NULL, output, NULL, width, height, components, u, v);
+}
+
+/* BILINEAR INTERPOLATION */
+BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const float *float_buffer,
+ unsigned char *byte_output, float *float_output, int width, int height,
+ int components, float u, float v)
+{
+ float a, b;
+ float a_b, ma_b, a_mb, ma_mb;
+ int y1, y2, x1, x2;
+
+ /* ImBuf in must have a valid rect or rect_float, assume this is already checked */
+
+ x1 = (int)floor(u);
+ x2 = (int)ceil(u);
+ y1 = (int)floor(v);
+ y2 = (int)ceil(v);
+
+ /* sample area entirely outside image? */
+ if (x2 < 0 || x1 > width - 1 || y2 < 0 || y1 > height - 1) {
+ return;
+ }
+
+ if (float_output) {
+ const float *row1, *row2, *row3, *row4;
+ float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ /* sample including outside of edges of image */
+ if (x1 < 0 || y1 < 0) row1 = empty;
+ else row1 = float_buffer + width * y1 * 4 + 4 * x1;
+
+ if (x1 < 0 || y2 > height - 1) row2 = empty;
+ else row2 = float_buffer + width * y2 * 4 + 4 * x1;
+
+ if (x2 > width - 1 || y1 < 0) row3 = empty;
+ else row3 = float_buffer + width * y1 * 4 + 4 * x2;
+
+ if (x2 > width - 1 || y2 > height - 1) row4 = empty;
+ else row4 = float_buffer + width * y2 * 4 + 4 * x2;
+
+ a = u - floorf(u);
+ b = v - floorf(v);
+ a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b);
+
+ if (components == 1) {
+ float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0];
+ }
+ else if (components == 3) {
+ float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0];
+ float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1];
+ float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2];
+ }
+ else {
+ float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0];
+ float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1];
+ float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2];
+ float_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3];
+ }
+ }
+ else {
+ const unsigned char *row1, *row2, *row3, *row4;
+ unsigned char empty[4] = {0, 0, 0, 0};
+
+ /* sample including outside of edges of image */
+ if (x1 < 0 || y1 < 0) row1 = empty;
+ else row1 = byte_buffer + width * y1 * 4 + 4 * x1;
+
+ if (x1 < 0 || y2 > height - 1) row2 = empty;
+ else row2 = byte_buffer + width * y2 * 4 + 4 * x1;
+
+ if (x2 > width - 1 || y1 < 0) row3 = empty;
+ else row3 = byte_buffer + width * y1 * 4 + 4 * x2;
+
+ if (x2 > width - 1 || y2 > height - 1) row4 = empty;
+ else row4 = byte_buffer + width * y2 * 4 + 4 * x2;
+
+ a = u - floorf(u);
+ b = v - floorf(v);
+ a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b);
+
+ if (components == 1) {
+ byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0];
+ }
+ else if (components == 3) {
+ byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0];
+ byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1];
+ byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2];
+ }
+ else {
+ byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0];
+ byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1];
+ byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2];
+ byte_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3];
+ }
+ }
+}
+
+void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width, int height,
+ int components, float u, float v)
+{
+ bilinear_interpolation(NULL, buffer, NULL, output, width, height, components, u, v);
+}
+
+void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height,
+ int components, float u, float v)
+{
+ bilinear_interpolation(buffer, NULL, output, NULL, width, height, components, u, v);
+}
diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c
index 7637c60ec16..e21ce0716d2 100644
--- a/source/blender/blenlib/intern/pbvh.c
+++ b/source/blender/blenlib/intern/pbvh.c
@@ -1707,11 +1707,19 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
}
}
-void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces)
+void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces,
+ DMFlagMat *flagmats, BLI_bitmap *grid_hidden)
{
+ int a;
+
bvh->grids = grids;
bvh->gridadj = gridadj;
bvh->gridfaces = gridfaces;
+ bvh->grid_flag_mats = flagmats;
+ bvh->grid_hidden = grid_hidden;
+
+ for (a = 0; a < bvh->totnode; ++a)
+ BLI_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]);
}
float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3]
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c
index 0b737e0eff5..e80f96ee0fe 100644
--- a/source/blender/blenlib/intern/string_utf8.c
+++ b/source/blender/blenlib/intern/string_utf8.c
@@ -317,12 +317,12 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size
/* end wchar_t / utf8 functions */
/* --------------------------------------------------------------------------*/
-/* copied from glib's gutf8.c */
+/* copied from glib's gutf8.c, added 'Err' arg */
/* note, glib uses unsigned int for unicode, best we do the same,
* though we don't typedef it - campbell */
-#define UTF8_COMPUTE(Char, Mask, Len) \
+#define UTF8_COMPUTE(Char, Mask, Len, Err) \
if (Char < 128) { \
Len = 1; \
Mask = 0x7f; \
@@ -348,7 +348,7 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size
Mask = 0x01; \
} \
else { \
- Len = -1; \
+ Len = Err; /* -1 is the typical error value or 1 to skip */ \
} (void)0
/* same as glib define but added an 'Err' arg */
@@ -371,7 +371,20 @@ int BLI_str_utf8_size(const char *p)
int mask = 0, len;
unsigned char c = (unsigned char) *p;
- UTF8_COMPUTE (c, mask, len);
+ UTF8_COMPUTE (c, mask, len, -1);
+
+ (void)mask; /* quiet warning */
+
+ return len;
+}
+
+/* use when we want to skip errors */
+int BLI_str_utf8_size_safe(const char *p)
+{
+ int mask = 0, len;
+ unsigned char c = (unsigned char) *p;
+
+ UTF8_COMPUTE (c, mask, len, 1);
(void)mask; /* quiet warning */
@@ -397,7 +410,7 @@ unsigned int BLI_str_utf8_as_unicode(const char *p)
unsigned int result;
unsigned char c = (unsigned char) *p;
- UTF8_COMPUTE (c, mask, len);
+ UTF8_COMPUTE (c, mask, len, -1);
if (len == -1)
return BLI_UTF8_ERR;
UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR);
@@ -412,7 +425,7 @@ unsigned int BLI_str_utf8_as_unicode_and_size(const char *p, size_t *index)
unsigned int result;
unsigned char c = (unsigned char) *p;
- UTF8_COMPUTE (c, mask, len);
+ UTF8_COMPUTE (c, mask, len, -1);
if (len == -1)
return BLI_UTF8_ERR;
UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR);
@@ -431,7 +444,7 @@ unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index)
p += *index;
c = (unsigned char) *p;
- UTF8_COMPUTE (c, mask, len);
+ UTF8_COMPUTE (c, mask, len, -1);
if (len == -1) {
/* when called with NULL end, result will never be NULL,
* checks for a NULL character */
diff --git a/source/blender/blenlib/intern/voronoi.c b/source/blender/blenlib/intern/voronoi.c
index 0d411038b3e..601b07c9a5d 100644
--- a/source/blender/blenlib/intern/voronoi.c
+++ b/source/blender/blenlib/intern/voronoi.c
@@ -609,9 +609,9 @@ static int voronoi_getNextSideCoord(ListBase *edges, float coord[2], int dim, in
static void voronoi_createBoundaryEdges(ListBase *edges, int width, int height)
{
const float corners[4][2] = {{width - 1, 0.0f},
- {width - 1, height - 1},
- {0.0f, height - 1},
- {0.0f, 0.0f}};
+ {width - 1, height - 1},
+ {0.0f, height - 1},
+ {0.0f, 0.0f}};
int i, dim = 0, dir = 1;
float coord[2] = {0.0f, 0.0f};
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index bef97a4ab6a..1a16615616d 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -361,36 +361,39 @@ static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr)
}
/* for libdata, nr has ID code, no increment */
-static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib)
+static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib)
{
- int i;
-
- if (addr == NULL) return NULL;
-
+ if (addr == NULL) {
+ return NULL;
+ }
+
/* lasthit works fine for non-libdata, linking there is done in same sequence as writing */
if (onm->sorted) {
OldNew entry_s, *entry;
-
+
entry_s.old = addr;
-
+
entry = bsearch(&entry_s, onm->entries, onm->nentries, sizeof(OldNew), verg_oldnewmap);
if (entry) {
ID *id = entry->newp;
-
+
if (id && (!lib || id->lib)) {
- return entry->newp;
+ return id;
}
}
}
-
- for (i = 0; i < onm->nentries; i++) {
- OldNew *entry = &onm->entries[i];
-
- if (entry->old == addr) {
- ID *id = entry->newp;
-
- if (id && (!lib || id->lib)) {
- return entry->newp;
+ else {
+ /* note, this can be a bottle neck when loading some files */
+ unsigned int nentries = (unsigned int)onm->nentries;
+ unsigned int i;
+ OldNew *entry;
+
+ for (i = 0, entry = onm->entries; i < nentries; i++, entry++) {
+ if (entry->old == addr) {
+ ID *id = id = entry->newp;
+ if (id && (!lib || id->lib)) {
+ return id;
+ }
}
}
}
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index 645e4e348e8..64fa1ea399d 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -397,11 +397,11 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n
/* more of a weight then a distance */
far_cross_dist = (/* first we want to have a value close to zero mapped to 1 */
- 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) *
+ 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) *
- /* second we multiply by the distance
- * so points close to the center are not preferred */
- far_cross_dist);
+ /* second we multiply by the distance
+ * so points close to the center are not preferred */
+ far_cross_dist);
if (far_cross_dist > far_cross_best || far_cross == NULL) {
far_cross = vert_arr[i]->co;
diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/intern/bmesh_decimate_collapse.c
index 1f92a8f9227..74792d1d558 100644
--- a/source/blender/bmesh/intern/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/intern/bmesh_decimate_collapse.c
@@ -52,6 +52,7 @@
#define BOUNDARY_PRESERVE_WEIGHT 100.0f
#define OPTIMIZE_EPS 0.01f /* FLT_EPSILON is too small, see [#33106] */
+#define COST_INVALID FLT_MAX
typedef enum CD_UseFlag {
CD_DO_VERT = (1 << 0),
@@ -132,6 +133,56 @@ 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])
+{
+ BMIter liter;
+ BMLoop *l;
+ unsigned int i;
+
+ for (i = 0; i < 2; i++) {
+ /* loop over both verts */
+ BMVert *v = *((&e->v1) + i);
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (l->e != e && l->prev->e != e) {
+ float *co_prev = l->prev->v->co;
+ float *co_next = l->next->v->co;
+ float cross_exist[3];
+ float cross_optim[3];
+
+#if 1
+ float vec_other[3]; /* line between the two outer verts, re-use for both cross products */
+ float vec_exist[3]; /* before collapse */
+ float vec_optim[3]; /* after collapse */
+
+ sub_v3_v3v3(vec_other, co_prev, co_next);
+ sub_v3_v3v3(vec_exist, co_prev, v->co);
+ sub_v3_v3v3(vec_optim, co_prev, optimize_co);
+
+ cross_v3_v3v3(cross_exist, vec_other, vec_exist);
+ cross_v3_v3v3(cross_optim, vec_other, vec_optim);
+
+ /* normalize isn't really needed, but ensures the value at a unit we can compare against */
+ normalize_v3(cross_exist);
+ normalize_v3(cross_optim);
+#else
+ normal_tri_v3(cross_exist, v->co, co_prev, co_next);
+ normal_tri_v3(cross_optim, optimize_co, co_prev, co_next);
+#endif
+
+ /* use a small value rather then zero so we don't flip a face in multiple steps
+ * (first making it zero area, then flipping again)*/
+ if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) {
+ //printf("no flip\n");
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
static void bm_decim_build_edge_cost_single(BMEdge *e,
const Quadric *vquadrics, const float *vweights,
Heap *eheap, HeapNode **eheap_table)
@@ -200,6 +251,16 @@ static void bm_decim_build_edge_cost_single(BMEdge *e,
eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e);
}
+
+/* use this for degenerate cases - add back to the heap with an invalid cost,
+ * this way it may be calculated again if surrounding geometry changes */
+static void bm_decim_invalid_edge_cost_single(BMEdge *e,
+ Heap *eheap, HeapNode **eheap_table)
+{
+ BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL);
+ eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e);
+}
+
static void bm_decim_build_edge_cost(BMesh *bm,
const Quadric *vquadrics, const float *vweights,
Heap *eheap, HeapNode **eheap_table)
@@ -525,7 +586,7 @@ BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l)
#endif
}
-static int bm_edge_collapse_is_degenerate(BMEdge *e_first)
+static int 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) */
@@ -629,11 +690,6 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e
{
BMVert *v_other;
- /* disallow collapsing which results in degenerate cases */
- if (bm_edge_collapse_is_degenerate(e_clear)) {
- return FALSE;
- }
-
v_other = BM_edge_other_vert(e_clear, v_clear);
BLI_assert(v_other != NULL);
@@ -704,8 +760,11 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e
BM_edge_kill(bm, e_clear);
+ v_other->head.hflag |= v_clear->head.hflag;
BM_vert_splice(bm, v_clear, v_other);
+ e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
+ e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag;
BM_edge_splice(bm, e_a_other[0], e_a_other[1]);
BM_edge_splice(bm, e_b_other[0], e_b_other[1]);
@@ -750,8 +809,10 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e
BM_edge_kill(bm, e_clear);
+ v_other->head.hflag |= v_clear->head.hflag;
BM_vert_splice(bm, v_clear, v_other);
+ e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
BM_edge_splice(bm, e_a_other[0], e_a_other[1]);
// BM_mesh_validate(bm);
@@ -781,12 +842,23 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
copy_v3_v3(v_clear_no, e->v2->no);
#endif
+ /* disallow collapsing which results in degenerate cases */
+ if (UNLIKELY(bm_edge_collapse_is_degenerate_topology(e))) {
+ bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */
+ return;
+ }
+
bm_decim_calc_target_co(e, optimize_co, vquadrics);
+ /* check if this would result in an overlapping face */
+ if (UNLIKELY(bm_edge_collapse_is_degenerate_flip(e, optimize_co))) {
+ bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */
+ return;
+ }
+
/* use for customdata merging */
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 */
if (customdata_fac < 0.0 - FLT_EPSILON || customdata_fac > 1.0f + FLT_EPSILON) {
@@ -848,7 +920,10 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
} while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first);
}
-#if 0
+ /* this block used to be disabled,
+ * but enable now since surrounding faces may have been
+ * set to COST_INVALID because of a face overlap that no longer occurs */
+#if 1
/* optional, update edges around the vertex face fan */
{
BMIter liter;
@@ -863,13 +938,17 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE);
- bm_decim_build_edge_cost_single(e_outer, vquadrics, eheap, eheap_table);
+ bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, eheap, eheap_table);
}
}
}
/* end optional update */
#endif
}
+ else {
+ /* add back with a high cost */
+ bm_decim_invalid_edge_cost_single(e, eheap, eheap_table);
+ }
}
@@ -925,7 +1004,10 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c
#endif
/* iterative edge collapse and maintain the eheap */
- while ((bm->totface > face_tot_target) && (BLI_heap_is_empty(eheap) == FALSE)) {
+ while ((bm->totface > face_tot_target) &&
+ (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));
BMEdge *e = BLI_heap_popmin(eheap);
BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */
diff --git a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c
index 68c0652d2c4..1ec13010d80 100644
--- a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c
+++ b/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c
@@ -247,9 +247,9 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int
#ifdef USE_WALKER
/* Walk over selected elements starting at active */
BMW_init(&walker, bm, BMW_CONNECTED_VERTEX,
- ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */
- BMW_NIL_LAY);
+ ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP,
+ BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */
+ BMW_NIL_LAY);
BLI_assert(walker.order == BMW_BREADTH_FIRST);
for (v = BMW_begin(&walker, v_first); v != NULL; v = BMW_step(&walker)) {
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 62374d8b7bb..dc8b52423ab 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -118,7 +118,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
e = v->e;
do {
e = bmesh_disk_edge_next(e, v);
- if (!(BM_edge_share_face_count(e, v->e))) {
+ if (!(BM_edge_share_face_check(e, v->e))) {
keepedge = e;
baseedge = v->e;
break;
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 31698f0abc1..398e6bbedcf 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -1064,6 +1064,7 @@ static BMOpDefine bmo_create_cube_def = {
0,
};
+#define NEW_BEVEL 1
/*
* Bevel
*
@@ -1071,6 +1072,12 @@ static BMOpDefine bmo_create_cube_def = {
*/
static BMOpDefine bmo_bevel_def = {
"bevel",
+#ifdef NEW_BEVEL
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */
+ {BMO_OP_SLOT_FLT, "offset"}, /* amount to offset beveled edge */
+ {BMO_OP_SLOT_INT, "segments"}, /* number of segments in bevel */
+ {0} /* null-terminating sentinel */},
+#else
{{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */
{BMO_OP_SLOT_ELEMENT_BUF, "face_spans"}, /* new geometry */
{BMO_OP_SLOT_ELEMENT_BUF, "face_holes"}, /* new geometry */
@@ -1081,6 +1088,7 @@ static BMOpDefine bmo_bevel_def = {
{BMO_OP_SLOT_INT, "lengthlayer"}, /* which PROP_FLT layer to us */
{BMO_OP_SLOT_FLT, "percent"}, /* percentage to expand beveled edge */
{0} /* null-terminating sentinel */},
+#endif
bmo_bevel_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 4cc946a3a40..9d1054dc042 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -354,7 +354,7 @@ void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, i
else {
fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size);
- memset(slot->data.p, 0, sizeof(float) * 4 * 4);
+ zero_m4(slot->data.p);
}
}
@@ -365,7 +365,12 @@ void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4])
if (!(slot->slot_type == BMO_OP_SLOT_MAT))
return;
- copy_m4_m4(r_mat, (float (*)[4])slot->data.p);
+ if (slot->data.p) {
+ copy_m4_m4(r_mat, (float (*)[4])slot->data.p);
+ }
+ else {
+ unit_m4(r_mat);
+ }
}
void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3])
@@ -375,7 +380,12 @@ void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3])
if (!(slot->slot_type == BMO_OP_SLOT_MAT))
return;
- copy_m3_m4(r_mat, slot->data.p);
+ if (slot->data.p) {
+ copy_m3_m4(r_mat, slot->data.p);
+ }
+ else {
+ unit_m3(r_mat);
+ }
}
void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p)
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 4b07dd74eef..1e1d7d1becb 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -401,6 +401,7 @@ BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step)
}
else {
BLI_assert(0);
+ return NULL;
}
if (BM_edge_is_manifold(e_next)) {
@@ -724,6 +725,47 @@ int BM_edge_is_boundary(BMEdge *e)
#endif
/**
+ * Returns the number of faces that are adjacent to both f1 and f2,
+ * \note Could be sped up a bit by not using iterators and by tagging
+ * faces on either side, then count the tags rather then searching.
+ */
+int BM_face_share_face_count(BMFace *f1, BMFace *f2)
+{
+ BMIter iter1, iter2;
+ BMEdge *e;
+ BMFace *f;
+ int count = 0;
+
+ 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))
+ count++;
+ }
+ }
+
+ return count;
+}
+
+/**
+ * same as #BM_face_share_face_count but returns a bool
+ */
+int BM_face_share_face_check(BMFace *f1, BMFace *f2)
+{
+ BMIter iter1, iter2;
+ BMEdge *e;
+ BMFace *f;
+
+ 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 FALSE;
+}
+
+/**
* Counts the number of edges two faces share (if any)
*/
int BM_face_share_edge_count(BMFace *f1, BMFace *f2)
@@ -743,9 +785,27 @@ int BM_face_share_edge_count(BMFace *f1, BMFace *f2)
}
/**
+ * Returns TRUE if the faces share an edge
+ */
+int BM_face_share_edge_check(BMFace *f1, BMFace *f2)
+{
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f1);
+ do {
+ if (bmesh_radial_face_find(l_iter->e, f2)) {
+ return TRUE;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ return FALSE;
+}
+
+/**
* Test if e1 shares any faces with e2
*/
-int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2)
+int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
{
BMLoop *l;
BMFace *f;
@@ -766,7 +826,7 @@ int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2)
/**
* Tests to see if e1 shares a vertex with e2
*/
-int BM_edge_share_vert_count(BMEdge *e1, BMEdge *e2)
+int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2)
{
return (e1->v1 == e2->v1 ||
e1->v1 == e2->v2 ||
@@ -1023,7 +1083,12 @@ float BM_vert_calc_shell_factor(BMVert *v)
accum_angle += face_angle;
}
- return accum_shell / accum_angle;
+ if (accum_angle != 0.0f) {
+ return accum_shell / accum_angle;
+ }
+ else {
+ return 1.0f;
+ }
}
/**
@@ -1044,7 +1109,12 @@ float BM_vert_calc_mean_tagged_edge_length(BMVert *v)
}
}
- return length / (float)tot;
+ if (tot) {
+ return length / (float)tot;
+ }
+ else {
+ return 0.0f;
+ }
}
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 34d0747676c..579a1397b0c 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -84,9 +84,13 @@ int BM_face_exists(BMesh *bm, 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);
+int BM_face_share_face_count(BMFace *f1, BMFace *f2);
int BM_face_share_edge_count(BMFace *f1, BMFace *f2);
-int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2);
-int BM_edge_share_vert_count(BMEdge *e1, BMEdge *e2);
+
+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_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);
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index c5120571755..7df5aa8fe9c 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor(s): Joseph Eagar.
+ * Contributor(s): Joseph Eagar, Aleksandr Mokhov, Howard Trickey
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -26,6 +26,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_listbase.h"
#include "BLI_array.h"
#include "BLI_math.h"
#include "BLI_smallhash.h"
@@ -36,14 +37,1358 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define BEVEL_FLAG 1
-#define BEVEL_DEL 2
-#define FACE_NEW 4
-#define EDGE_OLD 8
-#define FACE_OLD 16
-#define VERT_OLD 32
-#define FACE_SPAN 64
-#define FACE_HOLE 128
+#define NEW_BEVEL 1
+
+#ifdef NEW_BEVEL
+#define BEVEL_FLAG 1
+#define EDGE_SELECTED 2
+
+#define BEVEL_EPSILON 1e-6
+
+/* Constructed vertex, sometimes later instantiated as BMVert */
+typedef struct NewVert {
+ float co[3];
+ BMVert *v;
+} NewVert;
+
+struct BoundVert;
+
+/* Data for one end of an edge involved in a bevel */
+typedef struct EdgeHalf {
+ struct EdgeHalf *next, *prev; /* in CCW order */
+ BMEdge *e; /* original mesh edge */
+ int isbev; /* is this edge beveled? */
+ int isrev; /* is e->v2 the vertex at this end? */
+ int seg; /* how many segments for the bevel */
+ float offset; /* offset for this edge */
+ BMFace *fprev; /* face between this edge and previous, if any */
+ BMFace *fnext; /* face between this edge and next, if any */
+ struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */
+ struct BoundVert *rightv; /* right boundary vert, if beveled */
+} EdgeHalf;
+
+/* An element in a cyclic boundary of a Vertex Mesh (VMesh) */
+typedef struct BoundVert {
+ struct BoundVert *next, *prev; /* in CCW order */
+ int index; /* used for vmesh indexing */
+ NewVert nv;
+ EdgeHalf *efirst; /* first of edges attached here: in CCW order */
+ EdgeHalf *elast;
+ EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */
+} BoundVert;
+
+/* Mesh structure replacing a vertex */
+typedef struct VMesh {
+ enum {
+ M_NONE, /* no polygon mesh needed */
+ M_POLY, /* a simple polygon */
+ M_ADJ, /* "adjacent edges" mesh pattern */
+ M_CROSS, /* "cross edges" mesh pattern */
+ } mesh_kind;
+ int count; /* number of vertices in the boundary */
+ int seg; /* common # of segments for segmented edges */
+ BoundVert *boundstart; /* start of boundary double-linked list */
+ NewVert *mesh; /* allocated array - size and structure depends on kind */
+} VMesh;
+
+/* Data for a vertex involved in a bevel */
+typedef struct BevVert {
+ struct BevVert *next, *prev;
+ BMVert *v; /* original mesh vertex */
+ int edgecount; /* total number of edges around the vertex */
+ int selcount; /* number of selected edges around the vertex */
+ EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */
+ VMesh *vmesh; /* mesh structure for replacing vertex */
+} BevVert;
+
+/*
+ * Bevel parameters and state
+ */
+typedef struct BevelParams {
+ ListBase vertList; /* list of BevVert for each vertex involved in bevel */
+ float offset; /* blender units to offset each side of a beveled edge */
+ int seg; /* number of segments in beveled edge profile */
+
+ BMOperator *op;
+} BevelParams;
+
+/* 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. */
+static BoundVert *add_new_bound_vert(VMesh *vm, float co[3])
+{
+ BoundVert *ans = (BoundVert *) MEM_callocN(sizeof(BoundVert), "BoundVert");
+ copy_v3_v3(ans->nv.co, co);
+ if (!vm->boundstart) {
+ ans->index = 0;
+ vm->boundstart = ans;
+ ans->next = ans->prev = ans;
+ }
+ else {
+ BoundVert *tail = vm->boundstart->prev;
+ ans->index = tail->index + 1;
+ ans->prev = tail;
+ ans->next = vm->boundstart;
+ tail->next = ans;
+ vm->boundstart->prev = ans;
+ }
+ vm->count++;
+ return ans;
+}
+
+/* Mesh verts are indexed (i, j, k) where
+ * i = boundvert index (0 <= i < nv)
+ * j = ring index (0 <= j <= ns2)
+ * k = segment index (0 <= k <= ns)
+ * Not all of these are used, and some will share BMVerts */
+static NewVert *mesh_vert(VMesh *vm, int i, int j, int k)
+{
+ int nj = (vm->seg / 2) + 1;
+ int nk = vm->seg + 1;
+
+ return &vm->mesh[i * nk * nj + j * nk + k];
+}
+
+static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert *eg)
+{
+ NewVert *nv = mesh_vert(vm, i, j, k);
+ nv->v = BM_vert_create(bm, nv->co, eg);
+}
+
+static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto,
+ int ifrom, int jfrom, int kfrom)
+{
+ NewVert *nvto, *nvfrom;
+
+ nvto = mesh_vert(vm, ito, jto, kto);
+ nvfrom = mesh_vert(vm, ifrom, jfrom, kfrom);
+ nvto->v = nvfrom->v;
+ copy_v3_v3(nvto->co, nvfrom->co);
+}
+
+/* find the EdgeHalf in bv's array that has edge bme */
+static EdgeHalf *find_edge_half(BevVert *bv, BMEdge *bme)
+{
+ int i;
+
+ for (i = 0; i < bv->edgecount; i++) {
+ if (bv->edges[i].e == bme)
+ return &bv->edges[i];
+ }
+ return NULL;
+}
+
+/* Return the next EdgeHalf after from_e that is beveled.
+ * If from_e is NULL, find the first beveled edge. */
+static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e)
+{
+ EdgeHalf *e;
+
+ if (from_e == NULL)
+ from_e = &bv->edges[bv->edgecount - 1];
+ e = from_e;
+ do {
+ if (e->isbev)
+ return e;
+ e = e->next;
+ } while (e != from_e);
+ return NULL;
+}
+
+/* find the BevVert corresponding to BMVert bmv */
+static BevVert *find_bevvert(BevelParams *bp, BMVert *bmv)
+{
+ BevVert *bv;
+
+ for (bv = bp->vertList.first; bv; bv = bv->next) {
+ if (bv->v == bmv)
+ return bv;
+ }
+ return NULL;
+}
+
+/* Return a good respresentative face (for materials, etc.) for faces
+ * created around/near BoundVert v */
+static BMFace *boundvert_rep_face(BoundVert *v)
+{
+ BMFace *fans = NULL;
+ BMFace *firstf = NULL;
+ BMEdge *e1, *e2;
+ BMFace *f1, *f2;
+ BMIter iter1, iter2;
+
+ BLI_assert(v->efirst != NULL && v->elast != NULL);
+ e1 = v->efirst->e;
+ e2 = v->elast->e;
+ BM_ITER_ELEM (f1, &iter1, e1, BM_FACES_OF_EDGE) {
+ if (!firstf)
+ firstf = f1;
+ BM_ITER_ELEM (f2, &iter2, e2, BM_FACES_OF_EDGE) {
+ if (f1 == f2) {
+ fans = f1;
+ break;
+ }
+ }
+ }
+ if (!fans)
+ fans = firstf;
+
+ return fans;
+}
+
+/* Make ngon from verts alone.
+ * Make sure to properly copy face attributes and do custom data interpolation from
+ * example face, facerep. */
+static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, int totv, BMFace *facerep)
+{
+ BMIter iter;
+ BMLoop *l;
+ BMFace *f;
+
+ if (totv == 3) {
+ f = BM_face_create_quad_tri(bm,
+ vert_arr[0], vert_arr[1], vert_arr[2], NULL, facerep, 0);
+ }
+ else if (totv == 4) {
+ f = BM_face_create_quad_tri(bm,
+ vert_arr[0], vert_arr[1], vert_arr[2], vert_arr[3], facerep, 0);
+ }
+ else {
+ int i;
+ BMEdge *e;
+ BMEdge **ee = NULL;
+ BLI_array_staticdeclare(ee, 30);
+
+ for (i = 0; i < totv; i++) {
+ e = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, TRUE);
+ BLI_array_append(ee, e);
+ }
+ f = BM_face_create_ngon(bm, vert_arr[0], vert_arr[1], ee, totv, FALSE);
+ BLI_array_free(ee);
+ }
+ if (facerep && f) {
+ int has_mdisps = CustomData_has_layer(&bm->ldata, CD_MDISPS);
+ BM_elem_attrs_copy(bm, bm, facerep, f);
+ BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
+ BM_loop_interp_from_face(bm, l, facerep, TRUE, TRUE);
+ if (has_mdisps)
+ BM_loop_interp_multires(bm, l, facerep);
+ }
+ }
+ return f;
+}
+
+static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+ BMFace *facerep)
+{
+ BMVert *varr[4];
+
+ varr[0] = v1;
+ varr[1] = v2;
+ varr[2] = v3;
+ varr[3] = v4;
+ return bev_create_ngon(bm, varr, v4 ? 4 : 3, facerep);
+}
+
+/*
+ * Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco.
+ * e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of
+ * the bevel vertex, e1 precedes e2 in CCW order.
+ * If on_right is true, offset edge is on right of both edges, where e1 enters v and
+ * e2 leave it. If on_right is false, then the offset edge is on the left.
+ * When offsets are equal, the new point is on the edge bisector, with length offset/sin(angle/2),
+ * but if the offsets are not equal (allowing for this, as bevel modifier has edge weights that may
+ * lead to different offsets) then meeting point can be found be intersecting offset lines.
+ */
+static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f,
+ int on_right, float meetco[3])
+{
+ float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3],
+ off1a[3], off1b[3], off2a[3], off2b[3], isect2[3];
+
+ /* 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);
+
+ /* get normal to plane where meet point should be */
+ cross_v3_v3v3(norm_v, dir2, dir1);
+ normalize_v3(norm_v);
+ if (!on_right)
+ negate_v3(norm_v);
+ if (is_zero_v3(norm_v)) {
+ /* 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 */
+ if (f)
+ copy_v3_v3(norm_v, f->no);
+ else
+ copy_v3_v3(norm_v, v->no);
+ cross_v3_v3v3(norm_perp1, dir1, norm_v);
+ normalize_v3(norm_perp1);
+ copy_v3_v3(off1a, v->co);
+ madd_v3_v3fl(off1a, norm_perp1, e1->offset);
+ copy_v3_v3(meetco, off1a);
+ }
+ else {
+ /* get vectors perp to each edge, perp to norm_v, and pointing into face */
+ if (f) {
+ copy_v3_v3(norm_v, f->no);
+ normalize_v3(norm_v);
+ }
+ cross_v3_v3v3(norm_perp1, dir1, norm_v);
+ cross_v3_v3v3(norm_perp2, dir2, norm_v);
+ normalize_v3(norm_perp1);
+ normalize_v3(norm_perp2);
+
+ /* get points that are offset distances from each line, then another point on each line */
+ copy_v3_v3(off1a, v->co);
+ madd_v3_v3fl(off1a, norm_perp1, e1->offset);
+ add_v3_v3v3(off1b, off1a, dir1);
+ copy_v3_v3(off2a, v->co);
+ madd_v3_v3fl(off2a, norm_perp2, e2->offset);
+ add_v3_v3v3(off2b, off2a, dir2);
+
+ /* intersect the lines; by construction they should be on the same plane and not parallel */
+ if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) {
+ BLI_assert(!"offset_meet failure");
+ copy_v3_v3(meetco, off1a); /* just to do something */
+ }
+ }
+}
+
+/* Like offset_meet, but here f1 and f2 must not be NULL and give the
+ * planes in which to run the offset lines. They may not meet exactly,
+ * but the line intersection routine will find the closest approach point. */
+static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, BMVert *v,
+ BMFace *f1, BMFace *f2, float meetco[3])
+{
+ float dir1[3], dir2[3], norm_perp1[3], norm_perp2[3],
+ off1a[3], off1b[3], off2a[3], off2b[3], isect2[3];
+
+ 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);
+
+ /* get directions into offset planes */
+ cross_v3_v3v3(norm_perp1, dir1, f1->no);
+ normalize_v3(norm_perp1);
+ cross_v3_v3v3(norm_perp2, dir2, f2->no);
+ normalize_v3(norm_perp2);
+
+ /* get points that are offset distances from each line, then another point on each line */
+ copy_v3_v3(off1a, v->co);
+ madd_v3_v3fl(off1a, norm_perp1, e1->offset);
+ add_v3_v3v3(off1b, off1a, dir1);
+ copy_v3_v3(off2a, v->co);
+ madd_v3_v3fl(off2a, norm_perp2, e2->offset);
+ add_v3_v3v3(off2b, off2a, dir2);
+
+ /* intersect the lines; by construction they should be on the same plane and not parallel */
+ if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) {
+ BLI_assert(!"offset_meet failure");
+ copy_v3_v3(meetco, off1a); /* just to do something */
+ }
+}
+
+/* Offset by e->offset in plane with normal plane_no, on left if left==TRUE,
+ * else on right. If no is NULL, choose an arbitrary plane different
+ * from eh's direction. */
+static void offset_in_plane(EdgeHalf *e, float plane_no[3], int left, float r[3])
+{
+ float dir[3], no[3];
+ BMVert *v;
+
+ v = e->isrev ? e->e->v1 : e->e->v2;
+
+ sub_v3_v3v3(dir, BM_edge_other_vert(e->e, v)->co, v->co);
+ normalize_v3(dir);
+ if (plane_no) {
+ copy_v3_v3(no, plane_no);
+ }
+ else {
+ zero_v3(no);
+ if (fabs(dir[0]) < fabs(dir[1]))
+ no[0] = 1.0f;
+ else
+ no[1] = 1.0f;
+ }
+ if (left)
+ cross_v3_v3v3(r, no, dir);
+ else
+ cross_v3_v3v3(r, dir, no);
+ normalize_v3(r);
+ mul_v3_fl(r, e->offset);
+}
+
+/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */
+static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3])
+{
+ float dir[3], len;
+
+ sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co);
+ len = len_v3(dir);
+ normalize_v3(dir);
+ if (d > len)
+ d = len - (float)(50 * BEVEL_EPSILON);
+ copy_v3_v3(slideco, v->co);
+ madd_v3_v3fl(slideco, dir, -d);
+}
+
+/* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */
+static void project_to_edge(BMEdge *e, float co_a[3], float co_b[3], float projco[3])
+{
+ float otherco[3];
+
+ if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b,
+ projco, otherco)) {
+ BLI_assert(!"project meet failure");
+ copy_v3_v3(projco, e->v1->co);
+ }
+}
+
+
+/* return 1 if a and b are in CCW order on the normal side of f,
+ * and -1 if they are reversed, and 0 if there is no shared face f */
+static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f)
+{
+ BMLoop *la, *lb;
+
+ if (!f)
+ return 0;
+ la = BM_face_edge_share_loop(f, a);
+ lb = BM_face_edge_share_loop(f, b);
+ if (!la || !lb)
+ return 0;
+ return lb->next == la ? 1 : -1;
+}
+
+/*
+ * calculation of points on the round profile
+ * r - result, coordinate of point on round profile
+ * method:
+ * Inscribe a circle in angle va - v -vb
+ * such that it touches the arms at offset from v.
+ * Rotate the center-va segment by (i/n) of the
+ * angle va - center -vb, and put the endpoint
+ * of that segment in r.
+ */
+static void get_point_on_round_profile(float r[3], float offset, int i, int count,
+ float va[3], float v[3], float vb[3])
+{
+ float vva[3], vvb[3], angle, center[3], rv[3], axis[3], co[3];
+
+ sub_v3_v3v3(vva, va, v);
+ sub_v3_v3v3(vvb, vb, v);
+ normalize_v3(vva);
+ normalize_v3(vvb);
+ angle = angle_v3v3(vva, vvb);
+
+ add_v3_v3v3(center, vva, vvb);
+ normalize_v3(center);
+ mul_v3_fl(center, offset * (1.0f / cosf(0.5f * angle)));
+ add_v3_v3(center, v); /* coordinates of the center of the inscribed circle */
+
+
+ sub_v3_v3v3(rv, va, center); /* radius vector */
+
+
+ sub_v3_v3v3(co, v, center);
+ cross_v3_v3v3(axis, rv, co); /* calculate axis */
+
+ sub_v3_v3v3(vva, va, center);
+ sub_v3_v3v3(vvb, vb, center);
+ angle = angle_v3v3(vva, vvb);
+
+ rotate_v3_v3v3fl(co, rv, axis, angle * (float)(i) / (float)(count));
+
+ add_v3_v3(co, center);
+ copy_v3_v3(r, co);
+}
+
+/*
+ * Find the point (i/n) of the way around the round profile for e,
+ * where start point is va, midarc point is vmid, and end point is vb.
+ * Return the answer in profileco.
+ * Method:
+ * Adjust va and vb (along edge direction) so that they are perpendicular
+ * to edge at v, then use get_point_on_round_profile, then project
+ * back onto original va - vmid - vb plane.
+ * If va, vmid, and vb are all on the same plane, just interpolate between va and vb.
+ */
+static void get_point_on_round_edge(EdgeHalf *e, int i,
+ float va[3], float vmid[3], float vb[3], float profileco[3])
+{
+ float vva[3], vvb[3], point[3], dir[3], vaadj[3], vbadj[3], p2[3], pn[3];
+ int n = e->seg;
+
+ sub_v3_v3v3(vva, va, vmid);
+ sub_v3_v3v3(vvb, vb, vmid);
+ if (e->isrev)
+ sub_v3_v3v3(dir, e->e->v1->co, e->e->v2->co);
+ else
+ sub_v3_v3v3(dir, e->e->v2->co, e->e->v1->co);
+ normalize_v3(dir);
+ if (fabsf(angle_v3v3(vva, vvb) - (float)M_PI) > (float)BEVEL_EPSILON) {
+ copy_v3_v3(vaadj, va);
+ madd_v3_v3fl(vaadj, dir, -len_v3(vva) * cosf(angle_v3v3(vva, dir)));
+ copy_v3_v3(vbadj, vb);
+ madd_v3_v3fl(vbadj, dir, -len_v3(vvb) * cosf(angle_v3v3(vvb, dir)));
+
+ get_point_on_round_profile(point, e->offset, i, n, vaadj, vmid, vbadj);
+
+ add_v3_v3v3(p2, profileco, dir);
+ cross_v3_v3v3(pn, vva, vvb);
+ if (!isect_line_plane_v3(profileco, point, p2, vmid, pn, 0)) {
+ BLI_assert(!"bevel: unexpected non-intersection");
+ copy_v3_v3(profileco, point);
+ }
+ }
+ else {
+ /* planar case */
+ interp_v3_v3v3(profileco, va, vb, (float) i / (float) n);
+ }
+}
+
+static void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3])
+{
+ v[0] = (v1[0] + v2[0] + v3[0]) / 3.0f;
+ v[1] = (v1[1] + v2[1] + v3[1]) / 3.0f;
+ v[2] = (v1[2] + v2[2] + v3[2]) / 3.0f;
+}
+
+/* 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(BevVert *bv)
+{
+ EdgeHalf *efirst, *e;
+ BoundVert *v;
+ VMesh *vm;
+ float co[3], *no;
+ float lastd;
+
+ e = efirst = next_bev(bv, NULL);
+ vm = bv->vmesh;
+
+ BLI_assert(bv->edgecount >= 2); /* since bevel edges incident to 2 faces */
+
+ if (bv->edgecount == 2 && bv->selcount == 1) {
+ /* special case: beveled edge meets non-beveled one at valence 2 vert */
+ no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL);
+ offset_in_plane(e, no, TRUE, co);
+ v = add_new_bound_vert(vm, co);
+ v->efirst = v->elast = v->ebev = e;
+ e->leftv = v;
+ no = e->fnext ? e->fnext->no : (e->fprev ? e->fprev->no : NULL);
+ offset_in_plane(e, no, FALSE, co);
+ v = add_new_bound_vert(vm, co);
+ v->efirst = v->elast = e;
+ e->rightv = v;
+ /* make artifical extra point along unbeveled edge, and form triangle */
+ slide_dist(e->next, bv->v, e->offset, co);
+ v = add_new_bound_vert(vm, co);
+ v->efirst = v->elast = e->next;
+ vm->mesh_kind = M_POLY;
+ return;
+ }
+
+ lastd = e->offset;
+ vm->boundstart = NULL;
+ do {
+ if (e->isbev) {
+ /* handle only left side of beveled edge e here: next iteration should do right side */
+ if (e->prev->isbev) {
+ BLI_assert(e->prev != e); /* see: wire edge special case */
+ offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co);
+ v = add_new_bound_vert(vm, co);
+ v->efirst = e->prev;
+ v->elast = v->ebev = e;
+ e->leftv = v;
+ e->prev->rightv = v;
+ }
+ else {
+ /* e->prev is not beveled */
+ if (e->prev->prev->isbev) {
+ 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 */
+ /* TODO: fix case when one or both faces in following are NULL */
+ offset_in_two_planes(e->prev->prev, e, bv->v,
+ e->prev->prev->fnext, e->fprev, co);
+ v = add_new_bound_vert(vm, co);
+ v->efirst = e->prev->prev;
+ v->elast = v->ebev = e;
+ e->leftv = v;
+ e->prev->leftv = v;
+ e->prev->prev->rightv = v;
+ }
+ else {
+ /* neither e->prev nor e->prev->prev are beveled: make on-edge on e->prev */
+ offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co);
+ v = add_new_bound_vert(vm, co);
+ v->efirst = e->prev;
+ v->elast = v->ebev = e;
+ e->leftv = v;
+ e->prev->leftv = v;
+ }
+ }
+ lastd = len_v3v3(bv->v->co, v->nv.co);
+ }
+ else {
+ /* e is not beveled */
+ if (e->next->isbev) {
+ /* next iteration will place e between beveled previous and next edges */
+ e = e->next;
+ continue;
+ }
+ if (e->prev->isbev) {
+ /* on-edge meet between e->prev and e */
+ offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co);
+ v = add_new_bound_vert(vm, co);
+ v->efirst = e->prev;
+ v->elast = e;
+ e->leftv = v;
+ e->prev->rightv = v;
+ }
+ else {
+ /* None of e->prev, e, e->next are beveled.
+ * could either leave alone or add slide points to make
+ * one polygon around bv->v. For now, we choose latter.
+ * Could slide to make an even bevel plane but for now will
+ * just use last distance a meet point moved from bv->v. */
+ slide_dist(e, bv->v, lastd, co);
+ v = add_new_bound_vert(vm, co);
+ v->efirst = v->elast = e;
+ e->leftv = v;
+ }
+ }
+ e = e->next;
+ } while (e != efirst);
+
+ BLI_assert(vm->count >= 2);
+ if (vm->count == 2 && bv->edgecount == 3)
+ vm->mesh_kind = M_NONE;
+ else if (efirst->seg == 1 || bv->selcount < 3)
+ vm->mesh_kind = M_POLY;
+ else
+ vm->mesh_kind = M_ADJ;
+ /* TODO: if vm->count == 4 and bv->selcount == 4, use M_CROSS pattern */
+}
+
+/*
+ * Given that the boundary is built and the boundary BMVerts have been made,
+ * calculate the positions of the interior mesh points for the M_ADJ pattern,
+ * then make the BMVerts and the new faces. */
+static void bevel_build_rings(BMesh *bm, BevVert *bv)
+{
+ int k, ring, i, n, ns, ns2, nn;
+ VMesh *vm = bv->vmesh;
+ BoundVert *v, *vprev, *vnext;
+ NewVert *nv, *nvprev, *nvnext;
+ BMVert *bmv, *bmv1, *bmv2, *bmv3, *bmv4;
+ BMFace *f;
+ float co[3], coa[3], cob[3], midco[3];
+
+ n = vm->count;
+ ns = vm->seg;
+ ns2 = ns / 2;
+ BLI_assert(n > 2 && ns > 1);
+
+ /* Make initial rings, going between points on neighbors */
+ for (ring = 1; ring <= ns2; ring++) {
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ if (v->ebev) {
+ /* get points coords of points a and b, on outer rings
+ * of prev and next edges, k away from this edge */
+ vprev = v->prev;
+ vnext = v->next;
+
+ if (vprev->ebev)
+ nvprev = mesh_vert(vm, vprev->index, 0, ns - ring);
+ else
+ nvprev = mesh_vert(vm, vprev->index, 0, ns);
+ copy_v3_v3(coa, nvprev->co);
+ nv = mesh_vert(vm, i, ring, 0);
+ copy_v3_v3(nv->co, coa);
+ nv->v = nvprev->v;
+
+ if (vnext->ebev)
+ nvnext = mesh_vert(vm, vnext->index, 0, ring);
+ else
+ nvnext = mesh_vert(vm, vnext->index, 0, 0);
+ copy_v3_v3(cob, nvnext->co);
+ nv = mesh_vert(vm, i, ring, ns);
+ copy_v3_v3(nv->co, cob);
+ nv->v = nvnext->v;
+
+ /* TODO: better calculation of new midarc point? */
+ project_to_edge(v->ebev->e, coa, cob, midco);
+
+ for (k = 1; k < ns; k++) {
+ get_point_on_round_edge(v->ebev, k, coa, midco, cob, co);
+ copy_v3_v3(mesh_vert(vm, i, ring, k)->co, co);
+ }
+ }
+ v = v->next;
+ } while (v != vm->boundstart);
+ }
+
+ /* Now make sure cross points of rings share coordinates and vertices */
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ if (v->ebev) {
+ vprev = v->prev;
+ vnext = v->next;
+ if (vprev->ebev) {
+ for (ring = 1; ring <= ns2; ring++) {
+ for (k = 1; k <= ns2; k++) {
+ if (ns % 2 == 0 && (k == ns2 || ring == ns2))
+ continue; /* center line is special case: do after the rest are done */
+ nv = mesh_vert(vm, i, ring, k);
+ nvprev = mesh_vert(vm, vprev->index, k, ns - ring);
+ mid_v3_v3v3(co, nv->co, nvprev->co);
+ copy_v3_v3(nv->co, co);
+ 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);
+ }
+ }
+ if (!vprev->prev->ebev) {
+ for (ring = 1; ring <= ns2; ring++) {
+ for (k = 1; k <= ns2; k++) {
+ if (ns % 2 == 0 && (k == ns2 || ring == ns2))
+ continue;
+ create_mesh_bmvert(bm, vm, vprev->index, ring, k, bv->v);
+ }
+ }
+ }
+ if (!vnext->ebev) {
+ for (ring = 1; ring <= ns2; ring++) {
+ for (k = ns - ns2; k < ns; k++) {
+ if (ns % 2 == 0 && (k == ns2 || ring == ns2))
+ continue;
+ create_mesh_bmvert(bm, vm, i, ring, k, bv->v);
+ }
+ }
+ }
+ }
+ }
+ v = v->next;
+ } while (v != vm->boundstart);
+
+ if (ns % 2 == 0) {
+ /* do special case center lines */
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ if (v->ebev) {
+ vprev = v->prev;
+ vnext = v->next;
+ for (k = 1; k < ns2; k++) {
+ nv = mesh_vert(vm, i, k, ns2);
+ if (vprev->ebev)
+ nvprev = mesh_vert(vm, vprev->index, ns2, ns - k);
+ if (vnext->ebev)
+ nvnext = mesh_vert(vm, vnext->index, ns2, k);
+ if (vprev->ebev && vnext->ebev) {
+ mid_v3_v3v3v3(co, nvprev->co, nv->co, nvnext->co);
+ copy_v3_v3(nv->co, co);
+ 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);
+
+ }
+ else if (vprev->ebev) {
+ mid_v3_v3v3(co, nvprev->co, nv->co);
+ copy_v3_v3(nv->co, co);
+ create_mesh_bmvert(bm, vm, i, k, ns2, bv->v);
+ copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2);
+ }
+ else if (vnext->ebev) {
+ mid_v3_v3v3(co, nv->co, nvnext->co);
+ copy_v3_v3(nv->co, co);
+ create_mesh_bmvert(bm, vm, i, k, ns2, bv->v);
+ copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2);
+ }
+ }
+ }
+ v = v->next;
+ } while (v != vm->boundstart);
+
+ /* center point need to be average of all centers of rings */
+ /* TODO: this is wrong if not all verts have ebev: could have
+ * several disconnected sections of mesh. */
+ zero_v3(midco);
+ nn = 0;
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ if (v->ebev) {
+ nv = mesh_vert(vm, i, ns2, ns2);
+ add_v3_v3(midco, nv->co);
+ nn++;
+ }
+ v = v->next;
+ } while (v != vm->boundstart);
+ mul_v3_fl(midco, 1.0f / nn);
+ bmv = BM_vert_create(bm, midco, NULL);
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ if (v->ebev) {
+ nv = mesh_vert(vm, i, ns2, ns2);
+ copy_v3_v3(nv->co, midco);
+ nv->v = bmv;
+ }
+ v = v->next;
+ } while (v != vm->boundstart);
+ }
+
+ /* Make the ring quads */
+ for (ring = 0; ring < ns2; ring++) {
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ f = boundvert_rep_face(v);
+ if (v->ebev && (v->prev->ebev || v->next->ebev)) {
+ for (k = 0; k < ns2 + (ns % 2); k++) {
+ bmv1 = mesh_vert(vm, i, ring, k)->v;
+ bmv2 = mesh_vert(vm, i, ring, k + 1)->v;
+ bmv3 = mesh_vert(vm, i, ring + 1, k + 1)->v;
+ bmv4 = mesh_vert(vm, i, ring + 1, k)->v;
+ BLI_assert(bmv1 && bmv2 && bmv3 && bmv4);
+ if (bmv3 == bmv4 || bmv1 == bmv4)
+ bmv4 = NULL;
+ bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f);
+ }
+ }
+ else if (v->prev->ebev && v->prev->prev->ebev) {
+ /* finish off a sequence of beveled edges */
+ i = v->prev->index;
+ f = boundvert_rep_face(v->prev);
+ for (k = ns2 + (ns % 2); k < ns; k++) {
+ bmv1 = mesh_vert(vm, i, ring + 1, k)->v;
+ bmv2 = mesh_vert(vm, i, ring, k)->v;
+ bmv3 = mesh_vert(vm, i, ring, k + 1)->v;
+ BLI_assert(bmv1 && bmv2 && bmv3);
+ bev_create_quad_tri(bm, bmv1, bmv2, bmv3, NULL, f);
+ }
+ }
+ v = v->next;
+ } while (v != vm->boundstart);
+ }
+
+ /* 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);
+
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ BLI_assert(v->ebev);
+ BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v);
+ v = v->next;
+ } while (v != vm->boundstart);
+ f = boundvert_rep_face(vm->boundstart);
+ bev_create_ngon(bm, vv, BLI_array_count(vv), f);
+
+ BLI_array_free(vv);
+ }
+
+ /* Make 'rest-of-vmesh' polygon if not fully beveled */
+ if (vm->count > bv->selcount) {
+ int j;
+ BMVert **vv = NULL;
+ BLI_array_declare(vv);
+
+ v = vm->boundstart;
+ f = boundvert_rep_face(v);
+ j = 0;
+ do {
+ i = v->index;
+ if (v->ebev) {
+ if (!v->prev->ebev) {
+ for (k = 0; k < ns2; k++) {
+ bmv1 = mesh_vert(vm, i, ns2, k)->v;
+ if (!(j > 0 && bmv1 == vv[j - 1])) {
+ BLI_array_append(vv, bmv1);
+ j++;
+ }
+ }
+ }
+ bmv1 = mesh_vert(vm, i, ns2, ns2)->v;
+ if (!(j > 0 && bmv1 == vv[j - 1])) {
+ BLI_array_append(vv, bmv1);
+ j++;
+ }
+ if (!v->next->ebev) {
+ for (k = ns - ns2; k < ns; k++) {
+ bmv1 = mesh_vert(vm, i, ns2, k)->v;
+ if (!(j > 0 && bmv1 == vv[j - 1])) {
+ BLI_array_append(vv, bmv1);
+ j++;
+ }
+ }
+ }
+ }
+ else {
+ BLI_array_append(vv, mesh_vert(vm, i, 0, 0)->v);
+ j++;
+ }
+ v = v->next;
+ } while (v != vm->boundstart);
+ if (vv[0] == vv[j - 1])
+ j--;
+ bev_create_ngon(bm, vv, j, f);
+
+ BLI_array_free(vv);
+ }
+}
+
+static void bevel_build_poly(BMesh *bm, BevVert *bv)
+{
+ int n, k;
+ VMesh *vm = bv->vmesh;
+ BoundVert *v;
+ BMVert **vv = NULL;
+ BLI_array_declare(vv);
+
+ v = vm->boundstart;
+ n = 0;
+ do {
+ /* accumulate vertices for vertex ngon */
+ BLI_array_append(vv, v->nv.v);
+ n++;
+ if (v->ebev && v->ebev->seg > 1) {
+ for (k = 1; k < v->ebev->seg; k++) {
+ BLI_array_append(vv, mesh_vert(vm, v->index, 0, k)->v);
+ n++;
+ }
+ }
+ v = v->next;
+ } while (v != vm->boundstart);
+ if (n > 2)
+ bev_create_ngon(bm, vv, n, boundvert_rep_face(v));
+ BLI_array_free(vv);
+}
+
+/* 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(BMesh *bm, BevVert *bv)
+{
+ VMesh *vm = bv->vmesh;
+ BoundVert *v, *weld1, *weld2;
+ int n, ns, ns2, i, k, weld;
+ float *va, *vb, co[3], midco[3];
+
+ n = vm->count;
+ ns = vm->seg;
+ ns2 = ns / 2;
+
+ vm->mesh = (NewVert *)MEM_callocN(n * (ns2 + 1) * (ns + 1) * sizeof(NewVert), "NewVert");
+
+ /* special case: two beveled ends welded together */
+ weld = (bv->selcount == 2) && (vm->count == 2);
+ weld1 = weld2 = NULL; /* will hold two BoundVerts involved in weld */
+
+ /* make (i, 0, 0) mesh verts for all i */
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ copy_v3_v3(mesh_vert(vm, i, 0, 0)->co, v->nv.co);
+ create_mesh_bmvert(bm, vm, i, 0, 0, bv->v);
+ v->nv.v = mesh_vert(vm, i, 0, 0)->v;
+ if (weld && v->ebev) {
+ if (!weld1)
+ weld1 = v;
+ else
+ weld2 = v;
+ }
+ v = v->next;
+ } while (v != vm->boundstart);
+
+ /* copy other ends to (i, 0, ns) for all i, and fill in profiles for beveled edges */
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ copy_mesh_vert(vm, i, 0, ns, v->next->index, 0, 0);
+ if (v->ebev) {
+ 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);
+ 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);
+ }
+ }
+ v = v->next;
+ } while (v != vm->boundstart);
+
+ if (weld) {
+ for (k = 1; k < ns; k++) {
+ mid_v3_v3v3(co, mesh_vert(vm, weld1->index, 0, k)->co,
+ mesh_vert(vm, weld2->index, 0, ns - k)->co);
+ copy_v3_v3(mesh_vert(vm, weld1->index, 0, k)->co, co);
+ create_mesh_bmvert(bm, vm, weld1->index, 0, k, bv->v);
+ }
+ for (k = 1; k < ns; k++)
+ copy_mesh_vert(vm, weld2->index, 0, ns - k, weld1->index, 0, k);
+ }
+
+ if (vm->mesh_kind == M_ADJ)
+ bevel_build_rings(bm, bv);
+ else if (vm->mesh_kind == M_POLY)
+ bevel_build_poly(bm, bv);
+}
+
+/*
+ * Construction around the vertex
+ */
+static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMVert *v)
+{
+
+ BMOIter siter;
+ BMEdge *bme;
+ BevVert *bv;
+ BMEdge *bme2, *unflagged_bme;
+ BMFace *f;
+ BMIter iter, iter2;
+ EdgeHalf *e;
+ int i, ntot, found_shared_face, ccw_test_sum;
+ int nsel = 0;
+
+ /* Gather input selected edges.
+ * Only bevel selected edges that have exactly two incident faces. */
+ BMO_ITER (bme, &siter, bm, op, "geom", BM_EDGE) {
+ if ((bme->v1 == v) || (BM_edge_other_vert(bme, bme->v1) == v)) {
+ if (BM_edge_face_count(bme) == 2) {
+ BMO_elem_flag_enable(bm, bme, EDGE_SELECTED);
+ nsel++;
+ }
+ }
+ }
+
+ if (nsel == 0)
+ return;
+
+ ntot = BM_vert_edge_count(v);
+ bv = (BevVert *)MEM_callocN(sizeof(BevVert), "BevVert");
+ bv->v = v;
+ bv->edgecount = ntot;
+ bv->selcount = nsel;
+ bv->edges = (EdgeHalf *)MEM_callocN(ntot * sizeof(EdgeHalf), "EdgeHalf");
+ bv->vmesh = (VMesh *)MEM_callocN(sizeof(VMesh), "VMesh");
+ bv->vmesh->seg = bp->seg;
+ BLI_addtail(&bp->vertList, bv);
+
+ /* add edges to bv->edges in order that keeps adjacent edges sharing
+ * a face, if possible */
+ i = 0;
+ bme = v->e;
+ BMO_elem_flag_enable(bm, bme, BEVEL_FLAG);
+ e = &bv->edges[0];
+ e->e = bme;
+ for (i = 0; i < ntot; i++) {
+ if (i > 0) {
+ /* find an unflagged edge bme2 that shares a face f with previous bme */
+ found_shared_face = 0;
+ unflagged_bme = NULL;
+ BM_ITER_ELEM (bme2, &iter, v, BM_EDGES_OF_VERT) {
+ if (BMO_elem_flag_test(bm, bme2, BEVEL_FLAG))
+ continue;
+ if (!unflagged_bme)
+ unflagged_bme = bme2;
+ BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) {
+ if (BM_face_edge_share_loop(f, bme)) {
+ found_shared_face = 1;
+ break;
+ }
+ }
+ if (found_shared_face)
+ break;
+ }
+ e = &bv->edges[i];
+ if (found_shared_face) {
+ e->e = bme2;
+ e->fprev = f;
+ bv->edges[i - 1].fnext = f;
+ }
+ else {
+ e->e = unflagged_bme;
+ }
+ }
+ bme = e->e;
+ BMO_elem_flag_enable(bm, bme, BEVEL_FLAG);
+ if (BMO_elem_flag_test(bm, bme, EDGE_SELECTED)) {
+ e->isbev = 1;
+ e->seg = bp->seg;
+ }
+ else {
+ e->isbev = 0;
+ e->seg = 0;
+ }
+ e->isrev = (bme->v2 == v);
+ e->offset = e->isbev ? bp->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].fnext == f)
+ continue; /* if two shared faces, want the other one now */
+ bv->edges[ntot - 1].fnext = f;
+ bv->edges[0].fprev = f;
+ break;
+ }
+ }
+
+ /* remove BEVEL_FLAG now that we are finished with it*/
+ for (i = 0; i < ntot; i++)
+ BMO_elem_flag_disable(bm, bv->edges[i].e, BEVEL_FLAG);
+
+ /* if edge array doesn't go CCW around vertex from average normal side,
+ * reverse the array, being careful to reverse face pointers too */
+ if (ntot > 1) {
+ ccw_test_sum = 0;
+ for (i = 0; i < ntot; i++)
+ ccw_test_sum += bev_ccw_test(bv->edges[i].e, bv->edges[(i + 1) % ntot].e,
+ bv->edges[i].fnext);
+ if (ccw_test_sum < 0) {
+ for (i = 0; i <= (ntot / 2) - 1; i++) {
+ SWAP(EdgeHalf, bv->edges[i], bv->edges[ntot - i - 1]);
+ SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext);
+ SWAP(BMFace *, bv->edges[ntot - i - 1].fprev, bv->edges[ntot - i - 1].fnext);
+ }
+ if (ntot % 2 == 1) {
+ i = ntot / 2;
+ SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext);
+ }
+ }
+ }
+
+ for (i = 0; i < ntot; i++) {
+ e = &bv->edges[i];
+ e->next = &bv->edges[(i + 1) % ntot];
+ e->prev = &bv->edges[(i + ntot - 1) % ntot];
+ }
+
+ build_boundary(bv);
+ build_vmesh(bm, bv);
+}
+
+/* Face f has at least one beveled vertex. Rebuild f */
+static void rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
+{
+ BMIter liter;
+ BMLoop *l, *lprev;
+ BevVert *bv;
+ BoundVert *v, *vstart, *vend;
+ EdgeHalf *e, *eprev;
+ VMesh *vm;
+ int i, k;
+ BMVert *bmv;
+ BMVert **vv = NULL;
+ BLI_array_declare(vv);
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ bv = find_bevvert(bp, l->v);
+ if (bv) {
+ lprev = l->prev;
+ e = find_edge_half(bv, l->e);
+ eprev = find_edge_half(bv, lprev->e);
+ BLI_assert(e != NULL && eprev != NULL);
+ vstart = eprev->leftv;
+ if (e->isbev)
+ vend = e->rightv;
+ else
+ vend = e->leftv;
+ v = vstart;
+ vm = bv->vmesh;
+ BLI_array_append(vv, v->nv.v);
+ while (v != vend) {
+ if (vm->mesh_kind == M_NONE && v->ebev && v->ebev->seg > 1 && v->ebev != e && v->ebev != eprev) {
+ /* case of 3rd face opposite a beveled edge, with no vmesh */
+ i = v->index;
+ e = v->ebev;
+ for (k = 1; k < e->seg; k++) {
+ bmv = mesh_vert(vm, i, 0, k)->v;
+ BLI_array_append(vv, bmv);
+ }
+ }
+ v = v->prev;
+ BLI_array_append(vv, v->nv.v);
+ }
+ }
+ else {
+ BLI_array_append(vv, l->v);
+ }
+ }
+ bev_create_ngon(bm, vv, BLI_array_count(vv), f);
+ BLI_array_free(vv);
+}
+
+/* All polygons touching v need rebuilding because beveling v has made new vertices */
+static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert *v)
+{
+ BMFace *f;
+ BMIter iter;
+
+ /* TODO: don't iterate through all faces, but just local geometry around v */
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BMLoop *l = f->l_first;
+ do {
+ if (l->v == v) {
+ rebuild_polygon(bm, bp, f);
+ BM_face_kill(bm, f);
+ }
+ l = l->next;
+ } while (l != f->l_first);
+ }
+}
+
+
+
+/*
+ * Build the polygons along the selected Edge
+ */
+static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
+{
+ BevVert *bv1, *bv2;
+ BMVert *bmv1, *bmv2, *bmv3, *bmv4, *bmv1i, *bmv2i, *bmv3i, *bmv4i;
+ VMesh *vm1, *vm2;
+ EdgeHalf *e1, *e2;
+ BMFace *f1, *f2, *f;
+ int k, nseg, i1, i2;
+
+ if (BM_edge_face_count(bme) != 2)
+ return;
+
+ bv1 = find_bevvert(bp, bme->v1);
+ bv2 = find_bevvert(bp, bme->v2);
+
+ BLI_assert(bv1 && bv2);
+
+ e1 = find_edge_half(bv1, bme);
+ e2 = find_edge_half(bv2, bme);
+
+ BLI_assert(e1 && e2);
+
+ /* v4 v3
+ * \ /
+ * e->v1 - e->v2
+ * / \
+ * v1 v2 */
+
+ nseg = e1->seg;
+ BLI_assert(nseg > 0 && nseg == e2->seg);
+
+ bmv1 = e1->leftv->nv.v;
+ bmv4 = e1->rightv->nv.v;
+ bmv2 = e2->rightv->nv.v;
+ bmv3 = e2->leftv->nv.v;
+
+ BLI_assert(bmv1 && bmv2 && bmv3 && bmv4);
+
+ f1 = boundvert_rep_face(e1->leftv);
+ f2 = boundvert_rep_face(e1->rightv);
+
+ if (nseg == 1) {
+ bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f1);
+ }
+ else {
+ i1 = e1->leftv->index;
+ i2 = e2->leftv->index;
+ vm1 = bv1->vmesh;
+ vm2 = bv2->vmesh;
+ bmv1i = bmv1;
+ bmv2i = bmv2;
+ for (k = 1; k <= nseg; k++) {
+ bmv4i = mesh_vert(vm1, i1, 0, k)->v;
+ bmv3i = mesh_vert(vm2, i2, 0, nseg - k)->v;
+ f = (k <= nseg / 2 + (nseg % 2)) ? f1 : f2;
+ bev_create_quad_tri(bm, bmv1i, bmv2i, bmv3i, bmv4i, f);
+ bmv1i = bmv4i;
+ bmv2i = bmv3i;
+ }
+ }
+}
+
+
+static void free_bevel_params(BevelParams *bp)
+{
+ BevVert *bv;
+ VMesh *vm;
+ BoundVert *v, *vnext;
+
+ for (bv = bp->vertList.first; bv; bv = bv->next) {
+ MEM_freeN(bv->edges);
+ vm = bv->vmesh;
+ v = vm->boundstart;
+ if (v) {
+ do {
+ vnext = v->next;
+ MEM_freeN(v);
+ v = vnext;
+ } while (v != vm->boundstart);
+ }
+ if (vm->mesh)
+ MEM_freeN(vm->mesh);
+ MEM_freeN(vm);
+ }
+ BLI_freelistN(&bp->vertList);
+}
+
+void bmo_bevel_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMVert *v;
+ BMEdge *e;
+ BevelParams bp;
+
+ bp.offset = BMO_slot_float_get(op, "offset");
+ bp.op = op;
+ bp.seg = BMO_slot_int_get(op, "segments");
+
+ if (bp.offset > 0) {
+ bp.vertList.first = bp.vertList.last = NULL;
+
+ /* The analysis of the input vertices and execution additional constructions */
+ BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) {
+ bevel_vert_construct(bm, &bp, op, v);
+ }
+ /* Build polygons for edges */
+ BMO_ITER (e, &siter, bm, op, "geom", BM_EDGE) {
+ bevel_build_edge_polygons(bm, &bp, e);
+ }
+
+ BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) {
+ bevel_rebuild_existing_polygons(bm, &bp, v);
+ }
+
+ BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) {
+ if (find_bevvert(&bp, v))
+ BM_vert_kill(bm, v);
+ }
+ free_bevel_params(&bp);
+ }
+
+}
+
+#else
+#define BEVEL_FLAG 1
+#define BEVEL_DEL 2
+#define FACE_NEW 4
+#define EDGE_OLD 8
+#define FACE_OLD 16
+#define VERT_OLD 32
+#define FACE_SPAN 64
+#define FACE_HOLE 128
typedef struct LoopTag {
BMVert *newv;
@@ -56,7 +1401,7 @@ typedef struct EdgeTag {
static void calc_corner_co(BMLoop *l, const float fac, float r_co[3],
const short do_dist, const short do_even)
{
- float no[3], l_vec_prev[3], l_vec_next[3], l_co_prev[3], l_co[3], l_co_next[3], co_ofs[3];
+ float no[3], l_vec_prev[3], l_vec_next[3], l_co_prev[3], l_co[3], l_co_next[3], co_ofs[3];
int is_concave;
/* first get the prev/next verts */
@@ -299,7 +1644,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
/* find all faces surrounding e->v1 and, e->v2 */
for (i = 0; i < 2; i++) {
- BM_ITER_ELEM (l, &liter, i ? e->v2:e->v1, BM_LOOPS_OF_VERT) {
+ BM_ITER_ELEM (l, &liter, i ? e->v2 : e->v1, BM_LOOPS_OF_VERT) {
BMLoop *l2;
BMIter liter2;
@@ -886,3 +2231,4 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
BMO_slot_buffer_from_enabled_flag(bm, op, "face_spans", BM_FACE, FACE_SPAN);
BMO_slot_buffer_from_enabled_flag(bm, op, "face_holes", BM_FACE, FACE_HOLE);
}
+#endif /* NEW_BEVEL */
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index bd1c0f809bd..093f567d995 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -1177,10 +1177,10 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op)
}
if (edges1 && BLI_array_count(edges1) > 2 &&
- BM_edge_share_vert_count(edges1[0], edges1[BLI_array_count(edges1) - 1]))
+ BM_edge_share_vert_check(edges1[0], edges1[BLI_array_count(edges1) - 1]))
{
if (edges2 && BLI_array_count(edges2) > 2 &&
- BM_edge_share_vert_count(edges2[0], edges2[BLI_array_count(edges2) - 1]))
+ BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1]))
{
BLI_array_free(edges1);
BLI_array_free(edges2);
@@ -1193,7 +1193,7 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op)
}
if (edges2 && BLI_array_count(edges2) > 2 &&
- BM_edge_share_vert_count(edges2[0], edges2[BLI_array_count(edges2) - 1]))
+ BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1]))
{
edges2 = NULL;
}
diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c
index 013b6183f84..b9c9398fbfa 100644
--- a/source/blender/bmesh/operators/bmo_hull.c
+++ b/source/blender/bmesh/operators/bmo_hull.c
@@ -426,12 +426,12 @@ static int hull_input_vert_count(BMesh *bm, BMOperator *op)
}
static BMVert **hull_input_verts_copy(BMesh *bm, BMOperator *op,
- const int num_input_verts)
+ const int num_input_verts)
{
BMOIter oiter;
BMVert *v;
BMVert **input_verts = MEM_callocN(sizeof(*input_verts) *
- num_input_verts, AT);
+ num_input_verts, AT);
int i = 0;
BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) {
@@ -442,7 +442,7 @@ static BMVert **hull_input_verts_copy(BMesh *bm, BMOperator *op,
}
static float (*hull_verts_for_bullet(BMVert **input_verts,
- const int num_input_verts))[3]
+ const int num_input_verts))[3]
{
float (*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, AT);
int i;
@@ -455,12 +455,12 @@ static float (*hull_verts_for_bullet(BMVert **input_verts,
}
static BMVert **hull_verts_from_bullet(plConvexHull hull,
- BMVert **input_verts,
- const int num_input_verts)
+ BMVert **input_verts,
+ const int num_input_verts)
{
const int num_verts = plConvexHullNumVertices(hull);
BMVert **hull_verts = MEM_mallocN(sizeof(*hull_verts) *
- num_verts, AT);
+ num_verts, AT);
int i;
for (i = 0; i < num_verts; i++) {
@@ -479,8 +479,8 @@ static BMVert **hull_verts_from_bullet(plConvexHull hull,
}
static void hull_from_bullet(BMesh *bm, BMOperator *op,
- GHash *hull_triangles,
- BLI_mempool *pool)
+ GHash *hull_triangles,
+ BLI_mempool *pool)
{
int *fvi = NULL;
BLI_array_declare(fvi);
@@ -523,7 +523,7 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op,
fv[2] = hull_verts[fvi[j]];
hull_add_triangle(bm, hull_triangles, pool,
- fv[0], fv[1], fv[2]);
+ fv[0], fv[1], fv[2]);
}
}
}
diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
index 51b9adb5de3..362123e412d 100644
--- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c
+++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
@@ -43,8 +43,8 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f
-#define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f
+// #define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f /* UNUSED */
+// #define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f /* UNUSED */
#define SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE 1.8f
#define SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE 0.15f
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index 346daf830d0..f6b9b18d716 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -825,7 +825,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
/* make sure the two edges have a valid angle to each other */
- if (totesel == 2 && BM_edge_share_vert_count(e1, e2)) {
+ if (totesel == 2 && BM_edge_share_vert_check(e1, e2)) {
sub_v3_v3v3(vec1, e1->v2->co, e1->v1->co);
sub_v3_v3v3(vec2, e2->v2->co, e2->v1->co);
normalize_v3(vec1);
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index e311b383b86..aa514a5c0a7 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -282,7 +282,7 @@ void bmo_region_extend_exec(BMesh *bm, BMOperator *op)
#define FACE_VIS 1
#define FACE_FLAG 2
-#define FACE_MARK 4
+// #define FACE_MARK 4 /* UNUSED */
#define FACE_FLIP 8
/* NOTE: these are the original recalc_face_normals comment in editmesh_mods.c,
diff --git a/source/blender/compositor/nodes/COM_ScaleNode.cpp b/source/blender/compositor/nodes/COM_ScaleNode.cpp
index c51782b77af..d535e71a33c 100644
--- a/source/blender/compositor/nodes/COM_ScaleNode.cpp
+++ b/source/blender/compositor/nodes/COM_ScaleNode.cpp
@@ -26,6 +26,7 @@
#include "COM_ExecutionSystem.h"
#include "BKE_node.h"
#include "COM_SetValueOperation.h"
+#include "COM_SetSamplerOperation.h"
ScaleNode::ScaleNode(bNode *editorNode) : Node(editorNode)
{
@@ -38,7 +39,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
InputSocket *inputXSocket = this->getInputSocket(1);
InputSocket *inputYSocket = this->getInputSocket(2);
OutputSocket *outputSocket = this->getOutputSocket(0);
+ BaseScaleOperation *scaleoperation;
bNode *bnode = this->getbNode();
+
switch (bnode->custom1) {
case CMP_SCALE_RELATIVE: {
ScaleOperation *operation = new ScaleOperation();
@@ -46,8 +49,8 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
inputXSocket->relinkConnections(operation->getInputSocket(1), 1, graph);
inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph);
- outputSocket->relinkConnections(operation->getOutputSocket(0));
- graph->addOperation(operation);
+
+ scaleoperation = operation;
}
break;
case CMP_SCALE_SCENEPERCENT: {
@@ -57,9 +60,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
addLink(graph, scaleFactorOperation->getOutputSocket(), operation->getInputSocket(1));
addLink(graph, scaleFactorOperation->getOutputSocket(), operation->getInputSocket(2));
- outputSocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(scaleFactorOperation);
- graph->addOperation(operation);
+
+ scaleoperation = operation;
}
break;
@@ -75,9 +78,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
operation->setNewWidth(rd->xsch * rd->size / 100.0f);
operation->setNewHeight(rd->ysch * rd->size / 100.0f);
inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
- outputSocket->relinkConnections(operation->getOutputSocket(0));
operation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true);
- graph->addOperation(operation);
+
+ scaleoperation = operation;
}
break;
@@ -87,9 +90,12 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
inputXSocket->relinkConnections(operation->getInputSocket(1), 1, graph);
inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph);
- outputSocket->relinkConnections(operation->getOutputSocket(0));
- graph->addOperation(operation);
+
+ scaleoperation = operation;
}
break;
}
+
+ outputSocket->relinkConnections(scaleoperation->getOutputSocket(0));
+ graph->addOperation(scaleoperation);
}
diff --git a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp
index b28ee3eade1..a579503a829 100644
--- a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp
+++ b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp
@@ -72,6 +72,8 @@ void Stabilize2dNode::convertToOperations(ExecutionSystem *graph, CompositorCont
addLink(graph, scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(1));
addLink(graph, scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(2));
+ scaleOperation->setSampler((PixelSampler)this->getbNode()->custom1);
+
addLink(graph, scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
addLink(graph, angleAttribute->getOutputSocket(), rotateOperation->getInputSocket(1));
rotateOperation->setDoDegree2RadConversion(false);
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
index df48c7a6716..68a61dff801 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
@@ -50,6 +50,7 @@ MovieDistortionOperation::MovieDistortionOperation(bool distortion) : NodeOperat
this->m_cache = NULL;
this->m_distortion = distortion;
}
+
void MovieDistortionOperation::initExecution()
{
this->m_inputOperation = this->getInputSocketReader(0);
@@ -105,21 +106,9 @@ void MovieDistortionOperation::executePixel(float output[4], float x, float y, P
if (this->m_cache != NULL) {
float u, v;
this->m_cache->getUV(&this->m_movieClip->tracking, x, y, &u, &v);
- this->m_inputOperation->read(output, u, v, sampler);
+ this->m_inputOperation->read(output, u, v, COM_PS_BILINEAR);
}
else {
- this->m_inputOperation->read(output, x, y, sampler);
+ this->m_inputOperation->read(output, x, y, COM_PS_BILINEAR);
}
}
-
-bool MovieDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
-{
- rcti newInput;
-
- newInput.xmax = input->xmax + 100;
- newInput.xmin = input->xmin - 100;
- newInput.ymax = input->ymax + 100;
- newInput.ymin = input->ymin - 100;
-
- 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 93cc555fdbc..9f8aa065e3e 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
@@ -155,7 +155,6 @@ protected:
public:
MovieDistortionOperation(bool distortion);
- bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
void executePixel(float output[4], float x, float y, PixelSampler sampler);
void initExecution();
diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp
index a4015c6283f..2ca499683d3 100644
--- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp
+++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp
@@ -69,6 +69,46 @@ void RenderLayersBaseProg::initExecution()
}
}
+void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler)
+{
+ unsigned int offset;
+ int ix, iy;
+ int width = this->getWidth(), height = this->getHeight();
+
+ switch (sampler) {
+ case COM_PS_NEAREST:
+ ix = x;
+ iy = y;
+ offset = (iy * width + ix) * this->m_elementsize;
+
+ if (this->m_elementsize == 1)
+ output[0] = this->m_inputBuffer[offset];
+ else if (this->m_elementsize == 3)
+ copy_v3_v3(output, &this->m_inputBuffer[offset]);
+ else
+ copy_v4_v4(output, &this->m_inputBuffer[offset]);
+
+ break;
+
+ case COM_PS_BILINEAR:
+ BLI_bilinear_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
+ break;
+
+ case COM_PS_BICUBIC:
+ BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
+ break;
+ }
+
+ if (this->m_elementsize == 1) {
+ output[1] = 0.0f;
+ output[2] = 0.0f;
+ output[3] = 0.0f;
+ }
+ else if (this->m_elementsize == 3) {
+ output[3] = 1.0f;
+ }
+}
+
void RenderLayersBaseProg::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
int ix = x;
@@ -78,20 +118,7 @@ void RenderLayersBaseProg::executePixel(float output[4], float x, float y, Pixel
zero_v4(output);
}
else {
- unsigned int offset = (iy * this->getWidth() + ix) * this->m_elementsize;
- if (this->m_elementsize == 1) {
- output[0] = this->m_inputBuffer[offset];
- output[1] = 0.0f;
- output[2] = 0.0f;
- output[3] = 0.0f;
- }
- else if (this->m_elementsize == 3) {
- copy_v3_v3(output, &this->m_inputBuffer[offset]);
- output[3] = 1.0f;
- }
- else {
- copy_v4_v4(output, &this->m_inputBuffer[offset]);
- }
+ doInterpolation(output, x, y, sampler);
}
}
diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h b/source/blender/compositor/operations/COM_RenderLayersBaseProg.h
index ea57d4bc421..3916862a0b3 100644
--- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.h
@@ -80,6 +80,7 @@ protected:
*/
inline float *getInputBuffer() { return this->m_inputBuffer; }
+ void doInterpolation(float output[4], float x, float y, PixelSampler sampler);
public:
/**
* setter for the scene field. Will be called from
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp
index 276b2f54b6e..9e8f5af0ef0 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.cpp
+++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp
@@ -29,7 +29,16 @@
* note: use bilinear because bicubic makes fuzzy even when not scaling at all (1:1)
*/
-ScaleOperation::ScaleOperation() : NodeOperation()
+BaseScaleOperation::BaseScaleOperation()
+{
+#ifdef USE_FORCE_BILINEAR
+ m_sampler = (int) COM_PS_BILINEAR;
+#else
+ m_sampler = -1;
+#endif
+}
+
+ScaleOperation::ScaleOperation() : BaseScaleOperation()
{
this->addInputSocket(COM_DT_COLOR);
this->addInputSocket(COM_DT_VALUE);
@@ -59,22 +68,20 @@ void ScaleOperation::deinitExecution()
void ScaleOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
-#ifdef USE_FORCE_BILINEAR
- sampler = COM_PS_BILINEAR;
-#endif
+ PixelSampler effective_sampler = getEffectiveSampler(sampler);
float scaleX[4];
float scaleY[4];
- this->m_inputXOperation->read(scaleX, x, y, sampler);
- this->m_inputYOperation->read(scaleY, x, y, sampler);
+ this->m_inputXOperation->read(scaleX, x, y, effective_sampler);
+ this->m_inputYOperation->read(scaleY, x, y, effective_sampler);
const float scx = scaleX[0];
const float scy = scaleY[0];
float nx = this->m_centerX + (x - this->m_centerX) / scx;
float ny = this->m_centerY + (y - this->m_centerY) / scy;
- this->m_inputOperation->read(output, nx, ny, sampler);
+ this->m_inputOperation->read(output, nx, ny, effective_sampler);
}
bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
@@ -94,12 +101,12 @@ bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOpe
newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy;
newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy;
- return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+ return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
// SCALE ABSOLUTE
-ScaleAbsoluteOperation::ScaleAbsoluteOperation() : NodeOperation()
+ScaleAbsoluteOperation::ScaleAbsoluteOperation() : BaseScaleOperation()
{
this->addInputSocket(COM_DT_COLOR);
this->addInputSocket(COM_DT_VALUE);
@@ -129,15 +136,13 @@ void ScaleAbsoluteOperation::deinitExecution()
void ScaleAbsoluteOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
-#ifdef USE_FORCE_BILINEAR
- sampler = COM_PS_BILINEAR;
-#endif
+ PixelSampler effective_sampler = getEffectiveSampler(sampler);
float scaleX[4];
float scaleY[4];
- this->m_inputXOperation->read(scaleX, x, y, sampler);
- this->m_inputYOperation->read(scaleY, x, y, sampler);
+ this->m_inputXOperation->read(scaleX, x, y, effective_sampler);
+ this->m_inputYOperation->read(scaleY, x, y, effective_sampler);
const float scx = scaleX[0]; // target absolute scale
const float scy = scaleY[0]; // target absolute scale
@@ -151,7 +156,7 @@ void ScaleAbsoluteOperation::executePixel(float output[4], float x, float y, Pix
float nx = this->m_centerX + (x - this->m_centerX) / relativeXScale;
float ny = this->m_centerY + (y - this->m_centerY) / relativeYScale;
- this->m_inputOperation->read(output, nx, ny, sampler);
+ this->m_inputOperation->read(output, nx, ny, effective_sampler);
}
bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
@@ -176,12 +181,12 @@ bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input, ReadB
newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / relateveYScale;
newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / relateveYScale;
- return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+ return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
// Absolute fixed siez
-ScaleFixedSizeOperation::ScaleFixedSizeOperation() : NodeOperation()
+ScaleFixedSizeOperation::ScaleFixedSizeOperation() : BaseScaleOperation()
{
this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
this->addOutputSocket(COM_DT_COLOR);
@@ -250,17 +255,15 @@ void ScaleFixedSizeOperation::deinitExecution()
void ScaleFixedSizeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
-#ifdef USE_FORCE_BILINEAR
- sampler = COM_PS_BILINEAR;
-#endif
+ PixelSampler effective_sampler = getEffectiveSampler(sampler);
if (this->m_is_offset) {
float nx = ((x - this->m_offsetX) * this->m_relX);
float ny = ((y - this->m_offsetY) * this->m_relY);
- this->m_inputOperation->read(output, nx, ny, sampler);
+ this->m_inputOperation->read(output, nx, ny, effective_sampler);
}
else {
- this->m_inputOperation->read(output, x * this->m_relX, y * this->m_relY, sampler);
+ this->m_inputOperation->read(output, x * this->m_relX, y * this->m_relY, effective_sampler);
}
}
@@ -273,7 +276,7 @@ bool ScaleFixedSizeOperation::determineDependingAreaOfInterest(rcti *input, Read
newInput.ymax = input->ymax * this->m_relY;
newInput.ymin = input->ymin * this->m_relY;
- return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+ return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
@@ -281,7 +284,7 @@ void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], un
unsigned int nr[2];
nr[0] = this->m_newWidth;
nr[1] = this->m_newHeight;
- NodeOperation::determineResolution(resolution, nr);
+ BaseScaleOperation::determineResolution(resolution, nr);
resolution[0] = this->m_newWidth;
resolution[1] = this->m_newHeight;
}
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.h b/source/blender/compositor/operations/COM_ScaleOperation.h
index 4239ff063fb..f42cdbd78ed 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.h
+++ b/source/blender/compositor/operations/COM_ScaleOperation.h
@@ -25,7 +25,19 @@
#include "COM_NodeOperation.h"
-class ScaleOperation : public NodeOperation {
+class BaseScaleOperation : public NodeOperation {
+public:
+ void setSampler(PixelSampler sampler) { this->m_sampler = (int) sampler; }
+
+protected:
+ BaseScaleOperation();
+
+ PixelSampler getEffectiveSampler(PixelSampler sampler) { return (m_sampler == -1) ? sampler : (PixelSampler) m_sampler; }
+
+ int m_sampler;
+};
+
+class ScaleOperation : public BaseScaleOperation {
private:
SocketReader *m_inputOperation;
SocketReader *m_inputXOperation;
@@ -41,7 +53,7 @@ public:
void deinitExecution();
};
-class ScaleAbsoluteOperation : public NodeOperation {
+class ScaleAbsoluteOperation : public BaseScaleOperation {
SocketReader *m_inputOperation;
SocketReader *m_inputXOperation;
SocketReader *m_inputYOperation;
@@ -57,7 +69,7 @@ public:
void deinitExecution();
};
-class ScaleFixedSizeOperation : public NodeOperation {
+class ScaleFixedSizeOperation : public BaseScaleOperation {
SocketReader *m_inputOperation;
int m_newWidth;
int m_newHeight;
diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp
index d41d1c128da..8b5288321c1 100644
--- a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp
+++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp
@@ -92,7 +92,7 @@ void TrackPositionOperation::initExecution()
}
else if (this->m_position == POSITION_RELATIVE_FRAME) {
int relative_clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip,
- this->m_relativeFrame);
+ this->m_relativeFrame);
marker = BKE_tracking_marker_get(track, relative_clip_framenr);
copy_v2_v2(this->m_relativePos, marker->pos);
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 01c0a95e200..0f0584ad8fe 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -381,7 +381,7 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short rest
return RAD2DEGF(1.0f); /* radians to degrees */
}
}
-
+
/* TODO: other rotation types here as necessary */
}
}
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index f1fc93db60e..dffef5c131f 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -176,7 +176,7 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction)
return 1;
case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */
-{
+ {
/* TODO, other methods to get the mask */
// Sequence *seq = BKE_sequencer_active_get(ac->scene);
//MovieClip *clip = ac->scene->clip;
@@ -190,7 +190,7 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction)
ac->mode = saction->mode;
return 1;
-}
+ }
case SACTCONT_DOPESHEET: /* DopeSheet */
/* update scene-pointer (no need to check for pinning yet, as not implemented) */
saction->ads.source = (ID *)ac->scene;
@@ -925,14 +925,16 @@ static short skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_i
/* only consider if F-Curve involves sequence_editor.sequences */
if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
- Sequence *seq;
+ Sequence *seq = NULL;
char *seq_name;
-
- /* 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);
-
+
+ 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)
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index da8fc328343..f9cf4a29269 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -2104,15 +2104,15 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch,
if (sketch->depth_peels.first != NULL)
{
float colors[8][3] = {
- {1, 0, 0},
- {0, 1, 0},
- {0, 0, 1},
- {1, 1, 0},
- {1, 0, 1},
- {0, 1, 1},
- {1, 1, 1},
- {0, 0, 0}
- };
+ {1, 0, 0},
+ {0, 1, 0},
+ {0, 0, 1},
+ {1, 1, 0},
+ {1, 0, 1},
+ {0, 1, 1},
+ {1, 1, 1},
+ {0, 0, 0}
+ };
DepthPeel *p;
GLUquadric *quad = gluNewQuadric();
gluQuadricNormals(quad, GLU_SMOOTH);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 485d73974cd..957dcfbd848 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -6465,8 +6465,8 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
fac = (float)b - 1.5f;
bp->vec[1] += fac * grid;
if (a == 1 || a == 2) if (b == 1 || b == 2) {
- bp->vec[2] += grid;
- }
+ bp->vec[2] += grid;
+ }
mul_m4_v3(mat, bp->vec);
bp->vec[3] = 1.0;
bp++;
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index ed8a1ea8280..1defcf65ae8 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -40,8 +40,10 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "DNA_anim_types.h"
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "DNA_node_types.h"
@@ -51,14 +53,19 @@
#include "DNA_view3d_types.h"
#include "DNA_gpencil_types.h"
+#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_library.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_tracking.h"
+#include "UI_interface.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -71,6 +78,7 @@
#include "ED_gpencil.h"
#include "ED_view3d.h"
#include "ED_clip.h"
+#include "ED_keyframing.h"
#include "gpencil_intern.h"
@@ -387,6 +395,14 @@ enum {
GP_STROKECONVERT_CURVE,
};
+/* Defines for possible timing modes */
+enum {
+ GP_STROKECONVERT_TIMING_NONE = 1,
+ GP_STROKECONVERT_TIMING_LINEAR = 2,
+ GP_STROKECONVERT_TIMING_FULL = 3,
+ GP_STROKECONVERT_TIMING_CUSTOMGAP = 4,
+};
+
/* RNA enum define */
static EnumPropertyItem prop_gpencil_convertmodes[] = {
{GP_STROKECONVERT_PATH, "PATH", 0, "Path", ""},
@@ -394,6 +410,31 @@ static EnumPropertyItem prop_gpencil_convertmodes[] = {
{0, NULL, 0, NULL, NULL}
};
+static EnumPropertyItem prop_gpencil_convert_timingmodes_restricted[] = {
+ {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"},
+ {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static EnumPropertyItem prop_gpencil_convert_timingmodes[] = {
+ {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"},
+ {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"},
+ {GP_STROKECONVERT_TIMING_FULL, "FULL", 0, "Original", "Use the original timing, gaps included"},
+ {GP_STROKECONVERT_TIMING_CUSTOMGAP, "CUSTOMGAP", 0, "Custom Gaps",
+ "Use the original timing, but with custom gap lengths (in frames)"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop),
+ int *free)
+{
+ *free = FALSE;
+ if (RNA_boolean_get(ptr, "use_timing_data")) {
+ return prop_gpencil_convert_timingmodes;
+ }
+ return prop_gpencil_convert_timingmodes_restricted;
+}
+
/* --- */
/* convert the coordinates from the given stroke point into 3d-coordinates
@@ -440,40 +481,487 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin
/* --- */
+/* temp struct for gp_stroke_path_animation() */
+typedef struct tGpTimingData {
+ /* Data set from operator settings */
+ int mode;
+ int frame_range; /* Number of frames evaluated for path animation */
+ int start_frame, end_frame;
+ int realtime; /* A bool, actually, will overwrite end_frame in case of Original or CustomGap timing... */
+ float gap_duration, gap_randomness; /* To be used with CustomGap mode*/
+ int seed;
+
+ /* Data set from points, used to compute final timing FCurve */
+ int num_points, cur_point;
+
+ /* Distances */
+ float *dists;
+ float tot_dist;
+
+ /* Times */
+ float *times; /* Note: Gap times will be negative! */
+ float tot_time, gap_tot_time;
+ double inittime;
+} tGpTimingData;
+
+static void _gp_timing_data_set_nbr(tGpTimingData *gtd, int nbr)
+{
+ float *tmp;
+
+ BLI_assert(nbr > gtd->num_points);
+
+ tmp = gtd->dists;
+ gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__);
+ if (tmp) {
+ memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points);
+ MEM_freeN(tmp);
+ }
+
+ tmp = gtd->times;
+ gtd->times = MEM_callocN(sizeof(float) * nbr, __func__);
+ if (tmp) {
+ memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points);
+ MEM_freeN(tmp);
+ }
+
+ gtd->num_points = nbr;
+}
+
+static void gp_timing_data_add_point(tGpTimingData *gtd, double stroke_inittime, float time, float delta_dist)
+{
+ if (time < 0.0f) {
+ /* This is a gap, negative value! */
+ gtd->tot_time = -(gtd->times[gtd->cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time));
+ gtd->gap_tot_time += gtd->times[gtd->cur_point] - gtd->times[gtd->cur_point - 1];
+ }
+ else
+ gtd->tot_time = (gtd->times[gtd->cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time));
+ gtd->dists[gtd->cur_point] = (gtd->tot_dist += delta_dist);
+ gtd->cur_point++;
+}
+
+/* In frames! Binary search for FCurve keys have a threshold of 0.01, so we can’t set
+ * arbitrarily close points - this is esp. important with NoGaps mode!
+ */
+#define MIN_TIME_DELTA 0.02f
+
+/* Loop over next points to find the end of the stroke, and compute */
+static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, int idx, int nbr_gaps, int *nbr_done_gaps,
+ float tot_gaps_time, float delta_time, float *next_delta_time)
+{
+ int j;
+
+ for (j = idx + 1; j < gtd->num_points; j++) {
+ if (gtd->times[j] < 0) {
+ gtd->times[j] = -gtd->times[j];
+ if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
+ /* In this mode, gap time between this stroke and the next should be 0 currently...
+ * So we have to compute its final duration!
+ */
+ if (gtd->gap_randomness > 0.0f) {
+ /* We want gaps that are in gtd->gap_duration +/- gtd->gap_randomness range,
+ * and which sum to exactly tot_gaps_time...
+ */
+ int rem_gaps = nbr_gaps - *nbr_done_gaps;
+ if (rem_gaps < 2) {
+ /* Last gap, just give remaining time! */
+ *next_delta_time = tot_gaps_time;
+ }
+ else {
+ float delta, min, max;
+ /* This code ensures that if the first gaps have been shorter than average gap_duration,
+ * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa!
+ */
+ delta = delta_time - (gtd->gap_duration * *nbr_done_gaps);
+ /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */
+ min = -gtd->gap_randomness - delta;
+ CLAMP(min, -gtd->gap_randomness, 0.0f);
+ /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */
+ max = gtd->gap_randomness - delta;
+ CLAMP(max, 0.0f, gtd->gap_randomness);
+ *next_delta_time += gtd->gap_duration + (BLI_frand() * (max - min)) + min;
+ }
+ }
+ else {
+ *next_delta_time += gtd->gap_duration;
+ }
+ }
+ (*nbr_done_gaps)++;
+ break;
+ }
+ }
+
+ return j - 1;
+}
+
+static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, int *nbr_gaps, float *tot_gaps_time)
+{
+ int i;
+ float delta_time = 0.0f;
+
+ for (i = 0; i < gtd->num_points; i++) {
+ if (gtd->times[i] < 0 && i) {
+ (*nbr_gaps)++;
+ gtd->times[i] = -gtd->times[i] - delta_time;
+ delta_time += gtd->times[i] - gtd->times[i - 1];
+ gtd->times[i] = -gtd->times[i - 1]; /* Temp marker, values *have* to be different! */
+ }
+ else {
+ gtd->times[i] -= delta_time;
+ }
+ }
+ gtd->tot_time -= delta_time;
+
+ *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration;
+ gtd->tot_time += *tot_gaps_time;
+ if (G.debug & G_DEBUG) {
+ printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps);
+ }
+ if (gtd->gap_randomness > 0.0f) {
+ BLI_srandom(gtd->seed);
+ }
+}
+
+static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu,
+ Curve *cu, tGpTimingData *gtd, float time_range,
+ int nbr_gaps, float tot_gaps_time)
+{
+ /* Use actual recorded timing! */
+ float time_start = (float)gtd->start_frame;
+
+ float last_valid_time = 0.0f;
+ int end_stroke_idx = -1, start_stroke_idx = 0;
+ float end_stroke_time = 0.0f;
+
+ /* CustomGaps specific */
+ float delta_time = 0.0f, next_delta_time = 0.0f;
+ int nbr_done_gaps = 0;
+
+ int i;
+ float cfra;
+
+ /* This is a bit tricky, as:
+ * - We can't add arbitrarily close points on FCurve (in time).
+ * - We *must* have all "caps" points of all strokes in FCurve, as much as possible!
+ */
+ for (i = 0; i < gtd->num_points; i++) {
+ /* If new stroke... */
+ if (i > end_stroke_idx) {
+ start_stroke_idx = i;
+ delta_time = next_delta_time;
+ /* find end of that new stroke */
+ end_stroke_idx = gp_find_end_of_stroke_idx(gtd, i, nbr_gaps, &nbr_done_gaps,
+ tot_gaps_time, delta_time, &next_delta_time);
+ /* This one should *never* be negative! */
+ end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range);
+ }
+
+ /* Simple proportional stuff... */
+ cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen;
+ cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range);
+
+ /* And now, the checks about timing... */
+ if (i == start_stroke_idx) {
+ /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and
+ * that the end point of the stroke is far enough!
+ * In case it is not, we keep the end point...
+ * Note that with CustomGaps mode, this is here we set the actual gap timing!
+ */
+ if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) {
+ if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
+ cfra = last_valid_time + MIN_TIME_DELTA;
+ }
+ insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
+ last_valid_time = cfra;
+ }
+ else if (G.debug & G_DEBUG) {
+ printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx);
+ }
+ }
+ else if (i == end_stroke_idx) {
+ /* Always try to insert end point of a curve (should be safe enough, anyway...) */
+ if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
+ cfra = last_valid_time + MIN_TIME_DELTA;
+ }
+ insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
+ last_valid_time = cfra;
+ }
+ else {
+ /* Else ("middle" point), we only insert it if it's far enough from last keyframe,
+ * and also far enough from (not yet added!) end_stroke keyframe!
+ */
+ if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) {
+ insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
+ last_valid_time = cfra;
+ }
+ else if (G.debug & G_DEBUG) {
+ printf("\t Skipping \"middle\" point %d, too close from last added point or end point %d\n",
+ i, end_stroke_idx);
+ }
+ }
+ }
+}
+
+static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd)
+{
+ Scene *scene = CTX_data_scene(C);
+ bAction *act;
+ FCurve *fcu;
+ PointerRNA ptr;
+ PropertyRNA *prop = NULL;
+
+ int nbr_gaps = 0, i;
+
+ if (gtd->mode == GP_STROKECONVERT_TIMING_NONE)
+ return;
+
+ /* gap_duration and gap_randomness are in frames, but we need seconds!!! */
+ gtd->gap_duration = FRA2TIME(gtd->gap_duration);
+ gtd->gap_randomness = FRA2TIME(gtd->gap_randomness);
+
+ /* Enable path! */
+ cu->flag |= CU_PATH;
+ cu->pathlen = gtd->frame_range;
+
+ /* Get or create default action to add F-Curve+keyframe to */
+ act = verify_adt_action((ID*)cu, TRUE);
+ /* Create RNA stuff */
+ RNA_id_pointer_create((ID*)cu, &ptr);
+ prop = RNA_struct_find_property(&ptr, "eval_time");
+ /* Get or create fcurve */
+ fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, TRUE);
+
+ if (G.debug & G_DEBUG) {
+ printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
+ for (i = 0; i < gtd->num_points; i++) {
+ printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
+ }
+ }
+
+ if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) {
+ float cfra;
+
+ /* Linear extrapolation! */
+ fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
+
+ cu->ctime = 0.0f;
+ cfra = (float)gtd->start_frame;
+ insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
+
+ cu->ctime = cu->pathlen;
+ if (gtd->realtime) {
+ cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
+ }
+ else {
+ cfra = (float)gtd->end_frame;
+ }
+ insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST);
+ }
+ else {
+ /* Use actual recorded timing! */
+ float time_range;
+
+ /* CustomGaps specific */
+ float tot_gaps_time = 0.0f;
+
+ /* Pre-process gaps, in case we don't want to keep their org timing */
+ if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
+ gp_stroke_path_animation_preprocess_gaps(gtd, &nbr_gaps, &tot_gaps_time);
+ }
+
+ if (gtd->realtime) {
+ time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
+ }
+ else {
+ time_range = (float)(gtd->end_frame - gtd->start_frame);
+ }
+
+ if (G.debug & G_DEBUG) {
+ printf("Starting keying!\n");
+ }
+
+ gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, time_range,
+ nbr_gaps, tot_gaps_time);
+
+ }
+
+ /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */
+ calchandles_fcurve(fcu);
+
+ if (G.debug & G_DEBUG) {
+ printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
+ for (i = 0; i < gtd->num_points; i++) {
+ printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
+ }
+ printf("\n\n");
+ }
+
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ /* send updates */
+ DAG_id_tag_update((ID*)cu, 0);
+}
+
+#undef MIN_TIME_DELTA
+
+#define GAP_DFAC 0.05f
+#define WIDTH_CORR_FAC 0.1f
+#define BEZT_HANDLE_FAC 0.3f
+
/* convert stroke to 3d path */
-static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect)
+static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
+ float minmax_weights[2], float rad_fac, int stitch, tGpTimingData *gtd)
{
bGPDspoint *pt;
- Nurb *nu;
- BPoint *bp;
- int i;
+ Nurb *nu = curnu ? *curnu : NULL;
+ BPoint *bp, *prev_bp = NULL;
+ int i, old_nbp = 0;
+ const int do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
+
+ /* create new 'nurb' or extend current one within the curve */
+ if (nu) {
+ old_nbp = nu->pntsu;
+ /* If stitch, the first point of this stroke is already present in current nu.
+ * Else, we have to add to additional points to make the zero-radius link between strokes.
+ */
+ BKE_nurb_points_add(nu, gps->totpoints + (stitch ? -1 : 2));
+ }
+ else {
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)");
+
+ nu->pntsu = gps->totpoints;
+ nu->pntsv = 1;
+ nu->orderu = 2; /* point-to-point! */
+ nu->type = CU_NURBS;
+ nu->flagu = CU_NURB_ENDPOINT;
+ nu->resolu = cu->resolu;
+ nu->resolv = cu->resolv;
+ nu->knotsu = NULL;
+
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints");
+
+ stitch = FALSE; /* Security! */
+ }
- /* create new 'nurb' within the curve */
- nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)");
-
- nu->pntsu = gps->totpoints;
- nu->pntsv = 1;
- nu->orderu = gps->totpoints;
- nu->flagu = CU_NURB_ENDPOINT;
- nu->resolu = 32;
-
- nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * gps->totpoints, "bpoints");
-
+ if (do_gtd) {
+ _gp_timing_data_set_nbr(gtd, nu->pntsu);
+ }
+
+ /* If needed, make the link between both strokes with two zero-radius additional points */
+ /* About "zero-radius" point interpolations:
+ * - If we have at least two points in current curve (most common case), we linearly extrapolate
+ * the last segment to get the first point (p1) position and timing.
+ * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point
+ * with the first point of the current stroke.
+ * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated
+ * if it exists, else (if the stroke is a single point), linear interpolation with last curve point...
+ */
+ if (curnu && !stitch && old_nbp) {
+ float p1[3], p2[3], p[3], next_p[3];
+ float delta_time;
+
+ prev_bp = NULL;
+ if (old_nbp > 1 && gps->prev && gps->prev->totpoints > 1) {
+ /* Only use last curve segment if previous stroke was not a single-point one! */
+ prev_bp = nu->bp + old_nbp - 2;
+ }
+ bp = nu->bp + old_nbp - 1;
+ /* XXX We do this twice... Not sure it's worth to bother about this! */
+ gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect);
+ if (prev_bp) {
+ interp_v3_v3v3(p1, prev_bp->vec, bp->vec, 1.0f + GAP_DFAC);
+ }
+ else {
+ interp_v3_v3v3(p1, bp->vec, p, GAP_DFAC);
+ }
+ if (gps->totpoints > 1) {
+ /* XXX We do this twice... Not sure it's worth to bother about this! */
+ gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect);
+ interp_v3_v3v3(p2, p, next_p, -GAP_DFAC);
+ }
+ else {
+ interp_v3_v3v3(p2, p, bp->vec, GAP_DFAC);
+ }
+
+ /* First point */
+ bp++;
+ copy_v3_v3(bp->vec, p1);
+ bp->vec[3] = 1.0f;
+ bp->f1 = SELECT;
+ minmax_weights[0] = bp->radius = bp->weight = 0.0f;
+ if (do_gtd) {
+ if (prev_bp) {
+ delta_time = gtd->tot_time + (gtd->tot_time - gtd->times[gtd->cur_point - 1]) * GAP_DFAC;
+ }
+ else {
+ delta_time = gtd->tot_time + (((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC;
+ }
+ gp_timing_data_add_point(gtd, gtd->inittime, delta_time, len_v3v3((bp - 1)->vec, p1));
+ }
+
+ /* Second point */
+ bp++;
+ copy_v3_v3(bp->vec, p2);
+ bp->vec[3] = 1.0f;
+ bp->f1 = SELECT;
+ minmax_weights[0] = bp->radius = bp->weight = 0.0f;
+ if (do_gtd) {
+ /* This negative delta_time marks the gap! */
+ if (gps->totpoints > 1) {
+ delta_time = ((gps->points + 1)->time - gps->points->time) * -GAP_DFAC;
+ }
+ else {
+ delta_time = -(((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC;
+ }
+ gp_timing_data_add_point(gtd, gps->inittime, delta_time, len_v3v3(p1, p2));
+ }
+
+ old_nbp += 2;
+ }
+ if (old_nbp && do_gtd) {
+ prev_bp = nu->bp + old_nbp - 1;
+ }
/* add points */
- for (i = 0, pt = gps->points, bp = nu->bp; i < gps->totpoints; i++, pt++, bp++) {
+ for (i = stitch ? 1 : 0, pt = gps->points + (stitch ? 1 : 0), bp = nu->bp + old_nbp;
+ i < gps->totpoints;
+ i++, pt++, bp++)
+ {
float p3d[3];
-
+ float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC;
+
/* get coordinates to add at */
gp_strokepoint_convertcoords(C, gps, pt, p3d, subrect);
copy_v3_v3(bp->vec, p3d);
-
+ bp->vec[3] = 1.0f;
+
/* set settings */
bp->f1 = SELECT;
- bp->radius = bp->weight = pt->pressure * gpl->thickness;
+ bp->radius = width * rad_fac;
+ bp->weight = width;
+ CLAMP(bp->weight, 0.0f, 1.0f);
+ if (bp->weight < minmax_weights[0]) {
+ minmax_weights[0] = bp->weight;
+ }
+ else if (bp->weight > minmax_weights[1]) {
+ minmax_weights[1] = bp->weight;
+ }
+
+ /* Update timing data */
+ if (do_gtd) {
+ gp_timing_data_add_point(gtd, gps->inittime, pt->time, prev_bp ? len_v3v3(prev_bp->vec, p3d) : 0.0f);
+ }
+ prev_bp = bp;
}
-
+
/* add nurb to curve */
- BLI_addtail(&cu->nurb, nu);
+ if (!curnu || !*curnu) {
+ BLI_addtail(&cu->nurb, nu);
+ }
+ if (curnu) {
+ *curnu = nu;
+ }
+
+ BKE_nurb_knot_calc_u(nu);
}
static int gp_camera_view_subrect(bContext *C, rctf *subrect)
@@ -496,77 +984,288 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect)
}
/* convert stroke to 3d bezier */
-static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect)
+static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu,
+ float minmax_weights[2], float rad_fac, int stitch, tGpTimingData *gtd)
{
bGPDspoint *pt;
- Nurb *nu;
- BezTriple *bezt;
- int i, tot;
+ Nurb *nu = curnu ? *curnu : NULL;
+ BezTriple *bezt, *prev_bezt = NULL;
+ int i, tot, old_nbezt = 0;
float p3d_cur[3], p3d_prev[3], p3d_next[3];
+ const int do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE);
+
+ /* create new 'nurb' or extend current one within the curve */
+ if (nu) {
+ old_nbezt = nu->pntsu;
+ /* If we do stitch, first point of current stroke is assumed the same as last point of previous stroke,
+ * so no need to add it.
+ * If no stitch, we want to add two additional points to make a "zero-radius" link between both strokes.
+ */
+ BKE_nurb_bezierPoints_add(nu, gps->totpoints + (stitch ? -1 : 2));
+ }
+ else {
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)");
- /* create new 'nurb' within the curve */
- nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)");
+ nu->pntsu = gps->totpoints;
+ nu->resolu = 12;
+ nu->resolv = 12;
+ nu->type = CU_BEZIER;
+ nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints * sizeof(BezTriple), "bezts");
- nu->pntsu = gps->totpoints;
- nu->resolu = 12;
- nu->resolv = 12;
- nu->type = CU_BEZIER;
- nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints * sizeof(BezTriple), "bezts");
+ stitch = FALSE; /* Security! */
+ }
+
+ if (do_gtd) {
+ _gp_timing_data_set_nbr(gtd, nu->pntsu);
+ }
tot = gps->totpoints;
/* get initial coordinates */
pt = gps->points;
if (tot) {
- gp_strokepoint_convertcoords(C, gps, pt, p3d_cur, subrect);
+ gp_strokepoint_convertcoords(C, gps, pt, stitch ? p3d_prev : p3d_cur, subrect);
if (tot > 1) {
- gp_strokepoint_convertcoords(C, gps, pt + 1, p3d_next, subrect);
+ gp_strokepoint_convertcoords(C, gps, pt + 1, stitch ? p3d_cur : p3d_next, subrect);
+ }
+ if (stitch && tot > 2) {
+ gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect);
}
}
+ /* If needed, make the link between both strokes with two zero-radius additional points */
+ if (curnu && old_nbezt) {
+ /* Update last point's second handle! */
+ if (stitch) {
+ float h2[3];
+ bezt = nu->bezt + old_nbezt - 1;
+ interp_v3_v3v3(h2, bezt->vec[1], p3d_cur, BEZT_HANDLE_FAC);
+ copy_v3_v3(bezt->vec[2], h2);
+ pt++;
+ }
+ /* Create "link points" */
+ /* About "zero-radius" point interpolations:
+ * - If we have at least two points in current curve (most common case), we linearly extrapolate
+ * the last segment to get the first point (p1) position and timing.
+ * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point
+ * with the first point of the current stroke.
+ * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated
+ * if it exists, else (if the stroke is a single point), linear interpolation with last curve point...
+ */
+ else {
+ float h1[3], h2[3], p1[3], p2[3];
+ float delta_time;
+
+ prev_bezt = NULL;
+ if (old_nbezt > 1 && gps->prev && gps->prev->totpoints > 1) {
+ /* Only use last curve segment if previous stroke was not a single-point one! */
+ prev_bezt = nu->bezt + old_nbezt - 2;
+ }
+ bezt = nu->bezt + old_nbezt - 1;
+ if (prev_bezt) {
+ interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC);
+ }
+ else {
+ interp_v3_v3v3(p1, bezt->vec[1], p3d_cur, GAP_DFAC);
+ }
+ if (tot > 1) {
+ interp_v3_v3v3(p2, p3d_cur, p3d_next, -GAP_DFAC);
+ }
+ else {
+ interp_v3_v3v3(p2, p3d_cur, bezt->vec[1], GAP_DFAC);
+ }
+
+ /* Second handle of last point */
+ interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC);
+ copy_v3_v3(bezt->vec[2], h2);
+
+ /* First point */
+ interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC);
+ interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC);
+
+ bezt++;
+ copy_v3_v3(bezt->vec[0], h1);
+ copy_v3_v3(bezt->vec[1], p1);
+ copy_v3_v3(bezt->vec[2], h2);
+ bezt->h1 = bezt->h2 = HD_FREE;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ minmax_weights[0] = bezt->radius = bezt->weight = 0.0f;
+
+ if (do_gtd) {
+ if (prev_bezt) {
+ delta_time = gtd->tot_time + (gtd->tot_time - gtd->times[gtd->cur_point - 1]) * GAP_DFAC;
+ }
+ else {
+ delta_time = gtd->tot_time + (((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC;
+ }
+ gp_timing_data_add_point(gtd, gtd->inittime, delta_time, len_v3v3((bezt - 1)->vec[1], p1));
+ }
+
+ /* Second point */
+ interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC);
+ interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC);
+
+ bezt++;
+ copy_v3_v3(bezt->vec[0], h1);
+ copy_v3_v3(bezt->vec[1], p2);
+ copy_v3_v3(bezt->vec[2], h2);
+ bezt->h1 = bezt->h2 = HD_FREE;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ minmax_weights[0] = bezt->radius = bezt->weight = 0.0f;
+
+ if (do_gtd) {
+ /* This negative delta_time marks the gap! */
+ if (tot > 1) {
+ delta_time = ((gps->points + 1)->time - gps->points->time) * -GAP_DFAC;
+ }
+ else {
+ delta_time = -(((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC;
+ }
+ gp_timing_data_add_point(gtd, gps->inittime, delta_time, len_v3v3(p1, p2));
+ }
+
+ old_nbezt += 2;
+ copy_v3_v3(p3d_prev, p2);
+ }
+ }
+ if (old_nbezt && do_gtd) {
+ prev_bezt = nu->bezt + old_nbezt - 1;
+ }
/* add points */
- for (i = 0, bezt = nu->bezt; i < tot; i++, pt++, bezt++) {
+ for (i = stitch ? 1 : 0, bezt = nu->bezt + old_nbezt; i < tot; i++, pt++, bezt++) {
float h1[3], h2[3];
-
- if (i) interp_v3_v3v3(h1, p3d_cur, p3d_prev, 0.3);
- else interp_v3_v3v3(h1, p3d_cur, p3d_next, -0.3);
-
- if (i < tot - 1) interp_v3_v3v3(h2, p3d_cur, p3d_next, 0.3);
- else interp_v3_v3v3(h2, p3d_cur, p3d_prev, -0.3);
-
+ float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC;
+
+ if (i || old_nbezt) {
+ interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC);
+ }
+ else {
+ interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC);
+ }
+
+ if (i < tot - 1) {
+ interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC);
+ }
+ else {
+ interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC);
+ }
+
copy_v3_v3(bezt->vec[0], h1);
copy_v3_v3(bezt->vec[1], p3d_cur);
copy_v3_v3(bezt->vec[2], h2);
-
+
/* set settings */
bezt->h1 = bezt->h2 = HD_FREE;
bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->radius = bezt->weight = pt->pressure * gpl->thickness * 0.1f;
-
+ bezt->radius = width * rad_fac;
+ bezt->weight = width;
+ CLAMP(bezt->weight, 0.0f, 1.0f);
+ if (bezt->weight < minmax_weights[0]) {
+ minmax_weights[0] = bezt->weight;
+ }
+ else if (bezt->weight > minmax_weights[1]) {
+ minmax_weights[1] = bezt->weight;
+ }
+
+ /* Update timing data */
+ if (do_gtd) {
+ gp_timing_data_add_point(gtd, gps->inittime, pt->time, prev_bezt ? len_v3v3(prev_bezt->vec[1], p3d_cur) : 0.0f);
+ }
+
/* shift coord vects */
copy_v3_v3(p3d_prev, p3d_cur);
copy_v3_v3(p3d_cur, p3d_next);
-
+
if (i + 2 < tot) {
gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect);
}
+
+ prev_bezt = bezt;
}
/* must calculate handles or else we crash */
BKE_nurb_handles_calc(nu);
- /* add nurb to curve */
- BLI_addtail(&cu->nurb, nu);
+ if (!curnu || !*curnu) {
+ BLI_addtail(&cu->nurb, nu);
+ }
+ if (curnu) {
+ *curnu = nu;
+ }
+}
+
+#undef GAP_DFAC
+#undef WIDTH_CORR_FAC
+#undef BEZT_HANDLE_FAC
+
+static void gp_stroke_finalize_curve_endpoints(Curve *cu)
+{
+ Nurb *nu = cu->nurb.first;
+ int i = 0;
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ if (bezt) {
+ bezt[i].weight = bezt[i].radius = 0.0f;
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp = nu->bp;
+ if (bp) {
+ bp[i].weight = bp[i].radius = 0.0f;
+ }
+ }
+
+ nu = cu->nurb.last;
+ i = nu->pntsu - 1;
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ if (bezt) {
+ bezt[i].weight = bezt[i].radius = 0.0f;
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp = nu->bp;
+ if (bp) {
+ bp[i].weight = bp[i].radius = 0.0f;
+ }
+ }
+}
+
+static void gp_stroke_norm_curve_weights(Curve *cu, float minmax_weights[2])
+{
+ Nurb *nu;
+ const float delta = minmax_weights[0];
+ const float fac = 1.0f / (minmax_weights[1] - delta);
+ int i;
+
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ for (i = 0; i < nu->pntsu; i++, bezt++) {
+ bezt->weight = (bezt->weight - delta) * fac;
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp = nu->bp;
+ for (i = 0; i < nu->pntsu; i++, bp++) {
+ bp->weight = (bp->weight - delta) * fac;
+ }
+ }
+ }
}
/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
-static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short mode)
+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)
{
Scene *scene = CTX_data_scene(C);
bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
- bGPDstroke *gps;
+ bGPDstroke *gps, *prev_gps = NULL;
Object *ob;
Curve *cu;
+ Nurb *nu = NULL;
+ Base *base = BASACT, *newbase = NULL;
+ float minmax_weights[2] = {1.0f, 0.0f};
/* camera framing */
rctf subrect, *subrect_ptr = NULL;
@@ -574,7 +1273,7 @@ static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short m
/* error checking */
if (ELEM3(NULL, gpd, gpl, gpf))
return;
-
+
/* only convert if there are any strokes on this layer's frame to convert */
if (gpf->strokes.first == NULL)
return;
@@ -592,29 +1291,116 @@ static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short m
zero_v3(ob->rot);
cu = ob->data;
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 */
for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached,
+ * and stitch them to previous one.
+ */
+ int stitch = FALSE;
+ if (prev_gps) {
+ bGPDspoint *pt1 = prev_gps->points + prev_gps->totpoints - 1;
+ bGPDspoint *pt2 = gps->points;
+ if (pt1->x == pt2->x && pt1->y == pt2->y)
+ stitch = TRUE;
+ }
+ /* Decide whether we connect this stroke to previous one */
+ if (!(stitch || link_strokes))
+ nu = NULL;
switch (mode) {
case GP_STROKECONVERT_PATH:
- gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr);
+ gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, gtd);
break;
case GP_STROKECONVERT_CURVE:
- gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr);
+ gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, gtd);
break;
default:
BLI_assert(!"invalid mode");
break;
}
+ prev_gps = gps;
}
+
+ /* If link_strokes, be sure first and last points have a zero weight/size! */
+ if (link_strokes)
+ gp_stroke_finalize_curve_endpoints(cu);
+
+ /* Update curve's weights, if needed */
+ if (norm_weights && (minmax_weights[0] > 0.0f || minmax_weights[1] < 1.0f))
+ gp_stroke_norm_curve_weights(cu, minmax_weights);
+
+ /* Create the path animation, if needed */
+ gp_stroke_path_animation(C, reports, cu, gtd);
+
+ /* Reset org object as active, else we can't edit operator's settings!!! */
+ /* set layers OK */
+ newbase = BASACT;
+ newbase->lay = base->lay;
+ ob->lay = newbase->lay;
+ /* restore, BKE_object_add sets active */
+ BASACT = base;
+ base->flag |= SELECT;
}
/* --- */
+/* Check a GP layer has valid timing data! Else, most timing options are hidden in the operator.
+ * op may be NULL.
+ */
+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;
+ bGPDspoint *pt;
+ double base_time, cur_time, prev_time = -1.0;
+ int i, valid = TRUE;
+
+ do {
+ base_time = cur_time = gps->inittime;
+ if (cur_time <= prev_time) {
+ valid = FALSE;
+ break;
+ }
+ prev_time = cur_time;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ cur_time = base_time + (double)pt->time;
+ /* First point of a stroke should have the same time as stroke's inittime,
+ * so it's the only case where equality is allowed!
+ */
+ if ((i && cur_time <= prev_time) || (cur_time < prev_time)) {
+ valid = FALSE;
+ break;
+ }
+ prev_time = cur_time;
+ }
+ if (!valid) {
+ break;
+ }
+ } while ((gps = gps->next));
+
+ if (op) {
+ RNA_boolean_set(op->ptr, "use_timing_data", valid);
+ }
+ return valid;
+}
+
+/* Check end_frame is always > start frame! */
+static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr)
+{
+ int start_frame = RNA_int_get(ptr, "start_frame");
+ int end_frame = RNA_int_get(ptr, "end_frame");
+ if (end_frame <= start_frame) {
+ RNA_int_set(ptr, "end_frame", start_frame + 1);
+ }
+}
+
static int gp_convert_poll(bContext *C)
{
bGPdata *gpd = gpencil_data_get_active(C);
@@ -627,10 +1413,16 @@ static int gp_convert_poll(bContext *C)
static int gp_convert_layer_exec(bContext *C, wmOperator *op)
{
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data");
bGPdata *gpd = gpencil_data_get_active(C);
bGPDlayer *gpl = gpencil_layer_getactive(gpd);
Scene *scene = CTX_data_scene(C);
int mode = RNA_enum_get(op->ptr, "type");
+ int norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights");
+ float rad_fac = RNA_float_get(op->ptr, "radius_multiplier");
+ int link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes");
+ int valid_timing;
+ tGpTimingData gtd;
/* check if there's data to work with */
if (gpd == NULL) {
@@ -638,7 +1430,36 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- gp_layer_to_curve(C, gpd, gpl, mode);
+ if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) {
+ BKE_report(op->reports, RPT_WARNING,
+ "Current grease pencil strokes have no valid timing data, most timing options will be hidden!");
+ }
+ valid_timing = RNA_property_boolean_get(op->ptr, prop);
+
+ gtd.mode = RNA_enum_get(op->ptr, "timing_mode");
+ /* Check for illegal timing mode! */
+ if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) {
+ gtd.mode = GP_STROKECONVERT_TIMING_LINEAR;
+ RNA_enum_set(op->ptr, "timing_mode", gtd.mode);
+ }
+ if (!link_strokes) {
+ gtd.mode = GP_STROKECONVERT_TIMING_NONE;
+ }
+
+ gtd.frame_range = RNA_int_get(op->ptr, "frame_range");
+ gtd.start_frame = RNA_int_get(op->ptr, "start_frame");
+ gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : FALSE;
+ gtd.end_frame = RNA_int_get(op->ptr, "end_frame");
+ gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration");
+ gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness");
+ gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration);
+ gtd.seed = RNA_int_get(op->ptr, "seed");
+ gtd.num_points = gtd.cur_point = 0;
+ gtd.dists = gtd.times = NULL;
+ gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f;
+ gtd.inittime = 0.0;
+
+ gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, &gtd);
/* notifiers */
WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL);
@@ -648,24 +1469,131 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static int 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");
+ int timing_mode = RNA_enum_get(ptr, "timing_mode");
+ int realtime = RNA_boolean_get(ptr, "use_realtime");
+ float gap_duration = RNA_float_get(ptr, "gap_duration");
+ float gap_randomness = RNA_float_get(ptr, "gap_randomness");
+ int valid_timing = RNA_boolean_get(ptr, "use_timing_data");
+
+ /* Always show those props */
+ if (strcmp(prop_id, "type") == 0 ||
+ strcmp(prop_id, "use_normalize_weights") == 0 ||
+ strcmp(prop_id, "radius_multiplier") == 0 ||
+ strcmp(prop_id, "use_link_strokes") == 0)
+ {
+ return TRUE;
+ }
+
+ /* Never show this prop */
+ if (strcmp(prop_id, "use_timing_data") == 0)
+ return FALSE;
+
+ if (link_strokes) {
+ /* Only show when link_stroke is TRUE */
+ if (strcmp(prop_id, "timing_mode") == 0)
+ return TRUE;
+
+ if (timing_mode != GP_STROKECONVERT_TIMING_NONE) {
+ /* Only show when link_stroke is TRUE and stroke timing is enabled */
+ if (strcmp(prop_id, "frame_range") == 0 ||
+ strcmp(prop_id, "start_frame") == 0)
+ {
+ return TRUE;
+ }
+
+ /* Only show if we have valid timing data! */
+ if (valid_timing && strcmp(prop_id, "use_realtime") == 0)
+ return TRUE;
+
+ /* Only show if realtime or valid_timing is FALSE! */
+ if ((!realtime || !valid_timing) && strcmp(prop_id, "end_frame") == 0)
+ return TRUE;
+
+ if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
+ /* Only show for custom gaps! */
+ if (strcmp(prop_id, "gap_duration") == 0)
+ return TRUE;
+
+ /* Only show randomness for non-null custom gaps! */
+ if (strcmp(prop_id, "gap_randomness") == 0 && gap_duration > 0.0f)
+ return TRUE;
+
+ /* Only show seed for randomize action! */
+ if (strcmp(prop_id, "seed") == 0 && gap_duration > 0.0f && gap_randomness > 0.0f)
+ return TRUE;
+ }
+ }
+ }
+
+ /* Else, hidden! */
+ return FALSE;
+}
+
+static void gp_convert_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ /* Main auto-draw call */
+ uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0');
+}
+
void GPENCIL_OT_convert(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Convert Grease Pencil";
ot->idname = "GPENCIL_OT_convert";
- ot->description = "Convert the active Grease Pencil layer to a new Object";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->description = "Convert the active Grease Pencil layer to a new Curve Object";
/* callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = gp_convert_layer_exec;
ot->poll = gp_convert_poll;
+ ot->ui = gp_convert_ui;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to");
+ RNA_def_boolean(ot->srna, "use_normalize_weights", TRUE, "Normalize Weight",
+ "Normalize weight (set from stroke width)");
+ RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac",
+ "Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f);
+ RNA_def_boolean(ot->srna, "use_link_strokes", TRUE, "Link Strokes",
+ "Whether to link strokes with zero-radius sections of curves");
+ prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL,
+ "Timing Mode", "How to use timing data stored in strokes");
+ RNA_def_enum_funcs(prop, rna_GPConvert_mode_items);
+ RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range",
+ "The duration of evaluation of the path control curve", 1, 1000);
+ RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame",
+ "The start frame of the path control curve", 1, 100000);
+ RNA_def_boolean(ot->srna, "use_realtime", FALSE, "Realtime",
+ "Whether the path control curve reproduces the drawing in realtime, starting from Start Frame");
+ prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame",
+ "The end frame of the path control curve (if Realtime is not set)", 1, 100000);
+ RNA_def_property_update_runtime(prop, gp_convert_set_end_frame);
+ RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration",
+ "Custom Gap mode: (Average) length of gaps, in frames "
+ "(note: realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f);
+ RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 10000.0f, "Gap Randomness",
+ "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f);
+ RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed",
+ "Custom Gap mode: Random generator seed", 0, 100);
+ /* Note: Internal use, this one will always be hidden by UI code... */
+ prop = RNA_def_boolean(ot->srna, "use_timing_data", FALSE, "Has Valid Timing",
+ "Whether the converted grease pencil layer has valid timing data (internal use)");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ************************************************ */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 9bfd89075af..fcead283033 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 "PIL_time.h"
+
#include "BKE_gpencil.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -99,6 +101,14 @@ typedef struct tGPsdata {
short radius; /* radius of influence for eraser */
short flags; /* flags that can get set during runtime */
+ /* Those needs to be doubles, as (at least under unix) they are in seconds since epoch,
+ * float (and its 7 digits precision) is definitively not enough here!
+ * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least.
+ */
+ double inittime; /* Used when converting to path */
+ double curtime; /* Used when converting to path */
+ double ocurtime; /* Used when converting to path */
+
float imat[4][4]; /* inverted transformation matrix applying when converting coords from screen-space
* to region space */
@@ -201,7 +211,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3])
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
+#if 0 /* XXX: disabled for now, since we can't draw relative to the owner yet */
if (p->ownerPtr.type == &RNA_Object) {
Object *ob = (Object *)p->ownerPtr.data;
@@ -249,7 +259,7 @@ static short gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2])
}
/* convert screen-coordinates to buffer-coordinates */
-// XXX this method needs a total overhaul!
+/* XXX this method needs a total overhaul! */
static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3], float *depth)
{
bGPdata *gpd = p->gpd;
@@ -310,7 +320,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
}
/* add current stroke-point to buffer (returns whether point was successfully added) */
-static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure)
+static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, double curtime)
{
bGPdata *gpd = p->gpd;
tGPspoint *pt;
@@ -325,6 +335,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure)
/* store settings */
copy_v2_v2_int(&pt->x, mval);
pt->pressure = pressure;
+ pt->time = (float)(curtime - p->inittime);
/* increment buffer size */
gpd->sbuffer_size++;
@@ -338,6 +349,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure)
/* store settings */
copy_v2_v2_int(&pt->x, mval);
pt->pressure = pressure;
+ pt->time = (float)(curtime - p->inittime);
/* if this is just the second point we've added, increment the buffer size
* so that it will be drawn properly...
@@ -361,6 +373,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure)
/* store settings */
copy_v2_v2_int(&pt->x, mval);
pt->pressure = pressure;
+ pt->time = (float)(curtime - p->inittime);
/* increment counters */
gpd->sbuffer_size++;
@@ -378,10 +391,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure)
/* store settings */
copy_v2_v2_int(&pt->x, mval);
pt->pressure = pressure;
+ pt->time = (float)(curtime - p->inittime);
/* if there's stroke for this poly line session add (or replace last) point
* to stroke. This allows to draw lines more interactively (see new segment
- * during mouse slide, i.e.)
+ * during mouse slide, e.g.)
*/
if (gp_stroke_added_check(p)) {
bGPDstroke *gps = p->gpf->strokes.last;
@@ -410,8 +424,9 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure)
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL);
- /* copy pressure */
+ /* copy pressure and time */
pts->pressure = pt->pressure;
+ pts->time = pt->time;
}
/* increment counters */
@@ -425,18 +440,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure)
return GP_STROKEADD_INVALID;
}
-
-/* temp struct for gp_stroke_smooth() */
-typedef struct tGpSmoothCo {
- int x;
- int y;
-} tGpSmoothCo;
-
/* smooth a stroke (in buffer) before storing it */
static void gp_stroke_smooth(tGPsdata *p)
{
bGPdata *gpd = p->gpd;
- tGpSmoothCo *smoothArray, *spc;
+ tGPspoint *spt, tmp_spt[3];
int i = 0, cmx = gpd->sbuffer_size;
/* only smooth if smoothing is enabled, and we're not doing a straight line */
@@ -447,30 +455,26 @@ static void gp_stroke_smooth(tGPsdata *p)
if ((cmx <= 2) || (gpd->sbuffer == NULL))
return;
- /* create a temporary smoothing coordinates buffer, use to store calculated values to prevent sequential error */
- smoothArray = MEM_callocN(sizeof(tGpSmoothCo) * cmx, "gp_stroke_smooth smoothArray");
-
- /* first pass: calculate smoothing coordinates using weighted-averages */
- for (i = 0, spc = smoothArray; i < gpd->sbuffer_size; i++, spc++) {
- const tGPspoint *pc = (((tGPspoint *)gpd->sbuffer) + i);
- const tGPspoint *pb = (i - 1 > 0) ? (pc - 1) : (pc);
- const tGPspoint *pa = (i - 2 > 0) ? (pc - 2) : (pb);
- const tGPspoint *pd = (i + 1 < cmx) ? (pc + 1) : (pc);
+ /* Calculate smoothing coordinates using weighted-averages */
+ /* XXX DO NOT smooth first and last points! */
+ spt = (tGPspoint *)gpd->sbuffer;
+ /* This small array stores the last two points' org coordinates, we don't want to use already averaged ones!
+ * Note it is used as a cyclic buffer...
+ */
+ tmp_spt[0] = *spt;
+ for (i = 1, spt++; i < cmx - 1; i++, spt++) {
+ const tGPspoint *pc = spt;
+ const tGPspoint *pb = &tmp_spt[(i - 1) % 3];
+ const tGPspoint *pa = (i - 1 > 0) ? (&tmp_spt[(i - 2) % 3]) : (pb);
+ const tGPspoint *pd = pc + 1;
const tGPspoint *pe = (i + 2 < cmx) ? (pc + 2) : (pd);
- spc->x = (int)(0.1 * pa->x + 0.2 * pb->x + 0.4 * pc->x + 0.2 * pd->x + 0.1 * pe->x);
- spc->y = (int)(0.1 * pa->y + 0.2 * pb->y + 0.4 * pc->y + 0.2 * pd->y + 0.1 * pe->y);
- }
-
- /* second pass: apply smoothed coordinates */
- for (i = 0, spc = smoothArray; i < gpd->sbuffer_size; i++, spc++) {
- tGPspoint *pc = (((tGPspoint *)gpd->sbuffer) + i);
+ /* Store current point's org state for the two next points! */
+ tmp_spt[i % 3] = *spt;
- copy_v2_v2_int(&pc->x, &spc->x);
+ spt->x = (int)(0.1 * pa->x + 0.2 * pb->x + 0.4 * pc->x + 0.2 * pd->x + 0.1 * pe->x);
+ spt->y = (int)(0.1 * pa->y + 0.2 * pb->y + 0.4 * pc->y + 0.2 * pd->y + 0.1 * pe->y);
}
-
- /* free temp array */
- MEM_freeN(smoothArray);
}
/* simplify a stroke (in buffer) before storing it
@@ -492,7 +496,7 @@ static void gp_stroke_simplify(tGPsdata *p)
/* don't simplify if less than 4 points in buffer */
if ((num_points <= 4) || (old_points == NULL))
return;
-
+
/* clear buffer (but don't free mem yet) so that we can write to it
* - firstly set sbuffer to NULL, so a new one is allocated
* - secondly, reset flag after, as it gets cleared auto
@@ -509,17 +513,21 @@ static void gp_stroke_simplify(tGPsdata *p)
co[0] += (float)(old_points[offs].x * sfac); \
co[1] += (float)(old_points[offs].y * sfac); \
pressure += old_points[offs].pressure * sfac; \
+ time += old_points[offs].time * sfac; \
} (void)0
+ /* XXX Here too, do not lose start and end points! */
+ gp_stroke_addpoint(p, &old_points->x, old_points->pressure, p->inittime + (double)old_points->time);
for (i = 0, j = 0; i < num_points; i++) {
if (i - j == 3) {
- float co[2], pressure;
+ float co[2], pressure, time;
int mco[2];
/* initialize values */
- co[0] = 0;
- co[1] = 0;
- pressure = 0;
+ co[0] = 0.0f;
+ co[1] = 0.0f;
+ pressure = 0.0f;
+ time = 0.0f;
/* using macro, calculate new point */
GP_SIMPLIFY_AVPOINT(j, -0.25f);
@@ -532,11 +540,13 @@ static void gp_stroke_simplify(tGPsdata *p)
mco[1] = (int)co[1];
/* ignore return values on this... assume to be ok for now */
- gp_stroke_addpoint(p, mco, pressure);
+ gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time);
j += 2;
}
}
+ gp_stroke_addpoint(p, &old_points[num_points - 1].x, old_points[num_points - 1].pressure,
+ p->inittime + (double)old_points[num_points - 1].time);
/* free old buffer */
MEM_freeN(old_points);
@@ -571,7 +581,8 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* special case for poly line -- for already added stroke during session
* coordinates are getting added to stroke immediately to allow more
- * interactive behavior */
+ * interactive behavior
+ */
if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
if (gp_stroke_added_check(p)) {
return;
@@ -585,6 +596,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
gps->totpoints = totelem;
gps->thickness = p->gpl->thickness;
gps->flag = gpd->sbuffer_sflag;
+ gps->inittime = p->inittime;
/* allocate enough memory for a continuous array for storage points */
gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
@@ -602,8 +614,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
- /* copy pressure */
+ /* copy pressure and time */
pt->pressure = ptc->pressure;
+ pt->time = ptc->time;
pt++;
}
@@ -615,8 +628,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
- /* copy pressure */
+ /* copy pressure and time */
pt->pressure = ptc->pressure;
+ pt->time = ptc->time;
}
}
else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
@@ -626,8 +640,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
- /* copy pressure */
+ /* copy pressure and time */
pt->pressure = ptc->pressure;
+ pt->time = ptc->time;
}
else {
float *depth_arr = NULL;
@@ -699,8 +714,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL);
- /* copy pressure */
+ /* copy pressure and time */
pt->pressure = ptc->pressure;
+ pt->time = ptc->time;
}
if (depth_arr)
@@ -750,6 +766,25 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
gps->totpoints--;
gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint) * gps->totpoints);
+
+ /* We must adjust timings!
+ * Each point's timing data is a delta from stroke's inittime, so as we erase the first
+ * point of the stroke, we have to offset this inittime and all remaing points' delta values.
+ * This way we get a new stroke with exactly the same timing as if user had started drawing from
+ * the second point...
+ */
+ {
+ bGPDspoint *pts;
+ float delta = pt_tmp[1].time;
+ int j;
+
+ gps->inittime += delta;
+
+ pts = gps->points;
+ for (j = 0; j < gps->totpoints; j++, pts++) {
+ pts->time -= delta;
+ }
+ }
/* free temp buffer */
MEM_freeN(pt_tmp);
@@ -769,6 +804,25 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
gsn->points = MEM_callocN(sizeof(bGPDspoint) * gsn->totpoints, "gp_stroke_points");
memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint) * gsn->totpoints);
+ /* We must adjust timings of this new stroke!
+ * Each point's timing data is a delta from stroke's inittime, so as we erase the first
+ * point of the stroke, we have to offset this inittime and all remaing points' delta values.
+ * This way we get a new stroke with exactly the same timing as if user had started drawing from
+ * the second point...
+ */
+ {
+ bGPDspoint *pts;
+ float delta = pt_tmp[i].time;
+ int j;
+
+ gsn->inittime += delta;
+
+ pts = gsn->points;
+ for (j = 0; j < gsn->totpoints; j++, pts++) {
+ pts->time -= delta;
+ }
+ }
+
/* adjust existing stroke */
gps->totpoints = i;
gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
@@ -831,7 +885,7 @@ static void gp_point_to_xy(ARegion *ar, View2D *v2d, rctf *subrect, bGPDstroke *
/* eraser tool - evaluation per stroke */
-// TODO: this could really do with some optimization (KD-Tree/BVH?)
+/* TODO: this could really do with some optimization (KD-Tree/BVH?) */
static void gp_stroke_eraser_dostroke(tGPsdata *p,
const int mval[], const int mvalo[],
short rad, const rcti *rect, bGPDframe *gpf, bGPDstroke *gps)
@@ -919,11 +973,11 @@ static void gp_session_validatebuffer(tGPsdata *p)
/* clear memory of buffer (or allocate it if starting a new session) */
if (gpd->sbuffer) {
- //printf("\t\tGP - reset sbuffer\n");
+ /* printf("\t\tGP - reset sbuffer\n"); */
memset(gpd->sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
}
else {
- //printf("\t\tGP - allocate sbuffer\n");
+ /* printf("\t\tGP - allocate sbuffer\n"); */
gpd->sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
}
@@ -932,6 +986,9 @@ static void gp_session_validatebuffer(tGPsdata *p)
/* reset flags */
gpd->sbuffer_sflag = 0;
+
+ /* reset inittime */
+ p->inittime = 0.0;
}
/* (re)init new painting data */
@@ -959,8 +1016,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
/* supported views first */
case SPACE_VIEW3D:
{
- // View3D *v3d = curarea->spacedata.first;
- // RegionView3D *rv3d = ar->regiondata;
+ /* View3D *v3d = curarea->spacedata.first; */
+ /* RegionView3D *rv3d = ar->regiondata; */
/* set current area
* - must verify that region data is 3D-view (and not something else)
@@ -979,7 +1036,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
case SPACE_NODE:
{
- //SpaceNode *snode = curarea->spacedata.first;
+ /* SpaceNode *snode = curarea->spacedata.first; */
/* set current area */
p->sa = curarea;
@@ -1007,7 +1064,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
break;
case SPACE_IMAGE:
{
- //SpaceImage *sima = curarea->spacedata.first;
+ /* SpaceImage *sima = curarea->spacedata.first; */
/* set the current area */
p->sa = curarea;
@@ -1072,7 +1129,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
if (ED_gpencil_session_active() == 0) {
/* initialize undo stack,
- * also, existing undo stack would make buffer drawn */
+ * also, existing undo stack would make buffer drawn
+ */
gpencil_undo_init(p->gpd);
}
@@ -1107,7 +1165,7 @@ static void gp_session_cleanup(tGPsdata *p)
/* free stroke buffer */
if (gpd->sbuffer) {
- //printf("\t\tGP - free sbuffer\n");
+ /* printf("\t\tGP - free sbuffer\n"); */
MEM_freeN(gpd->sbuffer);
gpd->sbuffer = NULL;
}
@@ -1115,6 +1173,7 @@ static void gp_session_cleanup(tGPsdata *p)
/* clear flags */
gpd->sbuffer_size = 0;
gpd->sbuffer_sflag = 0;
+ p->inittime = 0.0;
}
/* init new stroke */
@@ -1259,7 +1318,8 @@ static void gp_paint_strokeend(tGPsdata *p)
static void gp_paint_cleanup(tGPsdata *p)
{
/* p->gpd==NULL happens when stroke failed to initialize,
- * for example. when GP is hidden in current space (sergey) */
+ * for example when GP is hidden in current space (sergey)
+ */
if (p->gpd) {
/* finish off a stroke */
gp_paint_strokeend(p);
@@ -1307,7 +1367,7 @@ static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short en
else if (enable) {
/* enable cursor */
p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- NULL, // XXX
+ NULL, /* XXX */
gpencil_draw_eraser, p);
}
}
@@ -1448,16 +1508,26 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p)
/* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */
else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) {
/* try to add point */
- short ok = gp_stroke_addpoint(p, p->mval, p->pressure);
+ short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime);
/* handle errors while adding point */
if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) {
/* finish off old stroke */
gp_paint_strokeend(p);
+ /* And start a new one!!! Else, projection errors! */
+ gp_paint_initstroke(p, p->paintmode);
/* start a new stroke, starting from previous point */
- gp_stroke_addpoint(p, p->mvalo, p->opressure);
- gp_stroke_addpoint(p, p->mval, p->pressure);
+ /* XXX Must manually reset inittime... */
+ /* XXX We only need to reuse previous point if overflow! */
+ if (ok == GP_STROKEADD_OVERFLOW) {
+ p->inittime = p->ocurtime;
+ gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime);
+ }
+ else {
+ p->inittime = p->curtime;
+ }
+ gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime);
}
else if (ok == GP_STROKEADD_INVALID) {
/* the painting operation cannot continue... */
@@ -1473,6 +1543,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p)
p->mvalo[0] = p->mval[0];
p->mvalo[1] = p->mval[1];
p->opressure = p->pressure;
+ p->ocurtime = p->curtime;
}
}
@@ -1485,10 +1556,11 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event)
int tablet = 0;
/* convert from window-space to area-space mouse coordinates
- * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding...
+ * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding...
*/
p->mval[0] = event->mval[0] + 1;
p->mval[1] = event->mval[1] + 1;
+ p->curtime = PIL_check_seconds_timer();
/* handle pressure sensitivity (which is supplied by tablets) */
if (event->custom == EVT_DATA_TABLET) {
@@ -1497,8 +1569,8 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event)
tablet = (wmtab->Active != EVT_TABLET_NONE);
p->pressure = wmtab->Pressure;
- //if (wmtab->Active == EVT_TABLET_ERASER)
- // TODO... this should get caught by the keymaps which call drawing in the first place
+ /* if (wmtab->Active == EVT_TABLET_ERASER) */
+ /* TODO... this should get caught by the keymaps which call drawing in the first place */
}
else
p->pressure = 1.0f;
@@ -1519,14 +1591,17 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event)
p->mvalo[0] = p->mval[0];
p->mvalo[1] = p->mval[1];
p->opressure = p->pressure;
-
+ p->inittime = p->ocurtime = p->curtime;
+
/* special exception here for too high pressure values on first touch in
- * windows for some tablets, then we just skip first touch ..
+ * windows for some tablets, then we just skip first touch...
*/
if (tablet && (p->pressure >= 0.99f))
return;
}
+ RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
+
/* apply the current latest drawing point */
gpencil_draw_apply(op, p);
@@ -1541,18 +1616,18 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
{
tGPsdata *p = NULL;
- //printf("GPencil - Starting Re-Drawing\n");
+ /* printf("GPencil - Starting Re-Drawing\n"); */
/* try to initialize context data needed while drawing */
if (!gpencil_draw_init(C, op)) {
if (op->customdata) MEM_freeN(op->customdata);
- //printf("\tGP - no valid data\n");
+ /* printf("\tGP - no valid data\n"); */
return OPERATOR_CANCELLED;
}
else
p = op->customdata;
- //printf("\tGP - Start redrawing stroke\n");
+ /* printf("\tGP - Start redrawing stroke\n"); */
/* loop over the stroke RNA elements recorded (i.e. progress of mouse movement),
* setting the relevant values in context at each step, then applying
@@ -1561,20 +1636,21 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
{
float mousef[2];
- //printf("\t\tGP - stroke elem\n");
+ /* printf("\t\tGP - stroke elem\n"); */
/* get relevant data for this point from stroke */
RNA_float_get_array(&itemptr, "mouse", mousef);
p->mval[0] = (int)mousef[0];
p->mval[1] = (int)mousef[1];
p->pressure = RNA_float_get(&itemptr, "pressure");
+ p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime;
if (RNA_boolean_get(&itemptr, "is_start")) {
/* if first-run flag isn't set already (i.e. not true first stroke),
* then we must terminate the previous one first before continuing
*/
if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) {
- // TODO: both of these ops can set error-status, but we probably don't need to worry
+ /* TODO: both of these ops can set error-status, but we probably don't need to worry */
gp_paint_strokeend(p);
gp_paint_initstroke(p, p->paintmode);
}
@@ -1587,6 +1663,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
p->mvalo[0] = p->mval[0];
p->mvalo[1] = p->mval[1];
p->opressure = p->pressure;
+ p->ocurtime = p->curtime;
}
/* apply this data as necessary now (as per usual) */
@@ -1594,7 +1671,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
}
RNA_END;
- //printf("\tGP - done\n");
+ /* printf("\tGP - done\n"); */
/* cleanup */
gpencil_draw_exit(C, op);
@@ -1640,7 +1717,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event)
/* set cursor */
if (p->paintmode == GP_PAINTMODE_ERASER)
- WM_cursor_modal(win, BC_CROSSCURSOR); // XXX need a better cursor
+ WM_cursor_modal(win, BC_CROSSCURSOR); /* XXX need a better cursor */
else
WM_cursor_modal(win, BC_PAINTBRUSHCURSOR);
@@ -1650,7 +1727,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event)
*/
if (event->val == KM_PRESS) {
/* hotkey invoked - start drawing */
- //printf("\tGP - set first spot\n");
+ /* printf("\tGP - set first spot\n"); */
p->status = GP_STATUS_PAINTING;
/* handle the initial drawing - i.e. for just doing a simple dot */
@@ -1658,7 +1735,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
else {
/* toolbar invoked - don't start drawing yet... */
- //printf("\tGP - hotkey invoked... waiting for click-drag\n");
+ /* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */
}
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
@@ -1686,7 +1763,7 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
p->status = GP_STATUS_ERROR;
}
- //printf("\t\tGP - start stroke\n");
+ /* printf("\t\tGP - start stroke\n"); */
/* we may need to set up paint env again if we're resuming */
/* XXX: watch it with the paintmode! in future,
@@ -1723,7 +1800,7 @@ static void gpencil_stroke_end(wmOperator *op)
static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event)
{
tGPsdata *p = op->customdata;
- int estate = OPERATOR_RUNNING_MODAL; /* default exit state - we don't pass on events, GP is used with key-modifiers */
+ int estate = OPERATOR_PASS_THROUGH; /* default exit state */
/* if (event->type == NDOF_MOTION)
* return OPERATOR_PASS_THROUGH;
@@ -1735,8 +1812,13 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event)
* the stroke is converted to 3D only after
* it is finished. This approach should work
* better in tools that immediately apply
- * in 3D space. */
+ * in 3D space.
+ */
+ /* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */
+ if (ISKEYBOARD(event->type))
+ estate = OPERATOR_RUNNING_MODAL;
+
//printf("\tGP - handle modal event...\n");
/* exit painting mode (and/or end current stroke)
@@ -1744,7 +1826,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event)
*/
if (ELEM4(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) {
/* exit() ends the current stroke before cleaning up */
- //printf("\t\tGP - end of paint op + end of stroke\n");
+ /* printf("\t\tGP - end of paint op + end of stroke\n"); */
p->status = GP_STATUS_DONE;
estate = OPERATOR_FINISHED;
}
@@ -1768,7 +1850,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event)
if (sketch) {
/* end stroke only, and then wait to resume painting soon */
- //printf("\t\tGP - end stroke only\n");
+ /* printf("\t\tGP - end stroke only\n"); */
gpencil_stroke_end(op);
/* we've just entered idling state, so this event was processed (but no others yet) */
@@ -1778,7 +1860,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event)
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
}
else {
- //printf("\t\tGP - end of stroke + op\n");
+ /* printf("\t\tGP - end of stroke + op\n"); */
p->status = GP_STATUS_DONE;
estate = OPERATOR_FINISHED;
}
@@ -1801,7 +1883,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event)
/* handle painting mouse-movements? */
if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
/* handle drawing event */
- //printf("\t\tGP - add point\n");
+ /* printf("\t\tGP - add point\n"); */
gpencil_draw_apply_event(op, event);
/* finish painting operation if anything went wrong just now */
@@ -1811,7 +1893,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event)
}
else {
/* event handled, so just tag as running modal */
- //printf("\t\t\t\tGP - add point handled!\n");
+ /* printf("\t\t\t\tGP - add point handled!\n"); */
estate = OPERATOR_RUNNING_MODAL;
}
}
@@ -1822,7 +1904,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event)
/* just resize the brush (local version)
* TODO: fix the hardcoded size jumps (set to make a visible difference) and hardcoded keys
*/
- //printf("\t\tGP - resize eraser\n");
+ /* printf("\t\tGP - resize eraser\n"); */
switch (event->type) {
case WHEELUPMOUSE: /* larger */
case PADPLUSKEY:
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 1d461f797d6..39dd8822267 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -56,6 +56,7 @@ struct wmKeyConfig;
typedef struct tGPspoint {
int x, y; /* x and y coordinates of cursor (in relative to area) */
float pressure; /* pressure of tablet at this point */
+ float time; /* Time relative to stroke start (used when converting to path) */
} tGPspoint;
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index ed4b4ae027f..3645f13f27a 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -807,7 +807,7 @@ void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *p
void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type, int levels, int brush);
-void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic);
+void uiTemplateColorPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic);
void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
PointerRNA *used_ptr, const char *used_propname, int active_layer);
void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 77aa2ce154d..7391d29c9bf 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -218,7 +218,11 @@ enum {
TH_NLA_META,
TH_NLA_META_SEL,
TH_NLA_SOUND,
- TH_NLA_SOUND_SEL
+ TH_NLA_SOUND_SEL,
+
+ TH_AXIS_X, /* X/Y/Z Axis */
+ TH_AXIS_Y,
+ TH_AXIS_Z
};
/* XXX WARNING: previous is saved in file, so do not change order! */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index c6e25ab9a34..e2f105b5761 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -2424,7 +2424,7 @@ void uiBlockEndAlign(uiBlock *block)
int ui_but_can_align(uiBut *but)
{
- return !ELEM3(but->type, LABEL, OPTION, OPTIONN);
+ return !ELEM4(but->type, LABEL, OPTION, OPTIONN, SEPR);
}
static void ui_block_do_align_but(uiBut *first, short nr)
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index ecb161714ee..5f01255b8e0 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -279,12 +279,7 @@ static int ui_is_a_warp_but(uiBut *but)
static float ui_mouse_scale_warp_factor(const short shift)
{
- if (U.uiflag & USER_CONTINUOUS_MOUSE) {
- return shift ? 0.05f : 1.0f;
- }
- else {
- return 1.0f;
- }
+ return shift ? 0.05f : 1.0f;
}
static void ui_mouse_scale_warp(uiHandleButtonData *data,
@@ -292,16 +287,11 @@ static void ui_mouse_scale_warp(uiHandleButtonData *data,
float *r_mx, float *r_my,
const short shift)
{
- if (U.uiflag & USER_CONTINUOUS_MOUSE) {
- const float fac = ui_mouse_scale_warp_factor(shift);
- /* slow down the mouse, this is fairly picky */
- *r_mx = (data->dragstartx * (1.0f - fac) + mx * fac);
- *r_my = (data->dragstarty * (1.0f - fac) + my * fac);
- }
- else {
- *r_mx = mx;
- *r_my = my;
- }
+ const float fac = ui_mouse_scale_warp_factor(shift);
+
+ /* slow down the mouse, this is fairly picky */
+ *r_mx = (data->dragstartx * (1.0f - fac) + mx * fac);
+ *r_my = (data->dragstarty * (1.0f - fac) + my * fac);
}
/* file selectors are exempt from utf-8 checks */
@@ -6050,38 +6040,22 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
switch (event->type) {
case MOUSEMOVE:
{
- /* if the mouse is over the button, do nothing */
- if (ui_mouse_inside_button(data->region, but, event->x, event->y)) {
- break;
- }
+ uiBut *bt;
- /* if the mouse is over the menu, also do nothing */
if (data->menu && data->menu->region) {
if (ui_mouse_inside_region(data->menu->region, event->x, event->y)) {
break;
}
- else {
- /* make a rectangle between the menu and the button that opened it,
- * this avoids any space between them exiting the popup. see [#29072] - campbell */
- rctf rct_all = but->rect;
- rctf rct_win;
-
- ui_block_to_window_fl(ar, block, &rct_all.xmin, &rct_all.ymin);
- ui_block_to_window_fl(ar, block, &rct_all.xmax, &rct_all.ymax);
-
- BLI_rctf_rcti_copy(&rct_win, &data->menu->region->winrct);
- BLI_rctf_union(&rct_all, &rct_win);
-
- if (BLI_rctf_isect_pt(&rct_all, event->x, event->y)) {
- break;
- }
- }
}
- if (but->type != COLOR) { /* exception */
- data->cancel = TRUE;
+ bt = ui_but_find_mouse_over(ar, event->x, event->y);
+
+ if (bt && bt->active != data) {
+ if (but->type != COLOR) { /* exception */
+ data->cancel = TRUE;
+ }
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
}
- button_activate_state(C, but, BUTTON_STATE_EXIT);
break;
}
}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 28e361ccf5a..9b77072dee1 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -2254,13 +2254,11 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_
show_picker = (but->block->flag & UI_BLOCK_POPUP) == 0;
}
- uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
-
copy_v3_v3(handle->retvec, but->editvec);
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;
+ block->flag = UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1 | UI_BLOCK_MOVEMOUSE_QUIT;
uiBoundsBlock(block, 10);
block->block_event_func = ui_picker_small_wheel_cb;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index c7e6a5f2882..68d85aab80f 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1952,11 +1952,12 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propn
MEM_freeN(cb);
}
-/********************* ColorWheel Template ************************/
+/********************* ColorPicker Template ************************/
#define WHEEL_SIZE 100
-void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic)
+/* This template now follows User Preference for type - name is not correct anymore... */
+void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
uiBlock *block = uiLayoutGetBlock(layout);
@@ -1971,10 +1972,24 @@ void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propnam
RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
- col = uiLayoutColumn(layout, FALSE);
+ col = uiLayoutColumn(layout, TRUE);
row = uiLayoutRow(col, TRUE);
- but = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, "");
+ switch (U.color_picker_type) {
+ case USER_CP_CIRCLE:
+ but = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, "");
+ break;
+ case USER_CP_SQUARE_SV:
+ but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, UI_GRAD_SV, 0, "");
+ break;
+ case USER_CP_SQUARE_HS:
+ but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, UI_GRAD_HS, 0, "");
+ break;
+ case USER_CP_SQUARE_HV:
+ but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, UI_GRAD_HV, 0, "");
+ break;
+ }
+
if (lock) {
but->flag |= UI_BUT_COLOR_LOCK;
@@ -1990,10 +2005,29 @@ void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propnam
if (cubic)
but->flag |= UI_BUT_COLOR_CUBIC;
- uiItemS(row);
- if (value_slider)
- uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, "");
+ if (value_slider) {
+
+ switch (U.color_picker_type) {
+ case USER_CP_CIRCLE:
+ uiItemS(row);
+ uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, "");
+ break;
+ case USER_CP_SQUARE_SV:
+ uiItemS(col);
+ uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, -1, softmin, softmax, UI_GRAD_SV + 3, 0, "");
+ break;
+ case USER_CP_SQUARE_HS:
+ uiItemS(col);
+ uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, -1, softmin, softmax, UI_GRAD_HS + 3, 0, "");
+ break;
+ case USER_CP_SQUARE_HV:
+ uiItemS(col);
+ uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, -1, softmin, softmax, UI_GRAD_HV + 3, 0, "");
+ break;
+ }
+
+ }
}
/********************* Layer Buttons Template ************************/
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index f41abce947e..c836d62021e 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1044,6 +1044,8 @@ static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, rcti *rect)
ui_text_clip_give_prev_off(but);
len = strlen(but->drawstr);
bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + len));
+ if (bytes < 0)
+ bytes = 1;
but->drawstr[len - bytes] = 0;
}
@@ -2057,7 +2059,7 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa
/* old below */
- for (dx = 0.0f; dx < 1.0f; dx += color_step) {
+ for (dx = 0.0f; dx < 0.999f; dx += color_step) { /* 0.999 = prevent float inaccuracy for steps */
/* previous color */
copy_v3_v3(col0[0], col1[0]);
copy_v3_v3(col0[1], col1[1]);
@@ -2112,7 +2114,7 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa
sx1 = rect->xmin + dx * BLI_rcti_size_x(rect);
sx2 = rect->xmin + (dx + color_step) * BLI_rcti_size_x(rect);
sy = rect->ymin;
- dy = BLI_rcti_size_y(rect) / 3.0;
+ dy = (float)BLI_rcti_size_y(rect) / 3.0f;
glBegin(GL_QUADS);
for (a = 0; a < 3; a++, sy += dy) {
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index de79a290cb3..d0189e0f5b4 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -236,7 +236,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->shade2; break;
case TH_HILITE:
cp = ts->hilite; break;
-
+
case TH_GRID:
cp = ts->grid; break;
case TH_WIRE:
@@ -514,6 +514,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_NLA_SOUND_SEL:
cp = ts->nla_sound_sel;
break;
+
+ case TH_AXIS_X:
+ cp = btheme->tui.xaxis; break;
+ case TH_AXIS_Y:
+ cp = btheme->tui.yaxis; break;
+ case TH_AXIS_Z:
+ cp = btheme->tui.zaxis; break;
}
}
}
@@ -659,9 +666,14 @@ void ui_theme_init_default(void)
/* UI buttons */
ui_widget_color_init(&btheme->tui);
+
btheme->tui.iconfile[0] = 0;
btheme->tui.panel.show_header = FALSE;
rgba_char_args_set(btheme->tui.panel.header, 0, 0, 0, 25);
+
+ rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255);
+ rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255);
+ rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255);
/* Bone Color Sets */
ui_theme_init_boneColorSets(btheme);
@@ -1078,7 +1090,6 @@ float UI_GetThemeValuef(int colorid)
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
return ((float)cp[0]);
-
}
/* get individual values, not scaled */
@@ -1088,7 +1099,6 @@ int UI_GetThemeValue(int colorid)
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
return ((int) cp[0]);
-
}
@@ -1250,21 +1260,20 @@ void UI_ThemeClearColor(int colorid)
void UI_make_axis_color(const unsigned char src_col[3], unsigned char dst_col[3], const char axis)
{
+ unsigned char col[3];
+
switch (axis) {
case 'X':
- dst_col[0] = src_col[0] > 219 ? 255 : src_col[0] + 36;
- dst_col[1] = src_col[1] < 26 ? 0 : src_col[1] - 26;
- dst_col[2] = src_col[2] < 26 ? 0 : src_col[2] - 26;
+ UI_GetThemeColor3ubv(TH_AXIS_X, col);
+ UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10);
break;
case 'Y':
- dst_col[0] = src_col[0] < 46 ? 0 : src_col[0] - 36;
- dst_col[1] = src_col[1] > 189 ? 255 : src_col[1] + 66;
- dst_col[2] = src_col[2] < 46 ? 0 : src_col[2] - 36;
+ UI_GetThemeColor3ubv(TH_AXIS_Y, col);
+ UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10);
break;
case 'Z':
- dst_col[0] = src_col[0] < 26 ? 0 : src_col[0] - 26;
- dst_col[1] = src_col[1] < 26 ? 0 : src_col[1] - 26;
- dst_col[2] = src_col[2] > 209 ? 255 : src_col[2] + 46;
+ UI_GetThemeColor3ubv(TH_AXIS_Z, col);
+ UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10);
break;
default:
BLI_assert(!"invalid axis arg");
@@ -1952,6 +1961,16 @@ void init_userdef_do_versions(void)
rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255);
}
}
+
+ if (bmain->versionfile < 264 || (bmain->versionfile == 264 && bmain->subversionfile < 9)) {
+ bTheme *btheme;
+
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255);
+ rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255);
+ rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255);
+ }
+ }
/* Freestyle color settings */
{
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 8e5c89adfca..bf4ee0eb61f 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -261,7 +261,7 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select)
lasteed = eed;
}
- if (lasteed != startedge && BM_edge_share_face_count(lasteed, startedge)) {
+ if (lasteed != startedge && BM_edge_share_face_check(lasteed, startedge)) {
v[1][0] = v[0][0];
v[1][1] = v[0][1];
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 3e985a9779c..c2f2e97b86a 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -1177,19 +1177,17 @@ void MESH_OT_edgering_select(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring");
}
-/* ******************* edgetag_shortest_path and helpers ****************** */
+/* ******************* generic tag_shortest_path and helpers ****************** */
-static float edgetag_cut_cost(BMEditMesh *UNUSED(em), BMEdge *e1, BMEdge *e2, BMVert *v)
+static float step_cost_3_v3(const float v1[3], const float v2[3], const float v3[3])
{
- BMVert *v1 = (e1->v1 == v) ? e1->v2 : e1->v1;
- BMVert *v2 = (e2->v1 == v) ? e2->v2 : e2->v1;
float cost, d1[3], d2[3];
+
/* The cost is based on the simple sum of the length of the two edgees... */
- sub_v3_v3v3(d1, v->co, v1->co);
- sub_v3_v3v3(d2, v2->co, v->co);
- cost = len_v3(d1);
- cost += len_v3(d2);
+ sub_v3_v3v3(d1, v2, v1);
+ sub_v3_v3v3(d2, v3, v2);
+ cost = len_v3(d1) + len_v3(d2);
/* but is biased to give higher values to sharp turns, so that it will take
* paths with fewer "turns" when selecting between equal-weighted paths between
@@ -1199,39 +1197,49 @@ static float edgetag_cut_cost(BMEditMesh *UNUSED(em), BMEdge *e1, BMEdge *e2, BM
return cost;
}
-static void edgetag_add_adjacent(BMEditMesh *em, SmallHash *visithash, Heap *heap, int mednum, int vertnum,
- int *nedges, int *edges, int *prevedge, float *cost)
-{
- BMEdge *e1 = EDBM_edge_at_index(em, mednum);
- BMVert *v = EDBM_vert_at_index(em, vertnum);
- int startadj, endadj = nedges[vertnum + 1];
-
- for (startadj = nedges[vertnum]; startadj < endadj; startadj++) {
- int adjnum = edges[startadj];
- BMEdge *e2 = EDBM_edge_at_index(em, adjnum);
- float newcost;
- float cutcost;
+/* ******************* edgetag_shortest_path and helpers ****************** */
- if (BLI_smallhash_haskey(visithash, (uintptr_t)e2))
- continue;
+static float edgetag_cut_cost(BMEdge *e1, BMEdge *e2, BMVert *v)
+{
+ BMVert *v1 = BM_edge_other_vert(e1, v);
+ BMVert *v2 = BM_edge_other_vert(e2, v);
+ return step_cost_3_v3(v1->co, v->co, v2->co);
+}
- cutcost = edgetag_cut_cost(em, e1, e2, v);
- newcost = cost[mednum] + cutcost;
+static void edgetag_add_adjacent(Heap *heap, BMEdge *e1, BMEdge **edges_prev, float *cost)
+{
+ BMIter viter;
+ BMVert *v;
- if (cost[adjnum] > newcost) {
- cost[adjnum] = newcost;
- prevedge[adjnum] = mednum;
- BLI_heap_insert(heap, newcost, SET_INT_IN_POINTER(adjnum));
+ BMIter eiter;
+ BMEdge *e2;
+
+ const int e1_index = BM_elem_index_get(e1);
+
+ BM_ITER_ELEM (v, &viter, e1, BM_VERTS_OF_EDGE) {
+ BM_ITER_ELEM (e2, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e2, BM_ELEM_TAG)) {
+ /* we know 'e2' is not visited, check it out! */
+ const int e2_index = BM_elem_index_get(e2);
+ const float cost_cut = edgetag_cut_cost(e1, e2, v);
+ const float cost_new = cost[e1_index] + cost_cut;
+
+ if (cost[e2_index] > cost_new) {
+ cost[e2_index] = cost_new;
+ edges_prev[e2_index] = e1;
+ BLI_heap_insert(heap, cost_new, e2);
+ }
+ }
}
}
}
-static void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *e, int val)
+static void edgetag_context_set(BMesh *bm, Scene *scene, BMEdge *e, int val)
{
switch (scene->toolsettings->edge_mode) {
case EDGE_MODE_SELECT:
- BM_edge_select_set(em->bm, e, val);
+ BM_edge_select_set(bm, e, val);
break;
case EDGE_MODE_TAG_SEAM:
BM_elem_flag_set(e, BM_ELEM_SEAM, val);
@@ -1243,25 +1251,19 @@ static void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *e, int val
BM_elem_flag_set(e, BM_ELEM_FREESTYLE, val);
break;
case EDGE_MODE_TAG_CREASE:
- {
- float *crease = CustomData_bmesh_get(&em->bm->edata, e->head.data, CD_CREASE);
- *crease = (val) ? 1.0f : 0.0f;
+ BM_elem_float_data_set(&bm->edata, e, CD_CREASE, (val) ? 1.0f : 0.0f);
break;
- }
case EDGE_MODE_TAG_BEVEL:
- {
- float *bweight = CustomData_bmesh_get(&em->bm->edata, e->head.data, CD_BWEIGHT);
- *bweight = (val) ? 1.0f : 0.0f;
+ BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (val) ? 1.0f : 0.0f);
break;
- }
}
}
-static int edgetag_context_check(Scene *scene, BMEditMesh *em, BMEdge *e)
+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) ? 1 : 0;
+ 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:
@@ -1269,74 +1271,48 @@ static int edgetag_context_check(Scene *scene, BMEditMesh *em, BMEdge *e)
case EDGE_MODE_TAG_FREESTYLE:
return !BM_elem_flag_test(e, BM_ELEM_FREESTYLE);
case EDGE_MODE_TAG_CREASE:
- return BM_elem_float_data_get(&em->bm->edata, e, CD_CREASE) ? 1 : 0;
+ return BM_elem_float_data_get(&bm->edata, e, CD_CREASE) ? TRUE : FALSE;
case EDGE_MODE_TAG_BEVEL:
- return BM_elem_float_data_get(&em->bm->edata, e, CD_BWEIGHT) ? 1 : 0;
+ return BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) ? TRUE : FALSE;
}
return 0;
}
-static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, BMEdge *target)
+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 */
BMEdge *e;
- BMIter iter;
+ BMIter eiter;
Heap *heap;
- SmallHash visithash;
float *cost;
- int i, totvert = 0, totedge = 0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0;
- int targetnum;
-
- BLI_smallhash_init(&visithash);
+ BMEdge **edges_prev;
+ int i, totedge;
/* note, would pass BM_EDGE except we are looping over all edges anyway */
- BM_mesh_elem_index_ensure(em->bm, BM_VERT /* | BM_EDGE */);
+ BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */);
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- BLI_smallhash_insert(&visithash, (uintptr_t)e, NULL);
+ BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == FALSE) {
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
}
- BM_elem_index_set(e, totedge); /* set_inline */
- totedge++;
+ BM_elem_index_set(e, i); /* set_inline */
}
- em->bm->elem_index_dirty &= ~BM_EDGE;
+ bm->elem_index_dirty &= ~BM_EDGE;
/* alloc */
- totvert = em->bm->totvert;
- nedges = MEM_callocN(sizeof(*nedges) * totvert + 1, "SeamPathNEdges");
- edges = MEM_mallocN(sizeof(*edges) * totedge * 2, "SeamPathEdges");
- prevedge = MEM_mallocN(sizeof(*prevedge) * totedge, "SeamPathPrevious");
+ totedge = bm->totedge;
+ edges_prev = MEM_callocN(sizeof(*edges_prev) * totedge, "SeamPathPrevious");
cost = MEM_mallocN(sizeof(*cost) * totedge, "SeamPathCost");
- /* count edges, compute adjacent edges offsets and fill adjacent */
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- nedges[BM_elem_index_get(e->v1) + 1]++;
- nedges[BM_elem_index_get(e->v2) + 1]++;
- }
-
- for (i = 1; i < totvert; i++) {
- int newswap = nedges[i + 1];
- nedges[i + 1] = nedgeswap + nedges[i];
- nedgeswap = newswap;
- }
- nedges[0] = nedges[1] = 0;
-
- i = 0;
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- edges[nedges[BM_elem_index_get(e->v1) + 1]++] = i;
- edges[nedges[BM_elem_index_get(e->v2) + 1]++] = i;
-
- cost[i] = 1e20f;
- prevedge[i] = -1;
- i++;
- }
+ fill_vn_fl(cost, totedge, 1e20f);
/*
* Arrays are now filled as follows:
*
- * nedges[n] = sum of the # of edges incident to all vertices numbered 0 through n - 1
- * edges[edges[n]..edges[n - 1]] = the indices of of the edges incident to vertex n
- *
* As the search continues, prevedge[n] will be the previous edge on the shortest
* path found so far to edge n. The visitedhash will of course contain entries
* for edges that have been visited, cost[n] will contain the length of the shortest
@@ -1347,61 +1323,46 @@ static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, B
/* regular dijkstra shortest path, but over edges instead of vertices */
heap = BLI_heap_new();
- BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(BM_elem_index_get(source)));
- cost[BM_elem_index_get(source)] = 0.0f;
- EDBM_index_arrays_init(em, 1, 1, 0);
- targetnum = BM_elem_index_get(target);
+ BLI_heap_insert(heap, 0.0f, e_src);
+ cost[BM_elem_index_get(e_src)] = 0.0f;
+
+ e = NULL;
while (!BLI_heap_is_empty(heap)) {
- mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap));
- e = EDBM_edge_at_index(em, mednum);
+ e = BLI_heap_popmin(heap);
- if (mednum == targetnum)
+ if (e == e_dst)
break;
- if (BLI_smallhash_haskey(&visithash, (uintptr_t)e))
- continue;
-
- BLI_smallhash_insert(&visithash, (uintptr_t)e, NULL);
-
- edgetag_add_adjacent(em, &visithash, heap, mednum, BM_elem_index_get(e->v1), nedges, edges, prevedge, cost);
- edgetag_add_adjacent(em, &visithash, heap, mednum, BM_elem_index_get(e->v2), nedges, edges, prevedge, cost);
+ if (!BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ edgetag_add_adjacent(heap, e, edges_prev, cost);
+ }
}
- if (mednum == targetnum) {
- short allseams = 1;
+ if (e == e_dst) {
+ short all_set = TRUE;
/* Check whether the path is already completely tagged.
* if it is, the tags will be cleared instead of set. */
- mednum = targetnum;
+ e = e_dst;
do {
- e = EDBM_edge_at_index(em, mednum);
- if (!edgetag_context_check(scene, em, e)) {
- allseams = 0;
+ if (!edgetag_context_check(scene, bm, e)) {
+ all_set = FALSE;
break;
}
- mednum = prevedge[mednum];
- } while (mednum != BM_elem_index_get(source));
+ } while ((e = edges_prev[BM_elem_index_get(e)]));
/* Follow path back and source and add or remove tags */
- mednum = targetnum;
+ e = e_dst;
do {
- e = EDBM_edge_at_index(em, mednum);
- if (allseams)
- edgetag_context_set(em, scene, e, 0);
- else
- edgetag_context_set(em, scene, e, 1);
- mednum = prevedge[mednum];
- } while (mednum != -1);
+ edgetag_context_set(bm, scene, e, !all_set);
+ } while ((e = edges_prev[BM_elem_index_get(e)]));
}
- EDBM_index_arrays_free(em);
- MEM_freeN(nedges);
- MEM_freeN(edges);
- MEM_freeN(prevedge);
+ MEM_freeN(edges_prev);
MEM_freeN(cost);
BLI_heap_free(heap, NULL);
- BLI_smallhash_release(&visithash);
return 1;
}
@@ -1409,21 +1370,15 @@ static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, B
/* ******************* 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(bContext *C, int mval[2])
+static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc)
{
- ViewContext vc;
- BMEditMesh *em;
- BMEdge *e;
+ BMEditMesh *em = vc->em;
+ BMEdge *e_dst;
float dist = 75.0f;
- em_setup_viewcontext(C, &vc);
- vc.mval[0] = mval[0];
- vc.mval[1] = mval[1];
- em = vc.em;
-
- e = EDBM_edge_find_nearest(&vc, &dist);
- if (e) {
- Mesh *me = vc.obedit->data;
+ e_dst = EDBM_edge_find_nearest(vc, &dist);
+ if (e_dst) {
+ Mesh *me = vc->obedit->data;
int path = 0;
if (em->bm->selected.last) {
@@ -1432,8 +1387,8 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2])
if (ese && ese->htype == BM_EDGE) {
BMEdge *e_act;
e_act = (BMEdge *)ese->ele;
- if (e_act != e) {
- if (edgetag_shortest_path(vc.scene, em, e_act, e)) {
+ 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;
}
@@ -1441,24 +1396,24 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2])
}
}
if (path == 0) {
- int act = (edgetag_context_check(vc.scene, em, e) == 0);
- edgetag_context_set(em, vc.scene, e, act); /* switch the edge option */
+ int act = (edgetag_context_check(vc->scene, em->bm, e_dst) == 0);
+ edgetag_context_set(em->bm, vc->scene, e_dst, act); /* switch the edge option */
}
EDBM_selectmode_flush(em);
/* even if this is selected it may not be in the selection list */
- if (edgetag_context_check(vc.scene, em, e) == 0)
- BM_select_history_remove(em->bm, e);
+ if (edgetag_context_check(vc->scene, em->bm, e_dst) == 0)
+ BM_select_history_remove(em->bm, e_dst);
else
- BM_select_history_store(em->bm, e);
+ BM_select_history_store(em->bm, e_dst);
/* force drawmode for mesh */
switch (CTX_data_tool_settings(C)->edge_mode) {
case EDGE_MODE_TAG_SEAM:
me->drawflag |= ME_DRAWSEAMS;
- ED_uvedit_live_unwrap(vc.scene, vc.obedit);
+ ED_uvedit_live_unwrap(vc->scene, vc->obedit);
break;
case EDGE_MODE_TAG_SHARP:
me->drawflag |= ME_DRAWSHARP;
@@ -1484,17 +1439,229 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2])
}
+/* ******************* facetag_shortest_path and helpers ****************** */
+
+
+static float facetag_cut_cost(BMFace *f1, BMFace *f2, BMEdge *e)
+{
+ float f1_cent[3];
+ float f2_cent[3];
+ float e_cent[3];
+
+ BM_face_calc_center_mean(f1, f1_cent);
+ BM_face_calc_center_mean(f2, f2_cent);
+ mid_v3_v3v3(e_cent, e->v1->co, e->v2->co);
+
+ return step_cost_3_v3(f1_cent, e_cent, f2_cent);
+}
+
+static void facetag_add_adjacent(Heap *heap, BMFace *f1, BMFace **faces_prev, float *cost)
+{
+ BMIter liter;
+ BMLoop *l2;
+ BMFace *f2;
+
+ const int f1_index = BM_elem_index_get(f1);
+
+ /* loop over faces of face, but do so by first looping over loops */
+ BM_ITER_ELEM (l2, &liter, f1, BM_LOOPS_OF_FACE) {
+ BMLoop *l_first;
+ BMLoop *l_iter;
+
+ l_iter = l_first = l2;
+ do {
+ f2 = l_iter->f;
+ if (!BM_elem_flag_test(f2, BM_ELEM_TAG)) {
+ /* we know 'f2' is not visited, check it out! */
+ const int f2_index = BM_elem_index_get(f2);
+ const float cost_cut = facetag_cut_cost(f1, f2, l_iter->e);
+ const float cost_new = cost[f1_index] + cost_cut;
+
+ if (cost[f2_index] > cost_new) {
+ cost[f2_index] = cost_new;
+ faces_prev[f2_index] = f1;
+ BLI_heap_insert(heap, cost_new, f2);
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+}
+
+static void facetag_context_set(BMesh *bm, Scene *UNUSED(scene), BMFace *f, int val)
+{
+ BM_face_select_set(bm, f, val);
+}
+
+static int facetag_context_check(Scene *UNUSED(scene), BMesh *UNUSED(bm), BMFace *f)
+{
+ return BM_elem_flag_test(f, BM_ELEM_SELECT) ? 1 : 0;
+}
+
+static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace *f_dst)
+{
+ /* BM_ELEM_TAG flag is used to store visited edges */
+ BMFace *f;
+ BMIter fiter;
+ Heap *heap;
+ float *cost;
+ BMFace **faces_prev;
+ int i, totface;
+
+ /* note, would pass BM_EDGE except we are looping over all faces anyway */
+ // 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) {
+ BM_elem_flag_disable(f, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ }
+
+ BM_elem_index_set(f, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_FACE;
+
+ /* alloc */
+ totface = bm->totface;
+ faces_prev = MEM_callocN(sizeof(*faces_prev) * totface, "SeamPathPrevious");
+ cost = MEM_mallocN(sizeof(*cost) * totface, "SeamPathCost");
+
+ fill_vn_fl(cost, totface, 1e20f);
+
+ /*
+ * Arrays are now filled as follows:
+ *
+ * As the search continues, faces_prev[n] will be the previous face on the shortest
+ * path found so far to face n. The visitedhash will of course contain entries
+ * for faces that have been visited, cost[n] will contain the length of the shortest
+ * path to face n found so far, Finally, heap is a priority heap which is built on the
+ * the same data as the cost array, but inverted: it is a worklist of faces prioritized
+ * by the shortest path found so far to the face.
+ */
+
+ /* regular dijkstra shortest path, but over faces instead of vertices */
+ heap = BLI_heap_new();
+ BLI_heap_insert(heap, 0.0f, f_src);
+ cost[BM_elem_index_get(f_src)] = 0.0f;
+
+ f = NULL;
+
+ while (!BLI_heap_is_empty(heap)) {
+ f = BLI_heap_popmin(heap);
+
+ if (f == f_dst)
+ break;
+
+ if (!BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ facetag_add_adjacent(heap, f, faces_prev, cost);
+ }
+ }
+
+ if (f == f_dst) {
+ short 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;
+ break;
+ }
+ } while ((f = faces_prev[BM_elem_index_get(f)]));
+
+ /* Follow path back and source and add or remove tags */
+ f = f_dst;
+ do {
+ facetag_context_set(bm, scene, f, !all_set);
+ } while ((f = faces_prev[BM_elem_index_get(f)]));
+ }
+
+ MEM_freeN(faces_prev);
+ MEM_freeN(cost);
+ BLI_heap_free(heap, NULL);
+
+ return 1;
+}
+
+static int mouse_mesh_shortest_path_face(bContext *C, ViewContext *vc)
+{
+ BMEditMesh *em = vc->em;
+ BMFace *f_dst;
+ float dist = 75.0f;
+
+ 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);
+
+ if (f_act) {
+ if (f_act != f_dst) {
+ if (facetag_shortest_path(vc->scene, em->bm, f_act, f_dst)) {
+ BM_select_history_remove(em->bm, f_act);
+ path = 1;
+ }
+ }
+ }
+ if (path == 0) {
+ int act = (facetag_context_check(vc->scene, em->bm, f_dst) == 0);
+ facetag_context_set(em->bm, vc->scene, f_dst, act); /* switch the face option */
+ }
+
+ EDBM_selectmode_flush(em);
+
+ /* even if this is selected it may not be in the selection list */
+ if (facetag_context_check(vc->scene, em->bm, f_dst) == 0)
+ BM_select_history_remove(em->bm, f_dst);
+ else
+ BM_select_history_store(em->bm, f_dst);
+
+ BM_active_face_set(em->bm, f_dst);
+
+ EDBM_update_generic(C, em, FALSE);
+
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+
+/* ******************* operator for edge and face tag ****************** */
+
static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
{
-
+ ViewContext vc;
+ BMEditMesh *em;
+
view3d_operator_needs_opengl(C);
- if (mouse_mesh_shortest_path(C, event->mval)) {
- return OPERATOR_FINISHED;
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0] = event->mval[0];
+ vc.mval[1] = event->mval[1];
+ em = vc.em;
+
+ if (em->selectmode & SCE_SELECT_EDGE) {
+ if (mouse_mesh_shortest_path_edge(C, &vc)) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
}
- else {
- return OPERATOR_PASS_THROUGH;
+ else if (em->selectmode & SCE_SELECT_FACE) {
+ if (mouse_mesh_shortest_path_face(C, &vc)) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
}
+
+ return OPERATOR_PASS_THROUGH;
}
static int edbm_shortest_path_select_poll(bContext *C)
@@ -1502,7 +1669,7 @@ static int edbm_shortest_path_select_poll(bContext *C)
if (ED_operator_editmesh_region_view3d(C)) {
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- return (em->selectmode & SCE_SELECT_EDGE) != 0;
+ return (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE)) != 0;
}
return 0;
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index df22cbcb294..82eb9457147 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -1736,12 +1736,12 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- 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,
- "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_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,
+ "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");
@@ -4602,11 +4602,15 @@ 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 */
@@ -4619,13 +4623,25 @@ 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
char msg[HEADER_LENGTH];
ScrArea *sa = CTX_wm_area(C);
- BevelData *opdata = op->customdata;
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);
@@ -4636,11 +4652,13 @@ static void edbm_bevel_update_header(wmOperator *op, bContext *C)
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;
@@ -4668,15 +4686,20 @@ static void edbm_bevel_recalc_weights(wmOperator *op)
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;
@@ -4684,6 +4707,7 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal)
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;
@@ -4693,10 +4717,12 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal)
*dv = d;
}
-
- opdata->em = em;
+
opdata->li = li;
opdata->weights = NULL;
+#endif
+
+ opdata->em = em;
opdata->is_modal = is_modal;
opdata->shift_factor = -1.0f;
@@ -4706,7 +4732,9 @@ 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;
}
@@ -4716,6 +4744,26 @@ static int edbm_bevel_calc(bContext *C, 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");
+
+ /* revert to original mesh */
+ if (opdata->is_modal) {
+ 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))
+ {
+ return 0;
+ }
+
+ BMO_op_exec(em->bm, &bmop);
+ if (!EDBM_op_finish(em, &bmop, op, TRUE))
+ return 0;
+#else
int i;
float factor = RNA_float_get(op->ptr, "percent") /*, dfac */ /* UNUSED */;
@@ -4743,6 +4791,7 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op)
if (!EDBM_op_finish(em, &bmop, op, TRUE))
return 0;
}
+#endif
EDBM_mesh_normals_update(opdata->em);
@@ -4760,10 +4809,12 @@ 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);
}
@@ -4844,7 +4895,11 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event)
static float edbm_bevel_mval_factor(wmOperator *op, 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
float mdiff[2];
float factor;
@@ -4882,9 +4937,21 @@ static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event)
static int edbm_bevel_modal(bContext *C, wmOperator *op, 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
+ float value;
+
+ if (handleNumInput(&opdata->num_input, event)) {
+ 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
float factor;
if (handleNumInput(&opdata->num_input, event)) {
@@ -4896,6 +4963,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
edbm_bevel_update_header(op, C);
return OPERATOR_RUNNING_MODAL;
}
+#endif
}
switch (event->type) {
@@ -4907,7 +4975,11 @@ 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_update_header(op, C);
@@ -4921,6 +4993,28 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
edbm_bevel_exit(C, op);
return OPERATOR_FINISHED;
+#ifdef NEW_BEVEL
+ case WHEELUPMOUSE: /* change number of segments */
+ if (event->val == KM_RELEASE)
+ break;
+
+ segments++;
+ RNA_int_set(op->ptr, "segments", segments);
+ edbm_bevel_calc(C, op);
+ edbm_bevel_update_header(op, C);
+ break;
+
+ case WHEELDOWNMOUSE: /* change number of segments */
+ if (event->val == KM_RELEASE)
+ break;
+
+ segments = max_ii(segments - 1, 1);
+ RNA_int_set(op->ptr, "segments", segments);
+ edbm_bevel_calc(C, 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");
@@ -4945,6 +5039,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
edbm_bevel_update_header(op, C);
}
break;
+#endif
}
return OPERATOR_RUNNING_MODAL;
@@ -4967,6 +5062,10 @@ 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. */
@@ -4974,6 +5073,7 @@ void MESH_OT_bevel(wmOperatorType *ot)
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
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 9fc4e0a906d..4d1f2bbc4e9 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1136,7 +1136,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (dupli_gh)
BLI_ghash_insert(dupli_gh, dob, ob);
if (parent_gh)
- BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->index)), ob);
+ BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->persistent_id[0])), ob);
}
if (use_hierarchy) {
@@ -1150,7 +1150,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
/* find parent that was also made real */
if (ob_src_par) {
- GHashPair *pair = BLI_ghashutil_pairalloc(ob_src_par, SET_INT_IN_POINTER(dob->index));
+ GHashPair *pair = BLI_ghashutil_pairalloc(ob_src_par, SET_INT_IN_POINTER(dob->persistent_id[0]));
ob_dst_par = BLI_ghash_lookup(parent_gh, pair);
BLI_ghashutil_pairfree(pair);
}
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index 0a2ca379518..5155f1001ab 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -58,6 +58,7 @@
#include "GPU_material.h"
#include "RE_engine.h"
+#include "RE_pipeline.h"
#include "ED_node.h"
#include "ED_render.h"
@@ -157,6 +158,8 @@ void ED_render_engine_changed(Main *bmain)
for (sc = bmain->screen.first; sc; sc = sc->id.next)
for (sa = sc->areabase.first; sa; sa = sa->next)
ED_render_engine_area_exit(sa);
+
+ RE_FreePersistentData();
}
/***************************** Updates ***********************************
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index 0ecac5fc497..ca85daadf3b 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -35,6 +35,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_math.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -52,6 +53,7 @@
#include "BKE_writeavi.h"
#include "BIF_gl.h"
+#include "BIF_glutil.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -278,6 +280,7 @@ void SCREEN_OT_screenshot(wmOperatorType *ot)
typedef struct ScreenshotJob {
Main *bmain;
Scene *scene;
+ wmWindowManager *wm;
unsigned int *dumprect;
int x, y, dumpsx, dumpsy;
short *stop;
@@ -395,6 +398,54 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
BKE_report(&sj->reports, RPT_INFO, "Screencast job stopped");
}
+/* Helper callback for drawing the cursor itself */
+static void screencast_draw_cursor(bContext *UNUSED(C), int x, int y, void *UNUSED(p_ptr))
+{
+
+ glPushMatrix();
+
+ glTranslatef((float)x, (float)y, 0.0f);
+
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ glColor4ub(0, 0, 0, 32);
+ glutil_draw_filled_arc(0.0, M_PI * 2.0, 20, 40);
+
+ glColor4ub(255, 255, 255, 128);
+ glutil_draw_lined_arc(0.0, M_PI * 2.0, 20, 40);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+
+ glPopMatrix();
+}
+
+/* Turn brush cursor in 3D view on/off */
+static void screencast_cursor_toggle(wmWindowManager *wm, short enable)
+{
+ static void *cursor = NULL;
+
+ if (cursor && !enable) {
+ /* clear cursor */
+ WM_paint_cursor_end(wm, cursor);
+ cursor = NULL;
+ }
+ else if (enable) {
+ /* enable cursor */
+ cursor = WM_paint_cursor_activate(wm, NULL, screencast_draw_cursor, NULL);
+ }
+}
+
+static void screenshot_endjob(void *sjv)
+{
+ ScreenshotJob *sj = sjv;
+
+ screencast_cursor_toggle(sj->wm, 0);
+}
+
+
static int screencast_exec(bContext *C, wmOperator *op)
{
bScreen *screen = CTX_wm_screen(C);
@@ -418,15 +469,18 @@ 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);
+
BKE_reports_init(&sj->reports, RPT_PRINT);
/* setup job */
WM_jobs_customdata_set(wm_job, sj, screenshot_freejob);
WM_jobs_timer(wm_job, 0.1, 0, NC_SCREEN | ND_SCREENCAST);
- WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, NULL);
+ WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, screenshot_endjob);
+
+ WM_jobs_start(sj->wm, wm_job);
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ screencast_cursor_toggle(sj->wm, 1);
WM_event_add_notifier(C, NC_SCREEN | ND_SCREENCAST, screen);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index bd6852c4344..4b400623920 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -109,19 +109,25 @@
#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] = FTOCHAR((f)[0]); \
- (c)[1] = FTOCHAR((f)[1]); \
- (c)[2] = FTOCHAR((f)[2]); \
+ (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] = FTOCHAR((f)[0]); \
- (c)[1] = FTOCHAR((f)[1]); \
- (c)[2] = FTOCHAR((f)[2]); \
- (c)[3] = FTOCHAR((f)[3]); \
+ (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]); \
@@ -3905,16 +3911,20 @@ static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, flo
}
}
+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[3]);
+ 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_ub[0] = FTOCHAR(rgba[0] * ps->brush->rgb[0]);
- rgba_ub[1] = FTOCHAR(rgba[1] * ps->brush->rgb[1]);
- rgba_ub[2] = FTOCHAR(rgba[2] * ps->brush->rgb[2]);
- rgba_ub[3] = FTOCHAR(rgba[3]);
+ rgba_float_to_uchar__mul_v3(rgba_ub, rgba, ps->brush->rgb);
}
else {
IMAPAINT_FLOAT_RGB_TO_CHAR(rgba_ub, ps->brush->rgb);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 6396a0c2cbc..9ebeb61a7bb 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -195,7 +195,7 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev
/* 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)
{
output[0] = sample->mouse[0];
output[1] = sample->mouse[1];
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 56d46a22e10..94b00101dc2 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -125,9 +125,11 @@ static void update_tessface_data(Object *ob, Mesh *me)
if (!me->mcol || !me->mface) {
/* should always be true */
/* XXX Why this clearing? tessface_calc will reset it anyway! */
-/* if (me->mcol) {*/
-/* memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface);*/
-/* }*/
+#if 0
+ if (me->mcol) {
+ memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface);
+ }
+#endif
/* create tessfaces because they will be used for drawing & fast updates */
BKE_mesh_tessface_calc(me); /* does own call to update pointers */
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 24e9effa9eb..a7f18c9de53 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -681,9 +681,9 @@ void buttons_context_compute(const bContext *C, SpaceButs *sbuts)
/************************* Context Callback ************************/
const char *buttons_context_dir[] = {
- "world", "object", "mesh", "armature", "lattice", "curve",
+ "texture_slot", "world", "object", "mesh", "armature", "lattice", "curve",
"meta_ball", "lamp", "speaker", "camera", "material", "material_slot",
- "texture", "texture_slot", "texture_user", "bone", "edit_bone",
+ "texture", "texture_user", "bone", "edit_bone",
"pose_bone", "particle_system", "particle_system_editable", "particle_settings",
"cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint", NULL
};
@@ -698,7 +698,12 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
/* here we handle context, getting data from precomputed path */
if (CTX_data_dir(member)) {
- CTX_data_dir_set(result, buttons_context_dir);
+ /* in case of new shading system we skip texture_slot, complex python
+ * UI script logic depends on checking if this is available */
+ if (sbuts->texuser)
+ CTX_data_dir_set(result, buttons_context_dir + 1);
+ else
+ CTX_data_dir_set(result, buttons_context_dir);
return 1;
}
else if (CTX_data_equals(member, "world")) {
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index a2e4da719e9..02716c20588 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -252,7 +252,6 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
int width, int height, float zoomx, float zoomy)
{
int x, y;
- MovieClip *clip = ED_space_clip_get_clip(sc);
/* find window pixel coordinates of origin */
UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
@@ -306,6 +305,15 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
IMB_display_buffer_release(cache_handle);
}
+}
+
+static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy)
+{
+ int x, y;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ /* find window pixel coordinates of origin */
+ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
/* draw boundary border for frame if stabilization is enabled */
if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
@@ -1469,6 +1477,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
}
if (width && height) {
+ draw_stabilization_border(sc, ar, width, height, zoomx, zoomy);
draw_tracking_tracks(sc, ar, clip, width, height, zoomx, zoomy);
draw_distortion(sc, ar, clip, width, height, zoomx, zoomy);
}
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 9ec2ad82bef..4e53f34359e 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -1065,7 +1065,7 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
if (clip->anim) {
pj->index_context = IMB_anim_index_rebuild_context(clip->anim, clip->proxy.build_tc_flag,
- clip->proxy.build_size_flag, clip->proxy.quality);
+ clip->proxy.build_size_flag, clip->proxy.quality);
}
WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index ddc624b4cdf..d7a9b1c0cb6 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -63,11 +63,12 @@
#include "clip_intern.h" // own include
-void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack *track, void *userdata,
- void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord,
- int scene_framenr, float val),
- void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord),
- void (*segment_end)(void *userdata))
+void clip_graph_tracking_values_iterate_track(
+ SpaceClip *sc, MovieTrackingTrack *track, void *userdata,
+ void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord,
+ int scene_framenr, float val),
+ void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord),
+ void (*segment_end)(void *userdata))
{
MovieClip *clip = ED_space_clip_get_clip(sc);
int width, height, coord;
@@ -122,11 +123,12 @@ void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack
}
}
-void clip_graph_tracking_values_iterate(SpaceClip *sc, int selected_only, int include_hidden, void *userdata,
- void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int coord, int scene_framenr, float val),
- void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord),
- void (*segment_end)(void *userdata))
+void clip_graph_tracking_values_iterate(
+ SpaceClip *sc, int selected_only, int include_hidden, void *userdata,
+ void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker,
+ int coord, int scene_framenr, float val),
+ void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord),
+ void (*segment_end)(void *userdata))
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index f41169b6c39..fa7c6bd472a 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -563,13 +563,13 @@ static void graph_refresh(const bContext *C, ScrArea *sa)
switch (fcu->array_index) {
case 0:
- col[0] = 1.0f; col[1] = 0.0f; col[2] = 0.0f;
+ UI_GetThemeColor3fv(TH_AXIS_X, col);
break;
case 1:
- col[0] = 0.0f; col[1] = 1.0f; col[2] = 0.0f;
+ UI_GetThemeColor3fv(TH_AXIS_Y, col);
break;
case 2:
- col[0] = 0.0f; col[1] = 0.0f; col[2] = 1.0f;
+ UI_GetThemeColor3fv(TH_AXIS_Z, col);
break;
default:
/* 'unknown' color - bluish so as to not conflict with handles */
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index aafd4abb25e..8d44da2e367 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -319,7 +319,7 @@ static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr
RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
col = uiLayoutColumn(layout, FALSE);
- uiTemplateColorWheel(col, &sockptr, "default_value", 1, 0, 0, 0);
+ uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0);
uiItemR(col, &sockptr, "default_value", 0, "", ICON_NONE);
}
@@ -2258,17 +2258,17 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C
split = uiLayoutSplit(layout, 0.0f, FALSE);
col = uiLayoutColumn(split, FALSE);
- uiTemplateColorWheel(col, ptr, "lift", 1, 1, 0, 1);
+ uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1);
row = uiLayoutRow(col, FALSE);
uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE);
col = uiLayoutColumn(split, FALSE);
- uiTemplateColorWheel(col, ptr, "gamma", 1, 1, 1, 1);
+ uiTemplateColorPicker(col, ptr, "gamma", 1, 1, 1, 1);
row = uiLayoutRow(col, FALSE);
uiItemR(row, ptr, "gamma", 0, NULL, ICON_NONE);
col = uiLayoutColumn(split, FALSE);
- uiTemplateColorWheel(col, ptr, "gain", 1, 1, 1, 1);
+ uiTemplateColorPicker(col, ptr, "gain", 1, 1, 1, 1);
row = uiLayoutRow(col, FALSE);
uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE);
@@ -2277,17 +2277,17 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C
split = uiLayoutSplit(layout, 0.0f, FALSE);
col = uiLayoutColumn(split, FALSE);
- uiTemplateColorWheel(col, ptr, "offset", 1, 1, 0, 1);
+ uiTemplateColorPicker(col, ptr, "offset", 1, 1, 0, 1);
row = uiLayoutRow(col, FALSE);
uiItemR(row, ptr, "offset", 0, NULL, ICON_NONE);
col = uiLayoutColumn(split, FALSE);
- uiTemplateColorWheel(col, ptr, "power", 1, 1, 0, 1);
+ uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1);
row = uiLayoutRow(col, FALSE);
uiItemR(row, ptr, "power", 0, NULL, ICON_NONE);
col = uiLayoutColumn(split, FALSE);
- uiTemplateColorWheel(col, ptr, "slope", 1, 1, 0, 1);
+ uiTemplateColorPicker(col, ptr, "slope", 1, 1, 0, 1);
row = uiLayoutRow(col, FALSE);
uiItemR(row, ptr, "slope", 0, NULL, ICON_NONE);
}
@@ -2299,23 +2299,23 @@ static void node_composit_buts_colorbalance_but(uiLayout *layout, bContext *UNUS
if (RNA_enum_get(ptr, "correction_method") == 0) {
- uiTemplateColorWheel(layout, ptr, "lift", 1, 1, 0, 1);
+ uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1);
uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE);
- uiTemplateColorWheel(layout, ptr, "gamma", 1, 1, 1, 1);
+ uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1);
uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE);
- uiTemplateColorWheel(layout, ptr, "gain", 1, 1, 1, 1);
+ uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1);
uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE);
}
else {
- uiTemplateColorWheel(layout, ptr, "offset", 1, 1, 0, 1);
+ uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1);
uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE);
- uiTemplateColorWheel(layout, ptr, "power", 1, 1, 0, 1);
+ uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1);
uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE);
- uiTemplateColorWheel(layout, ptr, "slope", 1, 1, 0, 1);
+ uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1);
uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE);
}
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 5dd005e9ddf..62e941d3148 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -2226,7 +2226,7 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op)
data.text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
if (data.text) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
+ bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
if (ntreetype && ntreetype->foreach_nodetree)
ntreetype->foreach_nodetree(bmain, &data, node_shader_script_update_text);
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index c4afe32e85f..2c40e0e656d 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1042,7 +1042,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
/* Default */
case eModifierType_None:
case eModifierType_ShapeKey:
- case NUM_MODIFIER_TYPES:
+ case NUM_MODIFIER_TYPES:
UI_icon_draw(x, y, ICON_DOT); break;
}
break;
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index a8103fe2630..37e57a1e850 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -913,6 +913,13 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
unsigned char *display_buffer;
void *cache_handle = NULL;
+ if (G.is_rendering == FALSE) {
+ /* 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_all_except(CTX_wm_manager(C), CTX_wm_screen(C));
+ }
+
render_size = sseq->render_size;
if (render_size == 0) {
render_size = scene->r.size;
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 94f64563fd8..f463b015bf5 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -95,7 +95,7 @@ static int text_font_draw_character(SpaceText *st, int x, int y, char c)
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(c);
+ size_t len = BLI_str_utf8_size_safe(c);
memcpy(str, c, len);
str[len] = '\0';
@@ -158,7 +158,7 @@ int flatten_string(SpaceText *st, FlattenString *fs, const char *in)
in++;
}
else {
- size_t len = BLI_str_utf8_size(in);
+ size_t len = BLI_str_utf8_size_safe(in);
flatten_string_append(fs, in, r, len);
in += len;
total++;
@@ -342,7 +342,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
if (*str == '\\') {
*fmt = prev; fmt++; str++;
if (*str == '\0') break;
- *fmt = prev; fmt++; str += BLI_str_utf8_size(str);
+ *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
continue;
}
/* Handle continuations */
@@ -363,14 +363,14 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
}
*fmt = 'l';
- str += BLI_str_utf8_size(str) - 1;
+ 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(str) - 1;
+ str += BLI_str_utf8_size_safe(str) - 1;
}
else if (*str == '"' || *str == '\'') {
/* Strings */
@@ -399,7 +399,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
*fmt = 'n';
}
else {
- str += BLI_str_utf8_size(str) - 1;
+ str += BLI_str_utf8_size_safe(str) - 1;
*fmt = 'q';
}
/* Punctuation */
@@ -407,7 +407,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
*fmt = '!';
/* Identifiers and other text (no previous ws. or delims. so text continues) */
else if (prev == 'q') {
- str += BLI_str_utf8_size(str) - 1;
+ 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 */
@@ -427,7 +427,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
*fmt = prev;
}
else {
- str += BLI_str_utf8_size(str) - 1;
+ str += BLI_str_utf8_size_safe(str) - 1;
*fmt = 'q';
}
}
@@ -575,7 +575,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *
end = max;
chop = 1;
*offc = 0;
- for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size(linep->line + j)) {
+ for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size_safe(linep->line + j)) {
int chars;
/* Mimic replacement of tabs */
@@ -640,7 +640,7 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi
*offc = 0;
cursin = txt_utf8_offset_to_index(linein->line, cursin);
- for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size(linein->line + j)) {
+ for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) {
/* Mimic replacement of tabs */
ch = linein->line[j];
@@ -685,7 +685,7 @@ int text_get_char_pos(SpaceText *st, const char *line, int cur)
{
int a = 0, i;
- for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size(line + i)) {
+ for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size_safe(line + i)) {
if (line[i] == '\t')
a += st->tabnumber - a % st->tabnumber;
else
@@ -698,7 +698,7 @@ static const char *txt_utf8_get_nth(const char *str, int n)
{
int pos = 0;
while (str[pos] && n--) {
- pos += BLI_str_utf8_size(str + pos);
+ pos += BLI_str_utf8_size_safe(str + pos);
}
return str + pos;
}
@@ -719,7 +719,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
start = 0; mstart = 0;
end = max; mend = txt_utf8_get_nth(str, max) - str;
- for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size(str + mi)) {
+ for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size_safe(str + mi)) {
if (i - start >= max) {
/* skip hidden part of line */
if (skip) {
@@ -730,7 +730,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
}
/* Draw the visible portion of text on the overshot line */
- for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size(str + ma)) {
+ 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]);
x += text_font_draw_character_utf8(st, x, y, str + ma);
}
@@ -748,7 +748,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
}
/* Draw the remaining text */
- for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size(str + ma)) {
+ 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]);
@@ -786,7 +786,7 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra
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(in + str_shift);
+ str_shift += BLI_str_utf8_size_safe(in + str_shift);
}
}
else text_font_draw(st, x, y, in);
@@ -1016,7 +1016,7 @@ int text_get_visible_lines(SpaceText *st, ARegion *ar, const char *str)
lines = 1;
start = 0;
end = max;
- for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size(str + j)) {
+ for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size_safe(str + j)) {
/* Mimic replacement of tabs */
ch = str[j];
if (ch == '\t') {
@@ -1639,7 +1639,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
if (b > 0) {
/* opening bracket, search forward for close */
fc++;
- c += BLI_str_utf8_size(linep->line + c);
+ 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] != '#') {
@@ -1657,7 +1657,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
}
}
fc++;
- c += BLI_str_utf8_size(linep->line + c);
+ c += BLI_str_utf8_size_safe(linep->line + c);
}
if (endl) break;
linep = linep->next;
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 2d902c4586a..1be50a54b68 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -1503,7 +1503,7 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int
end = max;
chop = loop = 1;
- for (i = 0, j = 0; loop; j += BLI_str_utf8_size(linein->line + j)) {
+ for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe(linein->line + j)) {
int chars;
/* Mimic replacement of tabs */
ch = linein->line[j];
@@ -1682,7 +1682,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel)
chop = loop = 1;
*charp = 0;
- for (i = 0, j = 0; loop; j += BLI_str_utf8_size((*linep)->line + j)) {
+ for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) {
int chars;
/* Mimic replacement of tabs */
ch = (*linep)->line[j];
@@ -1750,7 +1750,7 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel)
chop = loop = 1;
*charp = 0;
- for (i = 0, j = 0; loop; j += BLI_str_utf8_size((*linep)->line + j)) {
+ for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) {
int chars;
/* Mimic replacement of tabs */
ch = (*linep)->line[j];
@@ -2462,7 +2462,7 @@ static int flatten_len(SpaceText *st, const char *str)
{
int i, total = 0;
- for (i = 0; str[i]; i += BLI_str_utf8_size(str + i)) {
+ for (i = 0; str[i]; i += BLI_str_utf8_size_safe(str + i)) {
if (str[i] == '\t') {
total += st->tabnumber - total % st->tabnumber;
}
@@ -2475,7 +2475,7 @@ static int flatten_len(SpaceText *st, const char *str)
static int flatten_index_to_offset(SpaceText *st, const char *str, int index)
{
int i, j;
- for (i = 0, j = 0; i < index; j += BLI_str_utf8_size(str + j))
+ for (i = 0, j = 0; i < index; j += BLI_str_utf8_size_safe(str + j))
if (str[j] == '\t')
i += st->tabnumber - i % st->tabnumber;
else
@@ -2519,7 +2519,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
int j = 0, curs = 0, endj = 0; /* mem */
int chop = 1; /* flags */
- for (; loop; j += BLI_str_utf8_size(linep->line + j)) {
+ for (; loop; j += BLI_str_utf8_size_safe(linep->line + j)) {
int chars;
/* Mimic replacement of tabs */
@@ -2945,7 +2945,7 @@ static int text_insert_invoke(bContext *C, wmOperator *op, wmEvent *event)
size_t len;
if (event->utf8_buf[0]) {
- len = BLI_str_utf8_size(event->utf8_buf);
+ len = BLI_str_utf8_size_safe(event->utf8_buf);
memcpy(str, event->utf8_buf, len);
}
else {
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 6818c78bbd6..3413377c7b9 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -945,7 +945,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
ED_region_tag_redraw(ar);
break;
case NC_GPENCIL:
- if (wmn->data == ND_DATA)
+ if (wmn->data == ND_DATA || wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
break;
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 4d4fad47698..24fc6adae6d 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -545,12 +545,8 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
}
}
}
-
-
-
-
- if (v3d->zbuf && scene->obedit) glDepthMask(1);
+ if (v3d->zbuf && scene->obedit) glDepthMask(1);
}
static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
@@ -600,8 +596,8 @@ static void draw_view_axis(RegionView3D *rv3d)
mul_qt_v3(rv3d->viewquat, vec);
dx = vec[0] * k;
dy = vec[1] * k;
-
- glColor4ub(220, 0, 0, bright);
+
+ UI_ThemeColorShadeAlpha(TH_AXIS_X, 0, bright);
glBegin(GL_LINES);
glVertex2f(start, start + ydisp);
glVertex2f(start + dx, start + dy + ydisp);
@@ -620,8 +616,8 @@ static void draw_view_axis(RegionView3D *rv3d)
mul_qt_v3(rv3d->viewquat, vec);
dx = vec[0] * k;
dy = vec[1] * k;
-
- glColor4ub(0, 220, 0, bright);
+
+ UI_ThemeColorShadeAlpha(TH_AXIS_Y, 0, bright);
glBegin(GL_LINES);
glVertex2f(start, start + ydisp);
glVertex2f(start + dx, start + dy + ydisp);
@@ -640,7 +636,7 @@ static void draw_view_axis(RegionView3D *rv3d)
dx = vec[0] * k;
dy = vec[1] * k;
- glColor4ub(30, 30, 220, bright);
+ UI_ThemeColorShadeAlpha(TH_AXIS_Z, 0, bright);
glBegin(GL_LINES);
glVertex2f(start, start + ydisp);
glVertex2f(start + dx, start + dy + ydisp);
@@ -1218,7 +1214,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
hmargin = 0.1f * (x2 - x1);
vmargin = 0.05f * (y2 - y1);
- uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1+vmargin, x2 - hmargin, y2 - vmargin, 2.0f);
+ uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f);
hmargin = 0.035f * (x2 - x1);
vmargin = 0.035f * (y2 - y1);
@@ -2989,10 +2985,10 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const
v3d->zbuf = FALSE;
/* enables anti-aliasing for 3D view drawing */
-#if 0
- if (!(U.gameflags & USER_DISABLE_AA))
- glEnable(GL_MULTISAMPLE_ARB);
-#endif
+ if (U.ogl_multisamples)
+ if (!(U.gameflags & USER_DISABLE_AA))
+ glEnable(GL_MULTISAMPLE_ARB);
+
/* needs to be done always, gridview is adjusted in drawgrid() now */
rv3d->gridview = v3d->grid;
@@ -3105,12 +3101,12 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const
BIF_draw_manipulator(C);
-#if 0
/* Disable back anti-aliasing */
- if (!(U.gameflags & USER_DISABLE_AA))
- glDisable(GL_MULTISAMPLE_ARB);
-#endif
+ if (U.ogl_multisamples)
+ if (!(U.gameflags & USER_DISABLE_AA))
+ glDisable(GL_MULTISAMPLE_ARB);
+
if (v3d->zbuf) {
v3d->zbuf = FALSE;
glDisable(GL_DEPTH_TEST);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 43626b058d6..53f983912ac 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1064,11 +1064,11 @@ 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 extend = RNA_boolean_get(op->ptr, "extend");
+ short toggle = RNA_boolean_get(op->ptr, "toggle");
short changed = 0;
const char *name = object_mouse_select_menu_data[name_index].idname;
- if (!extend) {
+ if (!toggle) {
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if (base->flag & SELECT) {
@@ -1125,7 +1125,7 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN);
ot->prop = prop;
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
+ RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first");
}
static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */
@@ -1141,7 +1141,7 @@ 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 extend)
+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;
@@ -1207,7 +1207,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
PointerRNA ptr;
WM_operator_properties_create(&ptr, "VIEW3D_OT_select_menu");
- RNA_boolean_set(&ptr, "extend", extend);
+ RNA_boolean_set(&ptr, "toggle", toggle);
WM_operator_name_call(C, "VIEW3D_OT_select_menu", WM_OP_INVOKE_DEFAULT, &ptr);
WM_operator_properties_free(&ptr);
}
@@ -1440,7 +1440,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
/* note; shift+alt goes to group-flush-selecting */
if (enumerate) {
- basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, extend);
+ basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle);
}
else {
base = startbase;
@@ -1480,7 +1480,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
/* note; shift+alt goes to group-flush-selecting */
if (has_bones == 0 && enumerate) {
- basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, extend);
+ basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle);
}
else {
basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, startbase, has_bones);
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index c16f04f01f3..714898fed21 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -247,9 +247,9 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera
copy_qt_qt(rv3d->viewquat, sms.new_quat);
rv3d->dist = sms.new_dist;
v3d->lens = sms.new_lens;
- }
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(v3d, rv3d);
+ }
if (rv3d->viewlock & RV3D_BOXVIEW)
view3d_boxview_copy(sa, ar);
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 3b9fe22d6a1..23c764f9252 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -526,6 +526,10 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
/* if autokeying is enabled, send notifiers that keyframes were added */
if (IS_AUTOKEY_ON(t->scene))
WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ /* redraw UV editor */
+ if (t->mode == TFM_EDGE_SLIDE && (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT))
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
/* XXX temp, first hack to get auto-render in compositor work (ton) */
WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C));
@@ -1220,8 +1224,10 @@ int transformEvent(TransInfo *t, wmEvent *event)
break;
case LEFTALTKEY:
case RIGHTALTKEY:
- if (t->spacetype == SPACE_SEQ)
+ if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
t->flag |= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ }
break;
default:
@@ -1259,8 +1265,10 @@ int transformEvent(TransInfo *t, wmEvent *event)
// break;
case LEFTALTKEY:
case RIGHTALTKEY:
- if (t->spacetype == SPACE_SEQ)
+ if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
t->flag &= ~T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ }
break;
default:
@@ -3947,10 +3955,8 @@ void initShrinkFatten(TransInfo *t)
}
-
int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
{
- float vec[3];
float distance;
int i;
char str[64];
@@ -3978,17 +3984,20 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
t->values[0] = -distance;
for (i = 0; i < t->total; i++, td++) {
+ float tdistance; /* temp dist */
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
- copy_v3_v3(vec, td->axismtx[2]);
- mul_v3_fl(vec, distance);
- mul_v3_fl(vec, td->factor);
+ /* get the final offset */
+ tdistance = distance * td->factor;
+ if (td->ext && (t->flag & T_ALT_TRANSFORM)) {
+ tdistance *= td->ext->isize[0]; /* shell factor */
+ }
- add_v3_v3v3(td->loc, td->iloc, vec);
+ madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance);
}
recalcData(t);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index f6b888d4881..9bbd3f59cbf 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -1917,6 +1917,10 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx
tx->size = vs->radius;
td->val = vs->radius;
}
+ else if (t->mode == TFM_SHRINKFATTEN) {
+ td->ext = tx;
+ tx->isize[0] = BM_vert_calc_shell_factor(eve);
+ }
}
static void createTransEditVerts(TransInfo *t)
@@ -2029,7 +2033,11 @@ static void createTransEditVerts(TransInfo *t)
else t->total = countsel;
tob = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mesh EditMode)");
- if (t->mode == TFM_SKIN_RESIZE) {
+ if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
+ /* warning, this is overkill, we only need 2 extra floats,
+ * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
+ * since we may not use the 'alt' transform mode to maintain shell thickness,
+ * but with generic transform code its hard to lazy init vars */
tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension),
"TransObData ext");
}
@@ -5029,9 +5037,10 @@ static void special_aftertrans_update__mask(bContext *C, TransInfo *t)
if (t->scene->nodetree) {
/* tracks can be used for stabilization nodes,
* flush update for such nodes */
- //if (nodeUpdateID(t->scene->nodetree, &mask->id)) {
+ //if (nodeUpdateID(t->scene->nodetree, &mask->id))
+ {
WM_event_add_notifier(C, NC_MASK | ND_DATA, &mask->id);
- //}
+ }
}
/* TODO - dont key all masks... */
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 0780b8f90b5..a3f45acc02e 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -744,7 +744,7 @@ static char axisBlendAngle(float angle)
return (char)(255.0f * (angle - 5) / 15.0f);
}
-/* three colors can be set;
+/* three colors can be set:
* gray for ghosting
* moving: in transform theme color
* else the red/green/blue
@@ -776,15 +776,13 @@ static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned c
}
break;
case 'X':
- col[0] = 220;
+ UI_GetThemeColor3ubv(TH_AXIS_X, col);
break;
case 'Y':
- col[1] = 220;
+ UI_GetThemeColor3ubv(TH_AXIS_Y, col);
break;
case 'Z':
- col[0] = 30;
- col[1] = 30;
- col[2] = 220;
+ UI_GetThemeColor3ubv(TH_AXIS_Z, col);
break;
default:
BLI_assert(!"invalid axis arg");
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index aadf547260d..b9774a9f7b0 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -890,7 +890,7 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace)
{
ColorSpace *colorspace = colormanage_colorspace_get_named(from_colorspace);
- if (colorspace->is_data) {
+ if (colorspace && colorspace->is_data) {
ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA;
return;
}
@@ -1083,7 +1083,7 @@ void IMB_colormanagement_check_is_data(ImBuf *ibuf, const char *name)
{
ColorSpace *colorspace = colormanage_colorspace_get_named(name);
- if (colorspace->is_data)
+ if (colorspace && colorspace->is_data)
ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA;
else
ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA;
@@ -1095,7 +1095,7 @@ void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name)
ibuf->float_colorspace = colorspace;
- if (colorspace->is_data)
+ if (colorspace && colorspace->is_data)
ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA;
else
ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA;
@@ -1107,7 +1107,7 @@ void IMB_colormanagement_assign_rect_colorspace(ImBuf *ibuf, const char *name)
ibuf->rect_colorspace = colorspace;
- if (colorspace->is_data)
+ if (colorspace && colorspace->is_data)
ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA;
else
ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA;
diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h
index 9b90b744b67..0291816cd03 100644
--- a/source/blender/imbuf/intern/dds/BlockDXT.h
+++ b/source/blender/imbuf/intern/dds/BlockDXT.h
@@ -173,24 +173,24 @@ struct AlphaBlockDXT5
};
*/
uint64 u;
- uint8 alpha0() const { return u & 0xffLL; };
- uint8 alpha1() const { return (u >> 8) & 0xffLL; };
- uint8 bits0() const { return (u >> 16) & 0x7LL; };
- uint8 bits1() const { return (u >> 19) & 0x7LL; };
- uint8 bits2() const { return (u >> 22) & 0x7LL; };
- uint8 bits3() const { return (u >> 25) & 0x7LL; };
- uint8 bits4() const { return (u >> 28) & 0x7LL; };
- uint8 bits5() const { return (u >> 31) & 0x7LL; };
- uint8 bits6() const { return (u >> 34) & 0x7LL; };
- uint8 bits7() const { return (u >> 37) & 0x7LL; };
- uint8 bits8() const { return (u >> 40) & 0x7LL; };
- uint8 bits9() const { return (u >> 43) & 0x7LL; };
- uint8 bitsA() const { return (u >> 46) & 0x7LL; };
- uint8 bitsB() const { return (u >> 49) & 0x7LL; };
- uint8 bitsC() const { return (u >> 52) & 0x7LL; };
- uint8 bitsD() const { return (u >> 55) & 0x7LL; };
- uint8 bitsE() const { return (u >> 58) & 0x7LL; };
- uint8 bitsF() const { return (u >> 61) & 0x7LL; };
+ uint8 alpha0() const { return u & 0xffLL; }
+ uint8 alpha1() const { return (u >> 8) & 0xffLL; }
+ uint8 bits0() const { return (u >> 16) & 0x7LL; }
+ uint8 bits1() const { return (u >> 19) & 0x7LL; }
+ uint8 bits2() const { return (u >> 22) & 0x7LL; }
+ uint8 bits3() const { return (u >> 25) & 0x7LL; }
+ uint8 bits4() const { return (u >> 28) & 0x7LL; }
+ uint8 bits5() const { return (u >> 31) & 0x7LL; }
+ uint8 bits6() const { return (u >> 34) & 0x7LL; }
+ uint8 bits7() const { return (u >> 37) & 0x7LL; }
+ uint8 bits8() const { return (u >> 40) & 0x7LL; }
+ uint8 bits9() const { return (u >> 43) & 0x7LL; }
+ uint8 bitsA() const { return (u >> 46) & 0x7LL; }
+ uint8 bitsB() const { return (u >> 49) & 0x7LL; }
+ uint8 bitsC() const { return (u >> 52) & 0x7LL; }
+ uint8 bitsD() const { return (u >> 55) & 0x7LL; }
+ uint8 bitsE() const { return (u >> 58) & 0x7LL; }
+ uint8 bitsF() const { return (u >> 61) & 0x7LL; }
void evaluatePalette(uint8 alpha[8]) const;
void evaluatePalette8(uint8 alpha[8]) const;
diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp
index ee7a0ebb2f7..05821b27ca6 100644
--- a/source/blender/imbuf/intern/dds/FlipDXT.cpp
+++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp
@@ -140,10 +140,10 @@ static void FlipDXT5BlockFull(uint8_t *block)
unsigned int line_2_3 = block[5] + 256 * (block[6] + 256 * block[7]);
// swap lines 0 and 1 in line_0_1.
unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
- ((line_0_1 & 0xfff000) >> 12);
+ ((line_0_1 & 0xfff000) >> 12);
// swap lines 2 and 3 in line_2_3.
unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) |
- ((line_2_3 & 0xfff000) >> 12);
+ ((line_2_3 & 0xfff000) >> 12);
block[2] = line_3_2 & 0xff;
block[3] = (line_3_2 & 0xff00) >> 8;
@@ -162,7 +162,7 @@ static void FlipDXT5BlockHalf(uint8_t *block)
// See layout above.
unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]);
unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
- ((line_0_1 & 0xfff000) >> 12);
+ ((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;
diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h
index 7fed4ca89e7..a1ac49b58da 100644
--- a/source/blender/imbuf/intern/dds/Stream.h
+++ b/source/blender/imbuf/intern/dds/Stream.h
@@ -35,7 +35,7 @@ struct Stream
unsigned char *mem; // location in memory
unsigned int size; // size
unsigned int pos; // current position
- Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {};
+ Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {}
unsigned int seek(unsigned int p);
};
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 55c1b02e90b..8d289de9970 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -583,23 +583,23 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
if (is_data) {
/* exception for non-color data, just copy float */
IMB_buffer_float_from_float(buffer, rect_float,
- ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0,
- w, h, w, ibuf->x);
+ ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0,
+ w, h, w, ibuf->x);
/* 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,
- w, h, ibuf->x, w);
+ 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
+ w, h, ibuf->x, w);
}
else {
IMB_buffer_float_from_float(buffer, rect_float,
- ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide,
- w, h, w, ibuf->x);
+ ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide,
+ w, h, w, ibuf->x);
/* XXX: need to convert to image buffer's rect space */
IMB_buffer_byte_from_float(rect_byte, buffer,
- 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0,
- w, h, ibuf->x, w);
+ 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0,
+ w, h, ibuf->x, w);
}
/* ensure user flag is reset */
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index 57fbce710a1..a185c4ee3e0 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -43,6 +43,7 @@
#include "BLI_utildefines.h"
#include "BLI_threads.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -95,132 +96,15 @@ static void pixel_from_buffer(struct ImBuf *ibuf, unsigned char **outI, float **
*outF = ibuf->rect_float + offset;
}
-/**************************************************************************
- * INTERPOLATIONS
- *
- * Reference and docs:
- * http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms
- ***************************************************************************/
-
-/* BICUBIC Interpolation functions
- * More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation
- * function assumes out to be zero'ed, only does RGBA */
-
-static float P(float k)
-{
- float p1, p2, p3, p4;
- p1 = MAX2(k + 2.0f, 0);
- p2 = MAX2(k + 1.0f, 0);
- p3 = MAX2(k, 0);
- p4 = MAX2(k - 1.0f, 0);
- return (float)(1.0f / 6.0f) * (p1 * p1 * p1 - 4.0f * p2 * p2 * p2 + 6.0f * p3 * p3 * p3 - 4.0f * p4 * p4 * p4);
-}
-
-
-#if 0
-/* older, slower function, works the same as above */
-static float P(float k)
-{
- return (float)(1.0f / 6.0f) * (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * pow(MAX2(k, 0), 3.0f) - 4.0f * pow(MAX2(k - 1.0f, 0), 3.0f));
-}
-#endif
+/* BICUBIC Interpolation */
void bicubic_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v)
{
- int i, j, n, m, x1, y1;
- unsigned char *dataI;
- float a, b, w, wx, wy[4], outR, outG, outB, outA, *dataF;
-
- /* sample area entirely outside image? */
- if (ceil(u) < 0 || floor(u) > in->x - 1 || ceil(v) < 0 || floor(v) > in->y - 1) {
- return;
- }
-
- /* ImBuf in must have a valid rect or rect_float, assume this is already checked */
-
- i = (int)floor(u);
- j = (int)floor(v);
- a = u - i;
- b = v - j;
-
- outR = outG = outB = outA = 0.0f;
-
-/* Optimized and not so easy to read */
-
- /* avoid calling multiple times */
- wy[0] = P(b - (-1));
- wy[1] = P(b - 0);
- wy[2] = P(b - 1);
- wy[3] = P(b - 2);
-
- for (n = -1; n <= 2; n++) {
- x1 = i + n;
- CLAMP(x1, 0, in->x - 1);
- wx = P(n - a);
- for (m = -1; m <= 2; m++) {
- y1 = j + m;
- CLAMP(y1, 0, in->y - 1);
- /* normally we could do this */
- /* w = P(n-a) * P(b-m); */
- /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */
- w = wx * wy[m + 1];
-
- if (outF) {
- dataF = in->rect_float + in->x * y1 * 4 + 4 * x1;
- outR += dataF[0] * w;
- outG += dataF[1] * w;
- outB += dataF[2] * w;
- outA += dataF[3] * w;
- }
- if (outI) {
- dataI = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1;
- outR += dataI[0] * w;
- outG += dataI[1] * w;
- outB += dataI[2] * w;
- outA += dataI[3] * w;
- }
- }
- }
-
-/* Done with optimized part */
-
-#if 0
- /* older, slower function, works the same as above */
- for (n = -1; n <= 2; n++) {
- for (m = -1; m <= 2; m++) {
- x1 = i + n;
- y1 = j + m;
- if (x1 > 0 && x1 < in->x && y1 > 0 && y1 < in->y) {
- if (do_float) {
- dataF = in->rect_float + in->x * y1 * 4 + 4 * x1;
- outR += dataF[0] * P(n - a) * P(b - m);
- outG += dataF[1] * P(n - a) * P(b - m);
- outB += dataF[2] * P(n - a) * P(b - m);
- outA += dataF[3] * P(n - a) * P(b - m);
- }
- if (do_rect) {
- dataI = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1;
- outR += dataI[0] * P(n - a) * P(b - m);
- outG += dataI[1] * P(n - a) * P(b - m);
- outB += dataI[2] * P(n - a) * P(b - m);
- outA += dataI[3] * P(n - a) * P(b - m);
- }
- }
- }
- }
-#endif
-
- if (outI) {
- outI[0] = (int)outR;
- outI[1] = (int)outG;
- outI[2] = (int)outB;
- outI[3] = (int)outA;
- }
if (outF) {
- outF[0] = outR;
- outF[1] = outG;
- outF[2] = outB;
- outF[3] = outA;
+ 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);
}
}
@@ -239,77 +123,14 @@ void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, in
bicubic_interpolation_color(in, outI, outF, u, v);
}
-/* function assumes out to be zero'ed, only does RGBA */
/* BILINEAR INTERPOLATION */
void bilinear_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v)
{
- float *row1, *row2, *row3, *row4, a, b;
- unsigned char *row1I, *row2I, *row3I, *row4I;
- float a_b, ma_b, a_mb, ma_mb;
- float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- unsigned char emptyI[4] = {0, 0, 0, 0};
- int y1, y2, x1, x2;
-
-
- /* ImBuf in must have a valid rect or rect_float, assume this is already checked */
-
- x1 = (int)floor(u);
- x2 = (int)ceil(u);
- y1 = (int)floor(v);
- y2 = (int)ceil(v);
-
- /* sample area entirely outside image? */
- if (x2 < 0 || x1 > in->x - 1 || y2 < 0 || y1 > in->y - 1) {
- return;
- }
-
if (outF) {
- /* sample including outside of edges of image */
- if (x1 < 0 || y1 < 0) row1 = empty;
- else row1 = in->rect_float + in->x * y1 * 4 + 4 * x1;
-
- if (x1 < 0 || y2 > in->y - 1) row2 = empty;
- else row2 = in->rect_float + in->x * y2 * 4 + 4 * x1;
-
- if (x2 > in->x - 1 || y1 < 0) row3 = empty;
- else row3 = in->rect_float + in->x * y1 * 4 + 4 * x2;
-
- if (x2 > in->x - 1 || y2 > in->y - 1) row4 = empty;
- else row4 = in->rect_float + in->x * y2 * 4 + 4 * x2;
-
- a = u - floorf(u);
- b = v - floorf(v);
- a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b);
-
- outF[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0];
- outF[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1];
- outF[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2];
- outF[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3];
+ BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v);
}
- if (outI) {
- /* sample including outside of edges of image */
- if (x1 < 0 || y1 < 0) row1I = emptyI;
- else row1I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1;
-
- if (x1 < 0 || y2 > in->y - 1) row2I = emptyI;
- else row2I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x1;
-
- if (x2 > in->x - 1 || y1 < 0) row3I = emptyI;
- else row3I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x2;
-
- if (x2 > in->x - 1 || y2 > in->y - 1) row4I = emptyI;
- else row4I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x2;
-
- a = u - floorf(u);
- b = v - floorf(v);
- a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b);
-
- /* need to add 0.5 to avoid rounding down (causes darken with the smear brush)
- * tested with white images and this should not wrap back to zero */
- outI[0] = (ma_mb * row1I[0] + a_mb * row3I[0] + ma_b * row2I[0] + a_b * row4I[0]) + 0.5f;
- outI[1] = (ma_mb * row1I[1] + a_mb * row3I[1] + ma_b * row2I[1] + a_b * row4I[1]) + 0.5f;
- outI[2] = (ma_mb * row1I[2] + a_mb * row3I[2] + ma_b * row2I[2] + a_b * row4I[2]) + 0.5f;
- outI[3] = (ma_mb * row1I[3] + a_mb * row3I[3] + ma_b * row2I[3] + a_b * row4I[3]) + 0.5f;
+ else {
+ BLI_bilinear_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v);
}
}
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 5dda33dfd62..38bd28452f3 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -872,7 +872,7 @@ static void index_rebuild_ffmpeg_proc_decoded_frame(
context->frameno = floor((pts - context->start_pts) *
context->pts_time_base *
- context->frame_rate + 0.5f);
+ context->frame_rate + 0.5);
/* decoding starts *always* on I-Frames,
* so: P-Frames won't work, even if all the
diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c
index 692ba3c49ea..d94f6368298 100644
--- a/source/blender/imbuf/intern/jp2.c
+++ b/source/blender/imbuf/intern/jp2.c
@@ -41,7 +41,7 @@
#include "openjpeg.h"
-#define JP2_FILEHEADER_SIZE 14
+// #define JP2_FILEHEADER_SIZE 14 /* UNUSED */
static char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A};
static char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00};
diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c
index 61275a8937c..d96a01d7093 100644
--- a/source/blender/imbuf/intern/jpeg.c
+++ b/source/blender/imbuf/intern/jpeg.c
@@ -235,19 +235,19 @@ static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t
*/
#define INPUT_BYTE(cinfo, V, action) \
MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \
- bytes_in_buffer--; \
- V = GETJOCTET(*next_input_byte++); )
+ bytes_in_buffer--; \
+ V = GETJOCTET(*next_input_byte++); )
/* As above, but read two bytes interpreted as an unsigned 16-bit integer.
* V should be declared unsigned int or perhaps INT32.
*/
#define INPUT_2BYTES(cinfo, V, action) \
MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \
- bytes_in_buffer--; \
- V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
- MAKE_BYTE_AVAIL(cinfo, action); \
- bytes_in_buffer--; \
- V += GETJOCTET(*next_input_byte++); )
+ bytes_in_buffer--; \
+ V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
+ MAKE_BYTE_AVAIL(cinfo, action); \
+ bytes_in_buffer--; \
+ V += GETJOCTET(*next_input_byte++); )
static boolean
diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp
index 7262656d4e8..21fa878c08a 100644
--- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp
@@ -33,25 +33,25 @@
#include "openexr_multi.h"
-void * IMB_exr_get_handle (void) {return NULL;}
-void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; }
+void *IMB_exr_get_handle (void) {return NULL;}
+void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; }
-int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;}
-int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;}
-void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; }
+int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;}
+int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;}
+void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; }
-void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; }
+void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; }
-void IMB_exr_read_channels (void *handle) { (void)handle; }
-void IMB_exr_write_channels (void *handle) { (void)handle; }
-void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; }
-void IMB_exrtile_clear_channels (void *handle) { (void)handle; }
+void IMB_exr_read_channels (void *handle) { (void)handle; }
+void IMB_exr_write_channels (void *handle) { (void)handle; }
+void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; }
+void IMB_exrtile_clear_channels (void *handle) { (void)handle; }
-void IMB_exr_multilayer_convert (void *handle, void *base,
- void * (*addlayer)(void *base, const char *str),
- void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id))
- {
- (void)handle; (void)base; (void)addlayer; (void)addpass;
- }
+void IMB_exr_multilayer_convert (void *handle, void *base,
+ void * (*addlayer)(void *base, const char *str),
+ void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id))
+{
+ (void)handle; (void)base; (void)addlayer; (void)addpass;
+}
-void IMB_exr_close (void *handle) { (void)handle; }
+void IMB_exr_close (void *handle) { (void)handle; }
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
index 72cec0e3749..03ed1bb8008 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -65,7 +65,6 @@
#define BLU 2
#define EXP 3
#define COLXS 128
-#define STR_MAX 540
typedef unsigned char RGBE[4];
typedef float fCOLOR[3];
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index 8e072361583..d2b0645cf93 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -587,7 +587,7 @@ void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, i
{
if (!ibuf) return;
buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, display,
- x1, y1, x2, y2);
+ x1, y1, x2, y2);
}
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 527f334d6a4..b9525ccccf1 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -331,13 +331,13 @@ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
for (y = ibuf2->y; y > 0; y--) {
p2f = p1f + (ibuf1->x << 2);
for (x = ibuf2->x; x > 0; x--) {
- destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]);
- destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]);
- destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]);
- destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]);
- p1f += 8;
- p2f += 8;
- destf += 4;
+ destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]);
+ destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]);
+ destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]);
+ destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]);
+ p1f += 8;
+ p2f += 8;
+ destf += 4;
}
p1f = p2f;
if (ibuf1->x & 1) p1f += 4;
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 3cf84648ea6..deb9902c35d 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -201,8 +201,8 @@ typedef struct Curve {
float twist_smooth, smallcaps_scale;
int pathlen;
- short pad, totcol;
- short flag, bevresol;
+ short bevresol, totcol;
+ int flag;
float width, ext1, ext2;
/* default */
@@ -269,6 +269,7 @@ typedef struct Curve {
#define CU_PATH_RADIUS 4096 /* make use of the path radius if this is enabled (default for new curves) */
#define CU_DEFORM_FILL 8192 /* fill 2d curve after deformation */
#define CU_FILL_CAPS 16384 /* fill bevel caps */
+#define CU_MAP_TAPER 32768 /* map taper object to bevelled area */
/* twist mode */
#define CU_TWIST_Z_UP 0
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 100968e7257..b7c1ee675b3 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -41,6 +41,7 @@
typedef struct bGPDspoint {
float x, y, z; /* co-ordinates of point (usually 2d, but can be 3d as well) */
float pressure; /* pressure of input device (from 0 to 1) at this point */
+ float time; /* seconds since start of stroke */
} bGPDspoint;
/* Grease-Pencil Annotations - 'Stroke'
@@ -55,6 +56,7 @@ typedef struct bGPDstroke {
short thickness; /* thickness of stroke (currently not used) */
short flag; /* various settings about this stroke */
+ double inittime; /* Init time of stroke */
} bGPDstroke;
/* bGPDstroke->flag */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index c9e929ce41b..2c896e4893f 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -665,7 +665,8 @@ typedef struct ShrinkwrapModifierData {
float keepDist; /* distance offset to keep from mesh/projection point */
short shrinkType; /* shrink type projection */
short shrinkOpts; /* shrink options */
- char projAxis; /* axis to project over */
+ float projLimit; /* limit the projection ray cast */
+ char projAxis; /* axis to project over */
/*
* if using projection over vertex normal this controls the
@@ -674,7 +675,7 @@ typedef struct ShrinkwrapModifierData {
*/
char subsurfLevels;
- char pad[6];
+ char pad[2];
} ShrinkwrapModifierData;
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 29f6499986c..89328c33674 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -297,22 +297,19 @@ typedef struct ObHook {
typedef struct DupliObject {
struct DupliObject *next, *prev;
struct Object *ob;
- unsigned int origlay;
- int index;
+ unsigned int origlay, pad;
float mat[4][4], omat[4][4];
float orco[3], uv[2];
short type; /* from Object.transflag */
char no_draw, animated;
- /* Lowest-level particle index.
- * Note: This is needed for particle info in shaders.
- * Otherwise dupli groups in particle systems would override the
- * index value from higher dupli levels. Would be nice to have full generic access
- * to all dupli levels somehow, but for now this should cover most use-cases.
- */
- int particle_index;
- int pad;
+ /* persistent identifier for a dupli object, for inter-frame matching of
+ * objects with motion blur, or inter-update matching for syncing */
+ int persistent_id[8]; /* MAX_DUPLI_RECUR */
+
+ /* particle this dupli was generated from */
+ struct ParticleSystem *particle_system;
} DupliObject;
/* **************** OBJECT ********************* */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index facddd8c718..c9e00e5f545 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1196,11 +1196,12 @@ typedef struct Scene {
/* Use the same flag for autothreads */
#define R_FIXED_THREADS 0x80000
-#define R_SPEED 0x100000
-#define R_SSS 0x200000
-#define R_NO_OVERWRITE 0x400000 /* skip existing files */
-#define R_TOUCH 0x800000 /* touch files before rendering */
-#define R_SIMPLIFY 0x1000000
+#define R_SPEED 0x100000
+#define R_SSS 0x200000
+#define R_NO_OVERWRITE 0x400000 /* skip existing files */
+#define R_TOUCH 0x800000 /* touch files before rendering */
+#define R_SIMPLIFY 0x1000000
+#define R_PERSISTENT_DATA 0x2000000 /* keep data around for re-render */
#define R_EDGE_FRS 0x2000000 /* R_EDGE for Freestyle */
/* seq_flag */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 98c135fcf53..1770a6e497c 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -162,7 +162,8 @@ typedef struct ThemeUI {
char iconfile[256]; // FILE_MAXFILE length
float icon_alpha;
- float pad;
+ /* Axis Colors */
+ char xaxis[4], yaxis[4], zaxis[4];
} ThemeUI;
/* try to put them all in one, if needed a special struct can be created as well
@@ -418,9 +419,11 @@ typedef struct UserDef {
float ndof_sensitivity; /* overall sensitivity of 3D mouse */
float ndof_orbit_sensitivity;
- float pad4;
int ndof_flag; /* flags for 3D mouse */
+ short ogl_multisamples; /* amount of samples for OpenGL FSA, if zero no FSA */
+ short pad4;
+
float glalphaclip;
short autokey_mode; /* autokeying mode */
@@ -703,6 +706,17 @@ typedef enum eCompute_Device_Type {
USER_COMPUTE_DEVICE_CUDA = 2,
} eCompute_Device_Type;
+
+typedef enum eMultiSample_Type {
+ USER_MULTISAMPLE_NONE = 0,
+ USER_MULTISAMPLE_2 = 2,
+ USER_MULTISAMPLE_4 = 4,
+ USER_MULTISAMPLE_8 = 8,
+ USER_MULTISAMPLE_16 = 16,
+} eMultiSample_Type;
+
+
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 188c11911b1..de91c17553e 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -1003,7 +1003,7 @@ static int make_structDNA(char *baseDirectory, FILE *file)
/* FOR DEBUG */
if (debugSDNA > 1) {
int a, b;
-/* short *elem; */
+ /* short *elem; */
short num_types;
printf("nr_names %d nr_types %d nr_structs %d\n", nr_names, nr_types, nr_structs);
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 317204b36dc..c057739a28f 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -80,13 +80,15 @@ static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, F
const char *name_override, int close_prototype);
/* helpers */
-#define WRITE_COMMA { \
+#define WRITE_COMMA \
+ { \
if (!first) \
fprintf(f, ", "); \
first = 0; \
} (void)0
-#define WRITE_PARAM(param) { \
+#define WRITE_PARAM(param) \
+ { \
WRITE_COMMA; \
fprintf(f, param); \
}
@@ -3580,10 +3582,10 @@ static void rna_generate_header_class_cpp(StructDefRNA *ds, FILE *f)
fprintf(f, "class %s : public %s {\n", srna->identifier, (srna->base) ? srna->base->identifier : "Pointer");
fprintf(f, "public:\n");
fprintf(f, "\t%s(const PointerRNA &ptr_arg) :\n\t\t%s(ptr_arg)", srna->identifier,
- (srna->base) ? srna->base->identifier : "Pointer");
+ (srna->base) ? srna->base->identifier : "Pointer");
for (dp = ds->cont.properties.first; dp; dp = dp->next)
if (rna_is_collection_prop(dp->prop))
- fprintf(f, ",\n\t\t%s(ptr_arg)", dp->prop->identifier);
+ fprintf(f, ",\n\t\t%s(ptr_arg)", dp->prop->identifier);
fprintf(f, "\n\t\t{}\n\n");
for (dp = ds->cont.properties.first; dp; dp = dp->next)
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 1fe46342819..81e738ed82f 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -1224,10 +1224,10 @@ void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA
if (prop->translation_context)
nitem[i].name = BLF_pgettext(prop->translation_context, nitem[i].name);
else
- nitem[i].name = BLF_gettext(nitem[i].name);
+ nitem[i].name = BLF_pgettext(NULL, nitem[i].name);
}
if (nitem[i].description)
- nitem[i].description = BLF_gettext(nitem[i].description);
+ nitem[i].description = BLF_pgettext(NULL, nitem[i].description);
}
*item = nitem;
@@ -4011,12 +4011,15 @@ static char *rna_idp_path(PointerRNA *ptr, IDProperty *haystack, IDProperty *nee
BLI_assert(haystack->type == IDP_GROUP);
link.up = parent_link;
+ /* always set both name and index,
+ * else a stale value might get used */
link.name = NULL;
link.index = -1;
for (i = 0, iter = haystack->data.group.first; iter; iter = iter->next, i++) {
if (needle == iter) { /* found! */
link.name = iter->name;
+ link.index = -1;
path = rna_idp_path_create(&link);
break;
}
@@ -4026,6 +4029,7 @@ static char *rna_idp_path(PointerRNA *ptr, IDProperty *haystack, IDProperty *nee
PointerRNA child_ptr = RNA_pointer_get(ptr, iter->name);
if (child_ptr.type) {
link.name = iter->name;
+ link.index = -1;
if ((path = rna_idp_path(&child_ptr, iter, needle, &link))) {
break;
}
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index e96ed4f38d3..7bdebd620ee 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -146,8 +146,8 @@ static int rna_SculptCapabilities_has_overlay_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM(br->mtex.brush_map_mode,
- MTEX_MAP_MODE_VIEW,
- MTEX_MAP_MODE_TILED);
+ MTEX_MAP_MODE_VIEW,
+ MTEX_MAP_MODE_TILED);
}
static int rna_SculptCapabilities_has_persistence_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index a3cff99ddc8..1e1a8c82b8e 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -1422,6 +1422,11 @@ static void rna_def_curve(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Fill Caps", "Fill caps for beveled curves");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
+ prop = RNA_def_property(srna, "use_map_taper", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_MAP_TAPER);
+ RNA_def_property_ui_text(prop, "Map Taper", "Map effect of taper object on actually bevelled curve");
+ RNA_def_property_update(prop, 0, "rna_Curve_update_data");
+
/* texture space */
prop = RNA_def_property(srna, "use_auto_texspace", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "texflag", CU_AUTOSPACE);
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index a6f4a88e6c3..d939b1073fc 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -2824,7 +2824,7 @@ static void rna_def_mesh(BlenderRNA *brna)
prop = RNA_def_property(srna, "skin_vertices", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_skin_vertices_begin", NULL, NULL, NULL,
- "rna_Mesh_skin_vertices_length", NULL, NULL, NULL);
+ "rna_Mesh_skin_vertices_length", NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "MeshSkinVertexLayer");
RNA_def_property_ui_text(prop, "Skin Vertices", "All skin vertices");
rna_def_skin_vertices(brna, prop);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index d421eb697a3..2e3f8feda44 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -2400,6 +2400,13 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Offset", "Distance to keep from the target");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "project_limit", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "projLimit");
+ RNA_def_property_range(prop, 0.0, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0, 100, 1, 2);
+ RNA_def_property_ui_text(prop, "Project Limit", "Limit the distance used for projection (zero disables)");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "use_project_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "projAxis", MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS);
RNA_def_property_ui_text(prop, "X", "");
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index d241f697be0..a68bcf62df8 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -220,6 +220,7 @@ EnumPropertyItem prop_wave_items[] = {
#include "ED_node.h"
+#include "RE_engine.h"
#include "RE_pipeline.h"
#include "DNA_scene_types.h"
@@ -1133,6 +1134,22 @@ static IDProperty *rna_ShaderNodeScript_idprops(PointerRNA *ptr, int create)
return nss->prop;
}
+static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
+ RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
+
+ if (engine_type && engine_type->update_script_node) {
+ /* auto update node */
+ RenderEngine *engine = RE_engine_create(engine_type);
+ engine_type->update_script_node(engine, ntree, node);
+ RE_engine_free(engine);
+ }
+
+ node_update(bmain, scene, ntree, node);
+}
+
#else
static EnumPropertyItem prop_image_layer_items[] = {
@@ -1204,7 +1221,7 @@ typedef struct 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)
+ const char *base_name, const char *ui_name, const char *ui_desc)
{
NodeInfo *ni = nodes + ID;
@@ -1930,14 +1947,14 @@ static void def_sh_script(StructRNA *srna)
RNA_def_property_struct_type(prop, "Text");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Script", "Internal shader script to define the shader");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+ 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");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update");
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_funcs(prop, NULL, "rna_ShaderNodeScript_mode_set", NULL);
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 82f27b953cf..d436e4719ea 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1419,6 +1419,12 @@ int rna_Camera_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
return ((Object *)value.id.data)->type == OB_CAMERA;
}
+int rna_DupliObject_index_get(PointerRNA *ptr)
+{
+ DupliObject *dob = (DupliObject *)ptr->data;
+ return dob->persistent_id[0];
+}
+
#else
static int rna_matrix_dimsize_4x4[] = {4, 4};
@@ -2653,22 +2659,23 @@ static void rna_def_dupli_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Hide", "Don't show dupli object in viewport or render");
prop = RNA_def_property(srna, "index", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "index");
+ RNA_def_property_int_funcs(prop, "rna_DupliObject_index_get", NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Index", "Index in the lowest-level dupli list");
-
- prop = RNA_def_property(srna, "particle_index", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "particle_index");
+
+ prop = RNA_def_property(srna, "persistent_id", PROP_INT, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Persistent ID", "Persistent identifier for inter-frame matching of objects with motion blur");
+
+ prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Particle Index", "Index in the lowest-level particle dupli list");
+ RNA_def_property_ui_text(prop, "Particle System", "Particle system that this dupli object was instanced from");
prop = RNA_def_property(srna, "orco", PROP_FLOAT, PROP_TRANSLATION);
- RNA_def_property_float_sdna(prop, NULL, "orco");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Generated Coordinates", "Generated coordinates in parent object space");
prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "uv");
RNA_def_property_array(prop, 2);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "UV Coordinates", "UV coordinates in parent object space");
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 516f619d910..6011af2626e 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1257,6 +1257,12 @@ static void rna_Scene_simplify_update(Main *bmain, Scene *scene, PointerRNA *ptr
rna_Scene_use_simplify_update(bmain, scene, ptr);
}
+static void rna_Scene_use_persistent_data_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
+{
+ if (!(scene->r.mode & R_PERSISTENT_DATA))
+ RE_FreePersistentData();
+}
+
static int rna_Scene_use_audio_get(PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
@@ -4483,6 +4489,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "simplify_flag", R_SIMPLE_NO_TRIANGULATE);
RNA_def_property_ui_text(prop, "Skip Quad to Triangles", "Disable non-planar quads being triangulated");
+ /* persistent data */
+ prop = RNA_def_property(srna, "use_persistent_data", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", R_PERSISTENT_DATA);
+ 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");
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 2a8f1b90d4e..548539e3395 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -390,7 +390,7 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_int(func, "active_layer", 0, 0, INT_MAX, "Active Layer", "", 0, INT_MAX);
RNA_def_property_flag(parm, PROP_REQUIRED);
- func = RNA_def_function(srna, "template_color_wheel", "uiTemplateColorWheel");
+ func = RNA_def_function(srna, "template_color_picker", "uiTemplateColorPicker");
RNA_def_function_ui_description(func, "Item. A color wheel widget to pick colors");
api_ui_item_rna_common(func);
RNA_def_boolean(func, "value_slider", 0, "", "Display the value slider to the right of the color wheel");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 52953144261..de53ef1f90a 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -395,7 +395,7 @@ static EnumPropertyItem *rna_userdef_compute_device_itemf(bContext *UNUSED(C), P
int a;
if (devices) {
- for (a = 0; devices[a].name; a++) {
+ for (a = 0; devices[a].identifier[0]; a++) {
tmp.value = devices[a].value;
tmp.identifier = devices[a].identifier;
tmp.name = devices[a].name;
@@ -770,6 +770,25 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
prop = RNA_def_property(srna, "icon_alpha", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_ui_text(prop, "Icon Alpha", "Transparency of icons in the interface, to reduce contrast");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ /* axis */
+ prop = RNA_def_property(srna, "axis_x", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "xaxis");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "X Axis", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "axis_y", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "yaxis");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Y Axis", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "axis_z", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "zaxis");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Z Axis", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_space_generic(BlenderRNA *brna)
@@ -3009,6 +3028,15 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem multi_sample_levels[] = {
+ {USER_MULTISAMPLE_NONE, "NONE", 0, "No MultiSample", "Do not use OpenGL MultiSample"},
+ {USER_MULTISAMPLE_2, "2", 0, "MultiSample: 2", "Use 2x OpenGL MultiSample (requires restart)"},
+ {USER_MULTISAMPLE_4, "4", 0, "MultiSample: 4", "Use 4x OpenGL MultiSample (requires restart)"},
+ {USER_MULTISAMPLE_8, "8", 0, "MultiSample: 8", "Use 8x OpenGL MultiSample (requires restart)"},
+ {USER_MULTISAMPLE_16, "16", 0, "MultiSample: 16", "Use 16x OpenGL MultiSample (requires restart)"},
+ {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 */
@@ -3153,6 +3181,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_enum_items(prop, color_picker_types);
RNA_def_property_enum_sdna(prop, NULL, "color_picker_type");
RNA_def_property_ui_text(prop, "Color Picker Type", "Different styles of displaying the color picker widget");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "use_preview_images", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ALLWINCODECS);
@@ -3302,6 +3331,12 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Text Anti-aliasing", "Draw user interface text anti-aliased");
RNA_def_property_update(prop, 0, "rna_userdef_text_update");
+ /* Full scene anti-aliasing */
+ prop = RNA_def_property(srna, "multi_sample", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "ogl_multisamples");
+ RNA_def_property_enum_items(prop, multi_sample_levels);
+ RNA_def_property_ui_text(prop, "MultiSample", "Enable OpenGL multi-sampling, only for systems that support it, requires restart");
+
#ifdef WITH_CYCLES
prop = RNA_def_property(srna, "compute_device_type", PROP_ENUM, PROP_NONE);
RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);
@@ -3431,7 +3466,7 @@ static void rna_def_userdef_input(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_SHOW_GUIDE);
RNA_def_property_ui_text(prop, "Show Navigation Guide", "Display the center and axis during rotation");
/* TODO: update description when fly-mode visuals are in place ("projected position in fly mode")*/
-
+
/* 3D view */
prop = RNA_def_property(srna, "ndof_view_rotate_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "ndof_flag");
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 92ad6faa3ce..1298d281de8 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -205,7 +205,8 @@ static MFace *get_dface(DerivedMesh *dm, DerivedMesh *split, int cur, int i, MFa
return df;
}
-#define SET_VERTS(a, b, c, d) { \
+#define SET_VERTS(a, b, c, d) \
+ { \
v[0] = mf->v##a; uv[0] = a - 1; \
v[1] = mf->v##b; uv[1] = b - 1; \
v[2] = mf->v##c; uv[2] = c - 1; \
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 8a4d70da6e8..38ec0e8bb4c 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -644,8 +644,8 @@ typedef struct {
} EdgeStackElem;
static void build_emats_stack(BLI_Stack *stack, int *visited_e, EMat *emat,
- const MeshElemMap *emap, const MEdge *medge,
- const MVertSkin *vs, const MVert *mvert)
+ const MeshElemMap *emap, const MEdge *medge,
+ const MVertSkin *vs, const MVert *mvert)
{
EdgeStackElem stack_elem;
float axis[3], angle;
@@ -673,7 +673,7 @@ static void build_emats_stack(BLI_Stack *stack, int *visited_e, EMat *emat,
/* If parent is a branch node, start a new edge chain */
if (parent_is_branch) {
calc_edge_mat(emat[e].mat, mvert[parent_v].co,
- mvert[v].co);
+ mvert[v].co);
}
else {
/* Build edge matrix guided by parent matrix */
@@ -959,12 +959,12 @@ static void add_poly(SkinOutput *so,
static void connect_frames(SkinOutput *so,
BMVert *frame1[4],
- BMVert *frame2[4])
+BMVert *frame2[4])
{
BMVert *q[4][4] = {{frame2[0], frame2[1], frame1[1], frame1[0]},
- {frame2[1], frame2[2], frame1[2], frame1[1]},
- {frame2[2], frame2[3], frame1[3], frame1[2]},
- {frame2[3], frame2[0], frame1[0], frame1[3]}};
+ {frame2[1], frame2[2], frame1[2], frame1[1]},
+ {frame2[2], frame2[3], frame1[3], frame1[2]},
+ {frame2[3], frame2[0], frame1[0], frame1[3]}};
float p[3], no[3];
int i, swap;
@@ -1354,24 +1354,6 @@ static void add_quad_from_tris(SkinOutput *so, BMEdge *e, BMFace *adj[2])
add_poly(so, quad[0], quad[1], quad[2], quad[3]);
}
-/* Returns the number of faces that are adjacent to both f1 and f2 */
-static int BM_face_share_face_count(BMFace *f1, BMFace *f2)
-{
- BMIter iter1, iter2;
- BMEdge *e;
- BMFace *f;
- int count = 0;
-
- 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_count(f, f2))
- count++;
- }
- }
-
- return count;
-}
-
static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd)
{
BMIter iter;
@@ -1434,7 +1416,7 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd)
* share a border with another face, output as a quad */
if (!BM_elem_flag_test(adj[0], BM_ELEM_TAG) &&
!BM_elem_flag_test(adj[1], BM_ELEM_TAG) &&
- !BM_face_share_face_count(adj[0], adj[1]))
+ !BM_face_share_face_check(adj[0], adj[1]))
{
add_quad_from_tris(so, e, adj);
BM_elem_flag_enable(adj[0], BM_ELEM_TAG);
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index cc77d73a736..fbd3c084e70 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -207,9 +207,10 @@ BLI_INLINE void madd_v3v3short_fl(float r[3], const short a[3], const float f)
r[2] += (float)a[2] * f;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *dm,
- ModifierApplyFlag UNUSED(flag))
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob,
+ DerivedMesh *dm,
+ ModifierApplyFlag UNUSED(flag))
{
int i;
DerivedMesh *result;
diff --git a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c
index e8965d50b47..44a5ac9e968 100644
--- a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c
+++ b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c
@@ -29,12 +29,8 @@
* \ingroup cmpnodes
*/
-
-
#include "node_composite_util.h"
-#define AVG(a, b) ((a + b) / 2)
-
/* ******************* Color Spill Supression ********************************* */
static bNodeSocketTemplate cmp_node_color_spill_in[] = {
{SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f},
@@ -49,6 +45,9 @@ static bNodeSocketTemplate cmp_node_color_spill_out[] = {
#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;
diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c
index 24ed825c36e..b0605f9b248 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bump.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bump.c
@@ -36,7 +36,7 @@
/* **************** BUMP ******************** */
static bNodeSocketTemplate sh_node_bump_in[] = {
- { SOCK_FLOAT, 1, "Strength", 0.1f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
+ { SOCK_FLOAT, 1, "Strength", 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f},
{ SOCK_FLOAT, 1, "Height", 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" }
};
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 39fd8a5decc..ee83699abdb 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -30,6 +30,7 @@
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_normal_map_in[] = {
+ { SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f},
{ SOCK_RGBA, 0, N_("Color"), 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 3b8193c422d..b8537a1359f 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -504,7 +504,7 @@ void PyC_SetHomePath(const char *py_path_bundle)
* but current Python lib (release 3.1.1) doesn't handle these correctly */
if (strchr(py_path_bundle, ':'))
printf("Warning : Blender application is located in a path containing : or / chars\
- \nThis may make python import function fail\n");
+ \nThis may make python import function fail\n");
#endif
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index f5c77d49c21..9d1e2b8e620 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -170,6 +170,8 @@ void RE_FreeRender (struct Render *re);
void RE_FreeAllRender (void);
/* only call on file load */
void RE_FreeAllRenderResults(void);
+/* for external render engines that can keep persistent data */
+void RE_FreePersistentData(void);
/* get results and statistics */
void RE_FreeRenderResult(struct RenderResult *rr);
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 7f785eb3d8b..f7a5a930ac6 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -59,6 +59,7 @@ struct RenderBuckets;
struct ObjectInstanceRen;
struct RayObject;
struct RayFace;
+struct RenderEngine;
struct ReportList;
struct Main;
@@ -183,6 +184,9 @@ struct Render
ListBase parts;
+ /* render engine */
+ struct RenderEngine *engine;
+
/* octree tables and variables for raytrace */
struct RayObject *raytree;
struct RayFace *rayfaces;
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index bb7c1bdf94b..47bff762d13 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -4561,7 +4561,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
ParticleSystem *psys;
int show_emitter, allow_render= 1, index, psysindex, i;
- index= (dob)? dob->index: 0;
+ index= (dob)? dob->persistent_id[0]: 0;
/* the emitter has to be processed first (render levels of modifiers) */
/* so here we only check if the emitter should be rendered */
@@ -4960,7 +4960,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, 0))) {
mult_m4_m4m4(mat, re->viewmat, dob->mat);
/* ob = particle system, use that layer */
- obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat, ob->lay);
+ obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], 0, mat, ob->lay);
/* fill in instance variables for texturing */
set_dupli_tex_mat(re, obi, dob);
@@ -4987,7 +4987,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, psysindex))) {
if (obi == NULL)
mult_m4_m4m4(mat, re->viewmat, dob->mat);
- obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat, obd->lay);
+ obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], psysindex++, mat, obd->lay);
set_dupli_tex_mat(re, obi, dob);
if (dob->type != OB_DUPLIGROUP) {
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index e2f347c05f1..8bdb805ada2 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -349,7 +349,12 @@ int RE_engine_render(Render *re, int do_all)
re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
/* render */
- engine = RE_engine_create(type);
+ if (!re->engine)
+ re->engine = RE_engine_create(type);
+
+ engine = re->engine;
+
+ /* TODO: actually link to a parent which shouldn't happen */
engine->re = re;
if (re->flag & R_ANIMATION)
@@ -377,6 +382,11 @@ int RE_engine_render(Render *re, int do_all)
if (type->render)
type->render(engine, re->scene);
+ if (!(re->r.mode & R_PERSISTENT_DATA)) {
+ RE_engine_free(re->engine);
+ re->engine = NULL;
+ }
+
if (re->result->do_exr_tile) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
render_result_exr_file_end(re);
@@ -389,8 +399,6 @@ int RE_engine_render(Render *re, int do_all)
render_result_free_list(&engine->fullresult, engine->fullresult.first);
- RE_engine_free(engine);
-
if (BKE_reports_contain(re->reports, RPT_ERROR))
G.is_break = TRUE;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 9dab18b3c2c..aab7f442249 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -247,6 +247,7 @@ Render *RE_GetRender(const char *name)
return re;
}
+
/* if you want to know exactly what has been done */
RenderResult *RE_AcquireResultRead(Render *re)
{
@@ -390,6 +391,9 @@ void RE_InitRenderCB(Render *re)
/* only call this while you know it will remove the link too */
void RE_FreeRender(Render *re)
{
+ if (re->engine)
+ RE_engine_free(re->engine);
+
BLI_rw_mutex_end(&re->resultmutex);
free_renderdata_tables(re);
@@ -424,6 +428,19 @@ void RE_FreeAllRenderResults(void)
}
}
+void RE_FreePersistentData(void)
+{
+ Render *re;
+
+ /* render engines can be kept around for quick re-render, this clears all */
+ for (re = RenderGlobal.renderlist.first; re; re = re->next) {
+ if (re->engine) {
+ RE_engine_free(re->engine);
+ re->engine = NULL;
+ }
+ }
+}
+
/* ********* initialize state ******** */
diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c
index b486407c61c..42849a01971 100644
--- a/source/blender/render/intern/source/voxeldata.c
+++ b/source/blender/render/intern/source/voxeldata.c
@@ -265,7 +265,7 @@ static void init_frame_smoke(VoxelData *vd, float cfra)
/* map velocities between 0 and 0.3f */
for (i = 0; i < totRes; i++) {
- vd->dataset[i] = sqrt(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f;
+ vd->dataset[i] = sqrtf(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f;
}
}
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index d7285ec4380..60e3f7d6164 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -711,12 +711,14 @@ static int wm_automatic_draw_method(wmWindow *win)
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE))
return USER_DRAW_OVERLAP;
/* also Intel drivers are slow */
+ /* 2.64 BCon3 period, let's try if intel now works...
else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_UNIX, GPU_DRIVER_ANY))
return USER_DRAW_OVERLAP;
else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY))
return USER_DRAW_OVERLAP_FLIP;
else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_ANY))
return USER_DRAW_OVERLAP_FLIP;
+ */
/* Windows software driver darkens color on each redraw */
else if (GPU_type_matches(GPU_DEVICE_SOFTWARE, GPU_OS_WIN, GPU_DRIVER_SOFTWARE))
return USER_DRAW_OVERLAP_FLIP;
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 7cfa3ce9396..54e61df4f6a 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1279,74 +1279,6 @@ int WM_userdef_event_map(int kmitype)
return kmitype;
}
-static void wm_eventemulation(wmEvent *event)
-{
- /* Store last mmb event value to make emulation work when modifier keys are released first. */
- static int mmb_emulated = 0; /* this should be in a data structure somwhere */
-
- /* middlemouse emulation */
- if (U.flag & USER_TWOBUTTONMOUSE) {
- if (event->type == LEFTMOUSE) {
-
- if (event->val == KM_PRESS && event->alt) {
- event->type = MIDDLEMOUSE;
- event->alt = 0;
- mmb_emulated = 1;
- }
- else if (event->val == KM_RELEASE) {
- /* only send middle-mouse release if emulated */
- if (mmb_emulated) {
- event->type = MIDDLEMOUSE;
- event->alt = 0;
- }
- mmb_emulated = 0;
- }
- }
-
- }
-
-#ifdef __APPLE__
-
- /* rightmouse emulation */
- if (U.flag & USER_TWOBUTTONMOUSE) {
- if (event->type == LEFTMOUSE) {
-
- if (event->val == KM_PRESS && event->oskey) {
- event->type = RIGHTMOUSE;
- event->oskey = 0;
- mmb_emulated = 1;
- }
- else if (event->val == KM_RELEASE) {
- if (mmb_emulated) {
- event->oskey = RIGHTMOUSE;
- event->alt = 0;
- }
- mmb_emulated = 0;
- }
- }
-
- }
-#endif
-
- /* numpad emulation */
- if (U.flag & USER_NONUMPAD) {
- switch (event->type) {
- case ZEROKEY: event->type = PAD0; break;
- case ONEKEY: event->type = PAD1; break;
- case TWOKEY: event->type = PAD2; break;
- case THREEKEY: event->type = PAD3; break;
- case FOURKEY: event->type = PAD4; break;
- case FIVEKEY: event->type = PAD5; break;
- case SIXKEY: event->type = PAD6; break;
- case SEVENKEY: event->type = PAD7; break;
- case EIGHTKEY: event->type = PAD8; break;
- case NINEKEY: event->type = PAD9; break;
- case MINUSKEY: event->type = PADMINUS; break;
- case EQUALKEY: event->type = PADPLUSKEY; break;
- case BACKSLASHKEY: event->type = PADSLASHKEY; break;
- }
- }
-}
static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi)
{
@@ -2113,8 +2045,6 @@ void wm_event_do_handlers(bContext *C)
}
#endif
- wm_eventemulation(event);
-
CTX_wm_window_set(C, win);
/* we let modal handlers get active area/region, also wm_paintcursor_test needs it */
@@ -2616,6 +2546,75 @@ static int convert_key(GHOST_TKey key)
}
}
+static void wm_eventemulation(wmEvent *event)
+{
+ /* Store last mmb event value to make emulation work when modifier keys are released first. */
+ static int mmb_emulated = 0; /* this should be in a data structure somwhere */
+
+ /* middlemouse emulation */
+ if (U.flag & USER_TWOBUTTONMOUSE) {
+ if (event->type == LEFTMOUSE) {
+
+ if (event->val == KM_PRESS && event->alt) {
+ event->type = MIDDLEMOUSE;
+ event->alt = 0;
+ mmb_emulated = 1;
+ }
+ else if (event->val == KM_RELEASE) {
+ /* only send middle-mouse release if emulated */
+ if (mmb_emulated) {
+ event->type = MIDDLEMOUSE;
+ event->alt = 0;
+ }
+ mmb_emulated = 0;
+ }
+ }
+
+ }
+
+#ifdef __APPLE__
+
+ /* rightmouse emulation */
+ if (U.flag & USER_TWOBUTTONMOUSE) {
+ if (event->type == LEFTMOUSE) {
+
+ if (event->val == KM_PRESS && event->oskey) {
+ event->type = RIGHTMOUSE;
+ event->oskey = 0;
+ mmb_emulated = 1;
+ }
+ else if (event->val == KM_RELEASE) {
+ if (mmb_emulated) {
+ event->oskey = RIGHTMOUSE;
+ event->alt = 0;
+ }
+ mmb_emulated = 0;
+ }
+ }
+
+ }
+#endif
+
+ /* numpad emulation */
+ if (U.flag & USER_NONUMPAD) {
+ switch (event->type) {
+ case ZEROKEY: event->type = PAD0; break;
+ case ONEKEY: event->type = PAD1; break;
+ case TWOKEY: event->type = PAD2; break;
+ case THREEKEY: event->type = PAD3; break;
+ case FOURKEY: event->type = PAD4; break;
+ case FIVEKEY: event->type = PAD5; break;
+ case SIXKEY: event->type = PAD6; break;
+ case SEVENKEY: event->type = PAD7; break;
+ case EIGHTKEY: event->type = PAD8; break;
+ case NINEKEY: event->type = PAD9; break;
+ case MINUSKEY: event->type = PADMINUS; break;
+ case EQUALKEY: event->type = PADPLUSKEY; break;
+ case BACKSLASHKEY: event->type = PADSLASHKEY; break;
+ }
+ }
+}
+
/* adds customdata to event */
static void update_tablet_data(wmWindow *win, wmEvent *event)
{
@@ -2825,6 +2824,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
else
event.type = MIDDLEMOUSE;
+ wm_eventemulation(&event);
+
/* copy previous state to prev event state (two old!) */
evt->prevval = evt->val;
evt->prevtype = evt->type;
@@ -2890,6 +2891,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/
event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE;
+ wm_eventemulation(&event);
+
/* copy previous state to prev event state (two old!) */
evt->prevval = evt->val;
evt->prevtype = evt->type;
@@ -2978,9 +2981,13 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
if (event.keymodifier == UNKNOWNKEY)
event.keymodifier = 0;
- /* if test_break set, it catches this. XXX Keep global for now? */
- if (event.type == ESCKEY && event.val == KM_PRESS)
+ /* if test_break set, it catches this. Do not set with modifier presses. XXX Keep global for now? */
+ if ((event.type == ESCKEY && event.val == KM_PRESS) &&
+ /* check other modifiers because ms-windows uses these to bring up the task manager */
+ (event.shift == 0 && event.ctrl == 0 && event.alt == 0))
+ {
G.is_break = TRUE;
+ }
/* double click test - only for press */
if (event.val == KM_PRESS) {
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 616567e8184..a965cbf82d6 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -333,8 +333,14 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
{
GHOST_WindowHandle ghostwin;
+ static int multisamples = -1;
int scr_w, scr_h, posy;
+ /* force setting multisamples only once, it requires restart - and you cannot
+ mix it, either all windows have it, or none (tested in OSX opengl) */
+ if (multisamples == -1)
+ multisamples = U.ogl_multisamples;
+
wm_get_screensize(&scr_w, &scr_h);
posy = (scr_h - win->posy - win->sizey);
@@ -345,7 +351,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
(GHOST_TWindowState)win->windowstate,
GHOST_kDrawingContextTypeOpenGL,
0 /* no stereo */,
- 0 /* no AA */);
+ multisamples /* AA */);
if (ghostwin) {
/* needed so we can detect the graphics card below */
@@ -373,7 +379,6 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
/* standard state vars for window */
glEnable(GL_SCISSOR_TEST);
-
GPU_state_init();
}
}
@@ -749,6 +754,11 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
state = GHOST_GetWindowState(win->ghostwin);
win->windowstate = state;
+ /* stop screencast if resize */
+ if (type == GHOST_kEventWindowSize) {
+ WM_jobs_stop(CTX_wm_manager(C), win->screen, NULL);
+ }
+
/* win32: gives undefined window size when minimized */
if (state != GHOST_kWindowStateMinimized) {
GHOST_RectangleHandle client_rect;
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 828b7f5066c..11e790451cd 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -191,6 +191,10 @@ endif()
list(APPEND BLENDER_SORTED_LIBS bf_intern_guardedalloc_cpp)
endif()
+ if(WITH_INTERNATIONAL)
+ list(APPEND BLENDER_SORTED_LIBS bf_intern_locale)
+ endif()
+
foreach(SORTLIB ${BLENDER_SORTED_LIBS})
set(REMLIB ${SORTLIB})
foreach(SEARCHLIB ${BLENDER_LINK_LIBS})
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 2d37b0e1401..8274585cdb1 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -425,7 +425,7 @@ void uiTemplateEditModeSelection(struct uiLayout *layout, struct bContext *C) {}
void uiTemplateTextureImage(struct uiLayout *layout, struct bContext *C, struct Tex *tex) {}
void uiTemplateImage(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *userptr, int compact) {}
void uiTemplateDopeSheetFilter(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr) {}
-void uiTemplateColorWheel(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider) {}
+void uiTemplateColorPicker(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider) {}
void uiTemplateHistogram(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand) {}
void uiTemplateReportsBanner(struct uiLayout *layout, struct bContext *C, struct wmOperator *op) {}
void uiTemplateWaveform(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand) {}
@@ -464,6 +464,8 @@ ListBase R_engines = {NULL, NULL};
void RE_engine_free(struct RenderEngine *engine) {}
struct RenderEngineType *RE_engines_find(const char *idname) { return NULL; }
void RE_engine_update_memory_stats(struct RenderEngine *engine, float mem_used, float mem_peak) {};
+struct RenderEngine *RE_engine_create(struct RenderEngineType *type) { return NULL; };
+void RE_FreePersistentData(void) {}
/* python */
struct wmOperatorType *WM_operatortype_find(const char *idname, int quiet) {return (struct wmOperatorType *) NULL;}
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index f986e30b10c..5da08cf67da 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -470,20 +470,6 @@ elseif(WIN32)
DESTINATION ${TARGETDIR}
)
- if(WITH_INTERNATIONAL AND (NOT WITH_MINGW64))
- install(
- FILES ${LIBDIR}/gettext/lib/gnu_gettext.dll
- DESTINATION ${TARGETDIR}
- )
-
- if(NOT CMAKE_CL_64)
- install(
- FILES ${LIBDIR}/iconv/lib/iconv.dll
- DESTINATION ${TARGETDIR}
- )
- endif()
- endif()
-
if(WITH_PYTHON)
set_lib_path(PYLIB "python")
install(
@@ -531,7 +517,7 @@ elseif(WIN32)
endif()
if(CMAKE_CL_64)
- # gettext and png are statically linked on win64
+ # png is statically linked on win64
install(
FILES ${LIBDIR}/zlib/lib/zlib.dll
DESTINATION ${TARGETDIR}
@@ -989,6 +975,10 @@ endif()
list_insert_after(BLENDER_SORTED_LIBS "cycles_kernel" "cycles_kernel_osl")
endif()
+ if(WITH_INTERNATIONAL)
+ list(APPEND BLENDER_SORTED_LIBS bf_intern_locale)
+ endif()
+
foreach(SORTLIB ${BLENDER_SORTED_LIBS})
set(REMLIB ${SORTLIB})
foreach(SEARCHLIB ${BLENDER_LINK_LIBS})
diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp
index 7cf895255ba..11e90e1797d 100644
--- a/source/gameengine/Converter/BL_ArmatureChannel.cpp
+++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp
@@ -95,7 +95,7 @@ BL_ArmatureChannel::~BL_ArmatureChannel()
// PYTHON
PyMethodDef BL_ArmatureChannel::Methods[] = {
- {NULL,NULL} //Sentinel
+ {NULL,NULL} //Sentinel
};
// order of definition of attributes, must match Attributes[] array
diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
index b8ad117a220..379be91b523 100644
--- a/source/gameengine/Converter/BL_ArmatureConstraint.cpp
+++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
@@ -246,7 +246,7 @@ void BL_ArmatureConstraint::SetSubtarget(KX_GameObject* subtarget)
// PYTHON
PyMethodDef BL_ArmatureConstraint::Methods[] = {
- {NULL,NULL} //Sentinel
+ {NULL,NULL} //Sentinel
};
// order of definition of attributes, must match Attributes[] array
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index ed97b9ff73f..1f1c404efcb 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -639,7 +639,6 @@ PyTypeObject BL_ArmatureObject::Type = {
};
PyMethodDef BL_ArmatureObject::Methods[] = {
-
KX_PYMETHODTABLE_NOARGS(BL_ArmatureObject, update),
{NULL,NULL} //Sentinel
};
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 58ae415e9d3..eb695e624e4 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -423,64 +423,55 @@ static void SetDefaultLightMode(Scene* scene)
// --
-static void GetRGB(short type,
- MFace* mface,
- MCol* mmcol,
- Material *mat,
- unsigned int &c0,
- unsigned int &c1,
- unsigned int &c2,
- unsigned int &c3)
+static void GetRGB(
+ const bool use_mcol,
+ MFace *mface,
+ MCol *mmcol,
+ Material *mat,
+ unsigned int &c0,
+ unsigned int &c1,
+ unsigned int &c2,
+ unsigned int &c3)
{
unsigned int color = 0xFFFFFFFFL;
- switch (type) {
- case 0: // vertex colors
- {
- if (mmcol) {
- c0 = KX_Mcol2uint_new(mmcol[0]);
- c1 = KX_Mcol2uint_new(mmcol[1]);
- c2 = KX_Mcol2uint_new(mmcol[2]);
- if (mface->v4)
- c3 = KX_Mcol2uint_new(mmcol[3]);
- }
- else { // backup white
- c0 = KX_rgbaint2uint_new(color);
- c1 = KX_rgbaint2uint_new(color);
- c2 = KX_rgbaint2uint_new(color);
- if (mface->v4)
- c3 = KX_rgbaint2uint_new( color );
- }
- } break;
-
-
- case 1: // material rgba
- {
- if (mat) {
- union {
- unsigned char cp[4];
- unsigned int integer;
- } col_converter;
- col_converter.cp[3] = (unsigned char) (mat->r * 255.0f);
- col_converter.cp[2] = (unsigned char) (mat->g * 255.0f);
- col_converter.cp[1] = (unsigned char) (mat->b * 255.0f);
- col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f);
- color = col_converter.integer;
- }
- c0 = KX_rgbaint2uint_new(color);
- c1 = KX_rgbaint2uint_new(color);
- c2 = KX_rgbaint2uint_new(color);
+ if (use_mcol) {
+ // vertex colors
+
+ if (mmcol) {
+ c0 = KX_Mcol2uint_new(mmcol[0]);
+ c1 = KX_Mcol2uint_new(mmcol[1]);
+ c2 = KX_Mcol2uint_new(mmcol[2]);
if (mface->v4)
- c3 = KX_rgbaint2uint_new(color);
- } break;
-
- default: // white
- {
+ c3 = KX_Mcol2uint_new(mmcol[3]);
+ }
+ else { // backup white
c0 = KX_rgbaint2uint_new(color);
c1 = KX_rgbaint2uint_new(color);
c2 = KX_rgbaint2uint_new(color);
if (mface->v4)
- c3 = KX_rgbaint2uint_new(color);
- } break;
+ c3 = KX_rgbaint2uint_new( color );
+ }
+ }
+ else {
+ // material rgba
+ if (mat) {
+ union {
+ unsigned char cp[4];
+ unsigned int integer;
+ } col_converter;
+ col_converter.cp[3] = (unsigned char) (mat->r * 255.0f);
+ col_converter.cp[2] = (unsigned char) (mat->g * 255.0f);
+ col_converter.cp[1] = (unsigned char) (mat->b * 255.0f);
+ col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f);
+ color = col_converter.integer;
+ }
+ // backup white is fallback
+
+ c0 = KX_rgbaint2uint_new(color);
+ c1 = KX_rgbaint2uint_new(color);
+ c2 = KX_rgbaint2uint_new(color);
+ if (mface->v4)
+ c3 = KX_rgbaint2uint_new(color);
}
}
@@ -489,6 +480,45 @@ 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])
+{
+ 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]);
+ }
+}
+
+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);
+
+ uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f);
+
+ /* 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);
+ }
+ }
+ 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);
+ }
+}
+
// ------------------------------------
static bool ConvertMaterial(
BL_Material *material,
@@ -496,30 +526,25 @@ static bool ConvertMaterial(
MTFace* tface,
const char *tfaceName,
MFace* mface,
- MCol* mmcol,
+ MCol* mmcol, /* only for text, use first mcol, weak */
MTF_localLayer *layers,
- bool glslmat)
+ int layer_uv[2],
+ const bool glslmat)
{
material->Initialize();
int numchan = -1, texalpha = 0;
bool validmat = (mat!=0);
bool validface = (tface!=0);
- short type = 0;
- if ( validmat )
- type = 1; // material color
-
material->IdMode = DEFAULT_BLENDER;
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 vertex colors by explicitly setting
- if (mat->mode &MA_VERTEXCOLP || glslmat)
- type = 0;
-
// use lighting?
material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT;
material->ras_mode |= ( mat->game.flag & GEMAT_BACKCULL )?0:TWOSIDED;
@@ -772,33 +797,19 @@ static bool ConvertMaterial(
// No material - old default TexFace properties
material->ras_mode |= USE_LIGHT;
}
- MT_Point2 uv[4];
- MT_Point2 uv2[4];
- const char *uvName = "", *uv2Name = "";
-
- uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f);
+ 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;
-
- 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]);
-
uvName = tfaceName;
}
else {
// nothing at all
material->alphablend = GEMAT_SOLID;
material->tile = 0;
-
- uv[0] = uv[1] = uv[2] = uv[3] = MT_Point2(0.0f, 0.0f);
}
if (validmat && validface) {
@@ -816,49 +827,30 @@ static bool ConvertMaterial(
}
// get uv sets
- if (validmat)
- {
+ 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++)
- {
+ for (int vind = 0; vind<material->num_enabled; vind++) {
BL_Mapping &map = material->mapping[vind];
- if (map.uvCoName.IsEmpty())
+ if (map.uvCoName.IsEmpty()) {
isFirstSet = false;
- else
- {
- for (int lay=0; lay<MAX_MTFACE; lay++)
- {
+ }
+ 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)
- {
- MT_Point2 uvSet[4];
-
- uvSet[0].setValue(layer.face->uv[0]);
- uvSet[1].setValue(layer.face->uv[1]);
- uvSet[2].setValue(layer.face->uv[2]);
-
- if (mface->v4)
- uvSet[3].setValue(layer.face->uv[3]);
- else
- uvSet[3].setValue(0.0f, 0.0f);
-
- if (isFirstSet)
- {
- uv[0] = uvSet[0]; uv[1] = uvSet[1];
- uv[2] = uvSet[2]; uv[3] = uvSet[3];
+ 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)
- {
- uv2[0] = uvSet[0]; uv2[1] = uvSet[1];
- uv2[2] = uvSet[2]; uv2[3] = uvSet[3];
+ else if (strcmp(layer.name, uvName) != 0) {
+ layer_uv[1] = lay;
map.mapping |= USECUSTOMUV;
uv2Name = layer.name;
}
@@ -868,21 +860,11 @@ static bool ConvertMaterial(
}
}
- unsigned int rgb[4];
- GetRGB(type,mface,mmcol,mat,rgb[0],rgb[1],rgb[2], rgb[3]);
-
- // swap the material color, so MCol on bitmap font works
- if (validmat && type==1 && (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]);
+ if (validmat && mmcol) { /* color is only for text */
+ material->m_mcol = *(unsigned int *)mmcol;
}
-
- material->SetConversionRGB(rgb);
- material->SetConversionUV(uvName, uv);
- material->SetConversionUV2(uv2Name, uv2);
+ material->SetUVLayerName(uvName);
+ material->SetUVLayerName2(uv2Name);
if (validmat)
material->matname =(mat->id.name);
@@ -928,6 +910,7 @@ 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 = "";
@@ -1025,34 +1008,43 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
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 */
- unsigned int rgb[4];
- MT_Point2 uv[4];
+ MT_Point2 uv_1[4];
+ MT_Point2 uv_2[4];
/* first is the BL_Material */
- if (!bl_mat)
+ if (!bl_mat) {
bl_mat = new BL_Material();
- ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol,
- layers, converter->GetGLSLMaterials());
+ }
+
+ /* 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 were stored in bl_mat temporarily */
- bl_mat->GetConversionRGB(rgb);
- rgb0 = rgb[0]; rgb1 = rgb[1];
- rgb2 = rgb[2]; rgb3 = rgb[3];
+ /* 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);
- bl_mat->GetConversionUV(uv);
- uv0 = uv[0]; uv1 = uv[1];
- uv2 = uv[2]; uv3 = uv[3];
+ uv0 = uv_1[0]; uv1 = uv_1[1];
+ uv2 = uv_1[2]; uv3 = uv_1[3];
- bl_mat->GetConversionUV2(uv);
- uv20 = uv[0]; uv21 = uv[1];
- uv22 = uv[2]; uv23 = uv[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();
- kx_blmat->Initialize(scene, bl_mat, (ma?&ma->game:NULL));
+ //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 {
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index 30a4209965e..d1684db0f5a 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -103,6 +103,7 @@ extern "C"
#include "KX_MeshProxy.h"
#include "RAS_MeshObject.h"
extern "C" {
+ #include "PIL_time.h"
#include "BKE_context.h"
#include "BLO_readfile.h"
#include "BKE_idcode.h"
@@ -957,10 +958,12 @@ static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const c
bool 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 */
- int idcode= BKE_idcode_from_name(group);
+ const int idcode = BKE_idcode_from_name(group);
ReportList reports;
static char err_local[255];
-
+
+// TIMEIT_START(bge_link_blend_file);
+
/* 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);
@@ -1059,7 +1062,9 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha
}
}
}
-
+
+// TIMEIT_END(bge_link_blend_file);
+
return true;
}
diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp
index cb6bc556bab..0261a4a2d02 100644
--- a/source/gameengine/Expressions/IntValue.cpp
+++ b/source/gameengine/Expressions/IntValue.cpp
@@ -286,7 +286,7 @@ cInt CIntValue::GetInt()
double CIntValue::GetNumber()
{
- return (float) m_int;
+ return (double) m_int;
}
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index bb1d0a31c1f..77c76ca8153 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -259,7 +259,7 @@ void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper
* PyObjectPlus Methods -- Every class, even the abstract one should have a Methods
------------------------------*/
PyMethodDef PyObjectPlus::Methods[] = {
- {NULL, NULL} /* Sentinel */
+ {NULL, NULL} /* Sentinel */
};
#define BGE_PY_ATTR_INVALID (&(PyObjectPlus::Attributes[0]))
@@ -486,8 +486,8 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
static bool py_check_attr_float(float *var, PyObject *value, const PyAttributeDef *attrdef)
{
- double val = PyFloat_AsDouble(value);
- if (val == -1.0 && PyErr_Occurred())
+ float val = PyFloat_AsDouble(value);
+ if (val == -1.0f && PyErr_Occurred())
{
PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
return false;
@@ -664,13 +664,13 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
{
float *var = reinterpret_cast<float*>(ptr);
ptr += sizeof(float);
- double val = PyFloat_AsDouble(item);
- if (val == -1.0 && PyErr_Occurred())
+ float val = PyFloat_AsDouble(item);
+ if (val == -1.0f && PyErr_Occurred())
{
PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name);
goto UNDO_AND_ERROR;
}
- else if (attrdef->m_clamp)
+ else if (attrdef->m_clamp)
{
if (val < attrdef->m_fmin)
val = attrdef->m_fmin;
@@ -985,10 +985,10 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
for (int i=0; i<3; i++)
{
item = PySequence_GetItem(value, i); /* new ref */
- double val = PyFloat_AsDouble(item);
+ float val = PyFloat_AsDouble(item);
Py_DECREF(item);
item = NULL;
- if (val == -1.0 && PyErr_Occurred())
+ if (val == -1.0f && PyErr_Occurred())
{
PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name);
goto RESTORE_AND_ERROR;
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
index ab0e6c5edcb..4916d8a0a57 100644
--- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
@@ -202,7 +202,7 @@ PyTypeObject SCA_ILogicBrick::Type = {
};
PyMethodDef SCA_ILogicBrick::Methods[] = {
- {NULL,NULL} //Sentinel
+ {NULL,NULL} //Sentinel
};
PyAttributeDef SCA_ILogicBrick::Attributes[] = {
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
index 5dd4cc501ca..f02ac495233 100644
--- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
@@ -126,7 +126,6 @@ bool SCA_PropertySensor::Evaluate()
bool SCA_PropertySensor::CheckPropertyCondition()
{
-
m_recentresult=false;
bool result=false;
bool reverse = false;
@@ -153,13 +152,11 @@ bool SCA_PropertySensor::CheckPropertyCondition()
*/
if (result==false && dynamic_cast<CFloatValue *>(orgprop) != NULL) {
float f;
-
- if (EOF == sscanf(m_checkpropval.ReadPtr(), "%f", &f))
- {
- //error
+ if (sscanf(m_checkpropval.ReadPtr(), "%f", &f) == 1) {
+ result = (f == ((CFloatValue *)orgprop)->GetFloat());
}
else {
- result = (f == ((CFloatValue *)orgprop)->GetFloat());
+ /* error */
}
}
/* end patch */
@@ -174,7 +171,7 @@ bool SCA_PropertySensor::CheckPropertyCondition()
case KX_PROPSENSOR_EXPRESSION:
{
- /*
+#if 0
if (m_rightexpr)
{
CValue* resultval = m_rightexpr->Calculate();
@@ -189,7 +186,7 @@ bool SCA_PropertySensor::CheckPropertyCondition()
result = resultval->GetNumber() != 0;
}
}
- */
+#endif
break;
}
case KX_PROPSENSOR_INTERVAL:
@@ -197,7 +194,16 @@ bool SCA_PropertySensor::CheckPropertyCondition()
CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
if (!orgprop->IsError())
{
- float val = orgprop->GetText().ToFloat(), min = m_checkpropval.ToFloat(), max = m_checkpropmaxval.ToFloat();
+ const float min = m_checkpropval.ToFloat();
+ const float max = m_checkpropmaxval.ToFloat();
+ float val;
+
+ if (dynamic_cast<CStringValue *>(orgprop) == NULL) {
+ val = orgprop->GetNumber();
+ }
+ else {
+ val = orgprop->GetText().ToFloat();
+ }
result = (min <= val) && (val <= max);
}
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
index 2d51a45fe55..01995b13ad7 100644
--- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
@@ -220,11 +220,11 @@ bool SCA_RandomActuator::Update()
* this will be quite sufficient here.
*/
do {
- x = 2.0 * m_base->DrawFloat() - 1.0;
- y = 2.0 * m_base->DrawFloat() - 1.0;
- s = x*x + y*y;
- } while ( (s >= 1.0) || (s == 0.0) );
- t = x * sqrt( (-2.0 * log(s)) / s);
+ x = 2.0f * m_base->DrawFloat() - 1.0f;
+ y = 2.0f * m_base->DrawFloat() - 1.0f;
+ s = x * x + y * y;
+ } while ((s >= 1.0f) || (s == 0.0f));
+ t = x * sqrtf((-2.0 * log(s)) / s);
tmpval = new CFloatValue(m_parameter1 + m_parameter2 * t);
}
}
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index 725c23c60e3..3e8755c41ce 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -172,7 +172,7 @@ static BOOL scr_saver_init(int argc, char **argv)
#endif /* WIN32 */
-void usage(const char* program, bool isBlenderPlayer)
+static void usage(const char* program, bool isBlenderPlayer)
{
const char * consoleoption;
const char * example_filename = "";
@@ -332,7 +332,7 @@ static BlendFileData *load_game_data(const char *progname, char *filename = NULL
return bfd;
}
-bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs)
+static bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs)
{
bool run = true;
system->processEvents(false);
@@ -352,7 +352,7 @@ struct GPG_NextFrameState {
GlobalSettings *gs;
} gpg_nextframestate;
-int GPG_PyNextFrame(void *state0)
+static int GPG_PyNextFrame(void *state0)
{
GPG_NextFrameState *state = (GPG_NextFrameState *) state0;
int exitcode;
@@ -450,7 +450,6 @@ int main(int argc, char** argv)
// Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c)
BLF_init(11, U.dpi);
BLF_lang_init();
- BLF_lang_encoding("");
BLF_lang_set("");
BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp
index 4c7518769e1..0954aa0f7ab 100644
--- a/source/gameengine/Ketsji/BL_Material.cpp
+++ b/source/gameengine/Ketsji/BL_Material.cpp
@@ -36,10 +36,7 @@ BL_Material::BL_Material()
void BL_Material::Initialize()
{
- rgb[0] = 0;
- rgb[1] = 0;
- rgb[2] = 0;
- rgb[3] = 0;
+ m_mcol = 0xFFFFFFFFL;
IdMode = 0;
ras_mode = 0;
glslmat = 0;
@@ -66,11 +63,6 @@ void BL_Material::Initialize()
share = false;
int i;
- for (i=0; i<4; i++)
- {
- uv[i] = MT_Point2(0.f,1.f);
- uv2[i] = MT_Point2(0.f, 1.f);
- }
for (i=0; i<MAXTEX; i++) // :(
{
@@ -98,56 +90,15 @@ void BL_Material::Initialize()
}
}
-void BL_Material::SetConversionRGB(unsigned int *nrgb)
-{
- rgb[0]=*nrgb++;
- rgb[1]=*nrgb++;
- rgb[2]=*nrgb++;
- rgb[3]=*nrgb;
-}
-
-void BL_Material::GetConversionRGB(unsigned int *nrgb)
-{
- *nrgb++ = rgb[0];
- *nrgb++ = rgb[1];
- *nrgb++ = rgb[2];
- *nrgb = rgb[3];
-}
-
-void BL_Material::SetConversionUV(const STR_String& name, MT_Point2 *nuv)
+void BL_Material::SetUVLayerName(const STR_String& name)
{
uvName = name;
- uv[0] = *nuv++;
- uv[1] = *nuv++;
- uv[2] = *nuv++;
- uv[3] = *nuv;
}
-
-void BL_Material::GetConversionUV(MT_Point2 *nuv)
-{
- *nuv++ = uv[0];
- *nuv++ = uv[1];
- *nuv++ = uv[2];
- *nuv = uv[3];
-}
-void BL_Material::SetConversionUV2(const STR_String& name, MT_Point2 *nuv)
+void BL_Material::SetUVLayerName2(const STR_String& name)
{
uv2Name = name;
- uv2[0] = *nuv++;
- uv2[1] = *nuv++;
- uv2[2] = *nuv++;
- uv2[3] = *nuv;
}
-void BL_Material::GetConversionUV2(MT_Point2 *nuv)
-{
- *nuv++ = uv2[0];
- *nuv++ = uv2[1];
- *nuv++ = uv2[2];
- *nuv = uv2[3];
-}
-
-
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 b67bd95f878..ef180ed2126 100644
--- a/source/gameengine/Ketsji/BL_Material.h
+++ b/source/gameengine/Ketsji/BL_Material.h
@@ -87,22 +87,13 @@ public:
MTFace tface; /* copy of the derived meshes tface */
Image* img[MAXTEX];
EnvMap* cubemap[MAXTEX];
-
- unsigned int rgb[4];
- MT_Point2 uv[4];
- MT_Point2 uv2[4];
+ unsigned int m_mcol; /* for text color (only) */
STR_String uvName;
STR_String uv2Name;
- void SetConversionRGB(unsigned int *rgb);
- void GetConversionRGB(unsigned int *rgb);
-
- void SetConversionUV(const STR_String& name, MT_Point2 *uv);
- void GetConversionUV(MT_Point2 *uv);
-
- void SetConversionUV2(const STR_String& name, MT_Point2 *uv);
- void GetConversionUV2(MT_Point2 *uv);
+ void SetUVLayerName(const STR_String &name);
+ void SetUVLayerName2(const STR_String &name);
void SetSharedMaterial(bool v);
bool IsShared();
diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp
index fb8e7beb157..b047588df5a 100644
--- a/source/gameengine/Ketsji/BL_Shader.cpp
+++ b/source/gameengine/Ketsji/BL_Shader.cpp
@@ -571,41 +571,39 @@ void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
}
-int BL_Shader::GetAttribLocation(const STR_String& name)
+int BL_Shader::GetAttribLocation(const char *name)
{
- if ( GLEW_ARB_fragment_shader &&
- GLEW_ARB_vertex_shader &&
- GLEW_ARB_shader_objects
- )
+ if (GLEW_ARB_fragment_shader &&
+ GLEW_ARB_vertex_shader &&
+ GLEW_ARB_shader_objects)
{
- return glGetAttribLocationARB(mShader, name.ReadPtr());
+ return glGetAttribLocationARB(mShader, name);
}
return -1;
}
-void BL_Shader::BindAttribute(const STR_String& attr, int loc)
+void BL_Shader::BindAttribute(const char *attr, int loc)
{
- if ( GLEW_ARB_fragment_shader &&
- GLEW_ARB_vertex_shader &&
- GLEW_ARB_shader_objects
- )
+ if (GLEW_ARB_fragment_shader &&
+ GLEW_ARB_vertex_shader &&
+ GLEW_ARB_shader_objects )
{
- glBindAttribLocationARB(mShader, loc, attr.ReadPtr());
+ glBindAttribLocationARB(mShader, loc, attr);
}
}
-int BL_Shader::GetUniformLocation(const STR_String& name)
+int BL_Shader::GetUniformLocation(const char *name)
{
if ( GLEW_ARB_fragment_shader &&
GLEW_ARB_vertex_shader &&
- GLEW_ARB_shader_objects
+ GLEW_ARB_shader_objects
)
{
MT_assert(mShader!=0);
- int location = glGetUniformLocationARB(mShader, name.ReadPtr());
+ int location = glGetUniformLocationARB(mShader, name);
if (location == -1)
- spit("Invalid uniform value: " << name.ReadPtr() << ".");
+ spit("Invalid uniform value: " << name << ".");
return location;
}
@@ -900,7 +898,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
Py_RETURN_NONE;
}
- const char *uniform="";
+ const char *uniform;
int index=-1;
if (PyArg_ParseTuple(args, "si:setSampler", &uniform, &index))
{
@@ -941,7 +939,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
Py_RETURN_NONE;
}
- const char *uniform="";
+ const char *uniform;
float value=0;
if (PyArg_ParseTuple(args, "sf:setUniform1f", &uniform, &value ))
{
@@ -965,7 +963,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f, "setUniform2f(name, fx, fy)")
if (mError) {
Py_RETURN_NONE;
}
- const char *uniform="";
+ const char *uniform;
float array[2] = {0, 0};
if (PyArg_ParseTuple(args, "sff:setUniform2f", &uniform, &array[0],&array[1] ))
{
@@ -989,7 +987,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
if (mError) {
Py_RETURN_NONE;
}
- const char *uniform="";
+ const char *uniform;
float array[3] = {0, 0, 0};
if (PyArg_ParseTuple(args, "sfff:setUniform3f", &uniform, &array[0],&array[1],&array[2]))
{
@@ -1014,7 +1012,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) "
if (mError) {
Py_RETURN_NONE;
}
- const char *uniform="";
+ const char *uniform;
float array[4] = {0, 0, 0, 0};
if (PyArg_ParseTuple(args, "sffff:setUniform4f", &uniform, &array[0],&array[1],&array[2], &array[3]))
{
@@ -1038,7 +1036,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
if (mError) {
Py_RETURN_NONE;
}
- const char *uniform="";
+ const char *uniform;
int value=0;
if (PyArg_ParseTuple(args, "si:setUniform1i", &uniform, &value ))
{
@@ -1062,7 +1060,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i, "setUniform2i(name, ix, iy)")
if (mError) {
Py_RETURN_NONE;
}
- const char *uniform="";
+ const char *uniform;
int array[2] = {0, 0};
if (PyArg_ParseTuple(args, "sii:setUniform2i", &uniform, &array[0],&array[1] ))
{
@@ -1087,7 +1085,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
Py_RETURN_NONE;
}
- const char *uniform="";
+ const char *uniform;
int array[3] = {0, 0, 0};
if (PyArg_ParseTuple(args, "siii:setUniform3i", &uniform, &array[0],&array[1],&array[2]))
{
@@ -1110,7 +1108,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) "
if (mError) {
Py_RETURN_NONE;
}
- const char *uniform="";
+ const char *uniform;
int array[4] = {0, 0, 0, 0};
if (PyArg_ParseTuple(args, "siiii:setUniform4i", &uniform, &array[0],&array[1],&array[2], &array[3] ))
{
@@ -1296,7 +1294,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4,
0,0,0,1
};
- const char *uniform="";
+ const char *uniform;
PyObject *matrix=0;
int transp=0; // python use column major by default, so no transpose....
@@ -1342,7 +1340,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
0,0,1,
};
- const char *uniform="";
+ const char *uniform;
PyObject *matrix=0;
int transp=0; // python use column major by default, so no transpose....
if (!PyArg_ParseTuple(args, "sO|i:setUniformMatrix3",&uniform, &matrix,&transp))
@@ -1404,9 +1402,9 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" )
Py_RETURN_NONE;
}
- const char *uniform="";
+ const char *uniform;
int nloc=0;
- if (PyArg_ParseTuple(args, "si:setUniformDef",&uniform, &nloc))
+ if (PyArg_ParseTuple(args, "si:setUniformDef", &uniform, &nloc))
{
int loc = GetUniformLocation(uniform);
if (loc != -1)
diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h
index 82476873b85..243445d95c5 100644
--- a/source/gameengine/Ketsji/BL_Shader.h
+++ b/source/gameengine/Ketsji/BL_Shader.h
@@ -205,9 +205,9 @@ public:
void SetUniformfv(int location,int type, float *param, int size,bool transpose=false);
void SetUniformiv(int location,int type, int *param, int size,bool transpose=false);
- int GetAttribLocation(const STR_String& name);
- void BindAttribute(const STR_String& attr, int loc);
- int GetUniformLocation(const STR_String& name);
+ int GetAttribLocation(const char *name);
+ void BindAttribute(const char *attr, int loc);
+ int GetUniformLocation(const char *name);
void SetUniform(int uniform, const MT_Tuple2& vec);
void SetUniform(int uniform, const MT_Tuple3& vec);
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index 2154beeb205..88e26fd9a55 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -124,7 +124,7 @@ MTFace* KX_BlenderMaterial::GetMTFace(void) const
unsigned int* KX_BlenderMaterial::GetMCol(void) const
{
// fonts on polys
- return mMaterial->rgb;
+ return &mMaterial->m_mcol;
}
void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
@@ -138,6 +138,11 @@ 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;
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h
index 1653669ebcc..7bc9c7c3863 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.h
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h
@@ -76,6 +76,8 @@ 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;
diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h
index cc99aba99f6..3b0058aca6f 100644
--- a/source/gameengine/Ketsji/KX_CharacterWrapper.h
+++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h
@@ -32,4 +32,4 @@ private:
PHY_ICharacter* m_character;
};
-#endif //__KX_CHARACTERWRAPPER_H__
+#endif /* __KX_CHARACTERWRAPPER_H__ */
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index a669f4346ea..4f3d020a3d9 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -99,6 +99,7 @@ KX_GameObject::KX_GameObject(
m_bSuspendDynamics(false),
m_bUseObjectColor(false),
m_bIsNegativeScaling(false),
+ m_objectColor(1.0, 1.0, 1.0, 1.0),
m_bVisible(true),
m_bCulled(true),
m_bOccluder(false),
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp
index 87c366046ad..9430179e344 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.cpp
+++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp
@@ -70,13 +70,15 @@ PyTypeObject KX_MeshProxy::Type = {
};
PyMethodDef KX_MeshProxy::Methods[] = {
-{"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS},
-{"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS},
-{"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS},
-{"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS},
-{"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS},
-//{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS},
- {NULL,NULL} //Sentinel
+ {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS},
+ {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS},
+ {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS},
+ {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS},
+ {"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS},
+ {"transform", (PyCFunction)KX_MeshProxy::sPyTransform,METH_VARARGS},
+ {"transform_uv", (PyCFunction)KX_MeshProxy::sPyTransformUV,METH_VARARGS},
+ //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS},
+ {NULL,NULL} //Sentinel
};
PyAttributeDef KX_MeshProxy::Attributes[] = {
@@ -218,6 +220,160 @@ PyObject *KX_MeshProxy::PyGetPolygon(PyObject *args, PyObject *kwds)
return polyob;
}
+PyObject *KX_MeshProxy::PyTransform(PyObject *args, PyObject *kwds)
+{
+ int matindex;
+ PyObject *pymat;
+ bool ok = false;
+
+ MT_Matrix4x4 transform;
+
+ if (!PyArg_ParseTuple(args,"iO:transform", &matindex, &pymat) ||
+ !PyMatTo(pymat, transform))
+ {
+ return NULL;
+ }
+
+ MT_Matrix4x4 ntransform = transform.inverse().transposed();
+ ntransform[0][3] = ntransform[1][3] = ntransform[2][3] = 0.0f;
+
+ /* transform mesh verts */
+ unsigned int mit_index = 0;
+ for (list<RAS_MeshMaterial>::iterator mit = m_meshobj->GetFirstMaterial();
+ (mit != m_meshobj->GetLastMaterial());
+ ++mit, ++mit_index)
+ {
+ if (matindex == -1) {
+ /* always transform */
+ }
+ else if (matindex == mit_index) {
+ /* we found the right index! */
+ }
+ else {
+ continue;
+ }
+
+ RAS_MeshSlot *slot = mit->m_baseslot;
+ RAS_MeshSlot::iterator it;
+ ok = true;
+
+ for (slot->begin(it); !slot->end(it); slot->next(it)) {
+ size_t i;
+ for (i = it.startvertex; i < it.endvertex; i++) {
+ RAS_TexVert *vert = &it.vertex[i];
+ vert->Transform(transform, ntransform);
+ }
+ }
+
+ /* if we set a material index, quit when done */
+ if (matindex == mit_index) {
+ break;
+ }
+ }
+
+ if (ok == false) {
+ PyErr_Format(PyExc_ValueError,
+ "mesh.transform(...): invalid material index %d", matindex);
+ return NULL;
+ }
+
+ m_meshobj->SetMeshModified(true);
+
+ Py_RETURN_NONE;
+}
+
+PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds)
+{
+ int matindex;
+ PyObject *pymat;
+ int uvindex = -1;
+ int uvindex_from = -1;
+ bool ok = false;
+
+ MT_Matrix4x4 transform;
+
+ if (!PyArg_ParseTuple(args,"iO|iii:transform_uv", &matindex, &pymat, &uvindex, &uvindex_from) ||
+ !PyMatTo(pymat, transform))
+ {
+ return NULL;
+ }
+
+ if (uvindex < -1 || uvindex > 1) {
+ PyErr_Format(PyExc_ValueError,
+ "mesh.transform_uv(...): invalid uv_index %d", uvindex);
+ return NULL;
+ }
+ if (uvindex_from < -1 || uvindex_from > 1 || uvindex == -1) {
+ PyErr_Format(PyExc_ValueError,
+ "mesh.transform_uv(...): invalid uv_index_from %d", uvindex);
+ return NULL;
+ }
+ if (uvindex_from == uvindex) {
+ uvindex_from = -1;
+ }
+
+ /* transform mesh verts */
+ unsigned int mit_index = 0;
+ for (list<RAS_MeshMaterial>::iterator mit = m_meshobj->GetFirstMaterial();
+ (mit != m_meshobj->GetLastMaterial());
+ ++mit, ++mit_index)
+ {
+ if (matindex == -1) {
+ /* always transform */
+ }
+ else if (matindex == mit_index) {
+ /* we found the right index! */
+ }
+ else {
+ continue;
+ }
+
+ RAS_MeshSlot *slot = mit->m_baseslot;
+ RAS_MeshSlot::iterator it;
+ ok = true;
+
+ for (slot->begin(it); !slot->end(it); slot->next(it)) {
+ size_t i;
+
+ 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());
+ }
+
+ switch (uvindex) {
+ case 0:
+ vert->TransformUV1(transform);
+ break;
+ case 1:
+ vert->TransformUV2(transform);
+ break;
+ case -1:
+ vert->TransformUV1(transform);
+ vert->TransformUV2(transform);
+ break;
+ }
+ }
+ }
+
+ /* if we set a material index, quit when done */
+ if (matindex == mit_index) {
+ break;
+ }
+ }
+
+ if (ok == false) {
+ PyErr_Format(PyExc_ValueError,
+ "mesh.transform_uv(...): invalid material index %d", matindex);
+ return NULL;
+ }
+
+ m_meshobj->SetMeshModified(true);
+
+ Py_RETURN_NONE;
+}
+
PyObject *KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_MeshProxy* self = static_cast<KX_MeshProxy*>(self_v);
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h
index 98e73aa626f..5366634ef98 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.h
+++ b/source/gameengine/Ketsji/KX_MeshProxy.h
@@ -71,8 +71,10 @@ public:
KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength);
KX_PYMETHOD(KX_MeshProxy,GetVertex);
KX_PYMETHOD(KX_MeshProxy,GetPolygon);
+ KX_PYMETHOD(KX_MeshProxy,Transform);
+ KX_PYMETHOD(KX_MeshProxy,TransformUV);
- static PyObject* pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *pyattr_get_numMaterials(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
static PyObject *pyattr_get_numPolygons(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
};
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
index 36c94dc997b..f89b918f31b 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 {
- memset(&m_mcol, 0, sizeof(m_mcol));
+ m_mcol = 0;
}
m_material = ma;
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h
index 89bfb4ff9fb..2ce8f480c1c 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;
+ mutable unsigned int m_mcol; /* for text color (only) */
Material* m_material;
#ifdef WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
index d850168afdf..56dccc1d045 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
@@ -190,8 +190,8 @@ PyTypeObject KX_SCA_AddObjectActuator::Type = {
};
PyMethodDef KX_SCA_AddObjectActuator::Methods[] = {
- {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"},
- {NULL,NULL} //Sentinel
+ {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS, NULL},
+ {NULL,NULL} //Sentinel
};
PyAttributeDef KX_SCA_AddObjectActuator::Attributes[] = {
diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp
index e6209d2d47b..81c9dc91603 100644
--- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp
@@ -113,7 +113,7 @@ PyTypeObject KX_SCA_EndObjectActuator::Type = {
};
PyMethodDef KX_SCA_EndObjectActuator::Methods[] = {
- {NULL,NULL} //Sentinel
+ {NULL,NULL} //Sentinel
};
PyAttributeDef KX_SCA_EndObjectActuator::Attributes[] = {
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 96b4a21a36c..72be5f57b95 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -55,7 +55,7 @@
#include "SCA_BasicEventManager.h"
#include "KX_Camera.h"
#include "SCA_JoystickManager.h"
-
+#include "KX_PyMath.h"
#include "RAS_MeshObject.h"
#include "RAS_IRasterizer.h"
@@ -1706,6 +1706,17 @@ void KX_Scene::SetGravity(const MT_Vector3& gravity)
GetPhysicsEnvironment()->setGravity(gravity[0],gravity[1],gravity[2]);
}
+MT_Vector3 KX_Scene::GetGravity()
+{
+ PHY__Vector3 gravity;
+ MT_Vector3 vec;
+
+ GetPhysicsEnvironment()->getGravity(gravity);
+ vec = gravity.m_vec;
+
+ return vec;
+}
+
void KX_Scene::SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter)
{
m_sceneConverter = sceneConverter;
@@ -2270,6 +2281,25 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene* self = static_cast<KX_Scene*>(self_v);
+
+ return PyObjectFrom(self->GetGravity());
+}
+
+int KX_Scene::pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_Scene* self = static_cast<KX_Scene*>(self_v);
+
+ MT_Vector3 vec;
+ if (!PyVecTo(value, vec))
+ return PY_SET_ATTR_FAIL;
+
+ self->SetGravity(vec);
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyAttributeDef KX_Scene::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("name", KX_Scene, pyattr_get_name),
KX_PYATTRIBUTE_RO_FUNCTION("objects", KX_Scene, pyattr_get_objects),
@@ -2280,6 +2310,7 @@ PyAttributeDef KX_Scene::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera),
KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre),
KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post),
+ KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_Scene, pyattr_get_gravity, pyattr_set_gravity),
KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend),
KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling),
KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius),
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index c2e468e6da6..29473949535 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -573,6 +573,7 @@ public:
void SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* physEnv);
void SetGravity(const MT_Vector3& gravity);
+ MT_Vector3 GetGravity();
short GetAnimationFPS();
@@ -616,6 +617,8 @@ public:
static int pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(GetName()); }
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp
index dabb79b357d..82e414d7c42 100644
--- a/source/gameengine/Ketsji/KX_VertexProxy.cpp
+++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp
@@ -61,19 +61,19 @@ PyTypeObject KX_VertexProxy::Type = {
};
PyMethodDef KX_VertexProxy::Methods[] = {
-{"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS},
-{"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O},
-{"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_NOARGS},
-{"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_O},
-
-{"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS},
-{"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS},
-
-{"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS},
-{"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O},
-{"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_NOARGS},
-{"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_O},
- {NULL,NULL} //Sentinel
+ {"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS},
+ {"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O},
+ {"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV1, METH_NOARGS},
+ {"setUV", (PyCFunction)KX_VertexProxy::sPySetUV1, METH_O},
+
+ {"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS},
+ {"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS},
+
+ {"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS},
+ {"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O},
+ {"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_NOARGS},
+ {"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_O},
+ {NULL,NULL} //Sentinel
};
PyAttributeDef KX_VertexProxy::Attributes[] = {
@@ -247,7 +247,7 @@ int KX_VertexProxy::pyattr_set_u(void *self_v, const struct KX_PYATTRIBUTE_DEF *
float val = PyFloat_AsDouble(value);
MT_Point2 uv = self->m_vertex->getUV1();
uv[0] = val;
- self->m_vertex->SetUV(uv);
+ self->m_vertex->SetUV1(uv);
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
@@ -262,7 +262,7 @@ int KX_VertexProxy::pyattr_set_v(void *self_v, const struct KX_PYATTRIBUTE_DEF *
float val = PyFloat_AsDouble(value);
MT_Point2 uv = self->m_vertex->getUV1();
uv[1] = val;
- self->m_vertex->SetUV(uv);
+ self->m_vertex->SetUV1(uv);
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
@@ -389,9 +389,8 @@ int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF
if (PySequence_Check(value))
{
MT_Point2 vec;
- if (PyVecTo(value, vec))
- {
- self->m_vertex->SetUV(vec);
+ if (PyVecTo(value, vec)) {
+ self->m_vertex->SetUV1(vec);
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
@@ -521,18 +520,18 @@ PyObject *KX_VertexProxy::PySetRGBA(PyObject *value)
}
-PyObject *KX_VertexProxy::PyGetUV()
+PyObject *KX_VertexProxy::PyGetUV1()
{
return PyObjectFrom(MT_Vector2(m_vertex->getUV1()));
}
-PyObject *KX_VertexProxy::PySetUV(PyObject *value)
+PyObject *KX_VertexProxy::PySetUV1(PyObject *value)
{
MT_Point2 vec;
if (!PyVecTo(value, vec))
return NULL;
- m_vertex->SetUV(vec);
+ m_vertex->SetUV1(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 6e193d35b4c..4247d138a66 100644
--- a/source/gameengine/Ketsji/KX_VertexProxy.h
+++ b/source/gameengine/Ketsji/KX_VertexProxy.h
@@ -92,8 +92,8 @@ public:
KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ);
KX_PYMETHOD_O(KX_VertexProxy,SetXYZ);
- KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV);
- KX_PYMETHOD_O(KX_VertexProxy,SetUV);
+ KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV1);
+ KX_PYMETHOD_O(KX_VertexProxy,SetUV1);
KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV2);
KX_PYMETHOD_VARARGS(KX_VertexProxy,SetUV2);
diff --git a/source/gameengine/Network/NG_NetworkDeviceInterface.h b/source/gameengine/Network/NG_NetworkDeviceInterface.h
index 48edbdfc7fe..6da478ecda5 100644
--- a/source/gameengine/Network/NG_NetworkDeviceInterface.h
+++ b/source/gameengine/Network/NG_NetworkDeviceInterface.h
@@ -43,8 +43,8 @@ private:
// candidates for shared/common implementation class
bool m_online;
public:
- NG_NetworkDeviceInterface() {};
- virtual ~NG_NetworkDeviceInterface() {};
+ NG_NetworkDeviceInterface() {}
+ virtual ~NG_NetworkDeviceInterface() {}
virtual void NextFrame()=0;
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
index d1a8143fa88..d1fabba18f9 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
@@ -85,8 +85,9 @@ void DummyPhysicsEnvironment::setGravity(float x,float y,float z)
{
}
-
-
+void DummyPhysicsEnvironment::getGravity(PHY__Vector3& grav)
+{
+}
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
index 233c4412d9e..5ce34bdf7cf 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
@@ -56,6 +56,7 @@ public:
virtual float getFixedTimeStep();
virtual void setGravity(float x,float y,float z);
+ virtual void getGravity(PHY__Vector3& grav);
virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
float pivotX,float pivotY,float pivotZ,
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
index 077d225903c..bfbe570ad0c 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -143,6 +143,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 int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
float pivotX,float pivotY,float pivotZ,
diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h
index 53195d79768..60b9f052075 100644
--- a/source/gameengine/Rasterizer/RAS_ICanvas.h
+++ b/source/gameengine/Rasterizer/RAS_ICanvas.h
@@ -59,7 +59,7 @@ public:
virtual
~RAS_ICanvas(
) {
- };
+ }
virtual
void
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
index 16ecffb9a32..4c72f128817 100644
--- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
@@ -189,6 +189,8 @@ class RAS_MeshMaterial
public:
RAS_MeshSlot *m_baseslot;
class RAS_MaterialBucket *m_bucket;
+
+ /* the KX_GameObject is used as a key here */
CTR_Map<CTR_HashedPtr,RAS_MeshSlot*> m_slots;
diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp
index b60fae73e2a..945644ff3e6 100644
--- a/source/gameengine/Rasterizer/RAS_TexVert.cpp
+++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp
@@ -63,10 +63,10 @@ const MT_Point3& RAS_TexVert::xyz()
void RAS_TexVert::SetRGBA(const MT_Vector4& rgba)
{
unsigned char *colp = (unsigned char*) &m_rgba;
- colp[0] = (unsigned char) (rgba[0]*255.0f);
- colp[1] = (unsigned char) (rgba[1]*255.0f);
- colp[2] = (unsigned char) (rgba[2]*255.0f);
- colp[3] = (unsigned char) (rgba[3]*255.0f);
+ colp[0] = (unsigned char) (rgba[0] * 255.0);
+ colp[1] = (unsigned char) (rgba[1] * 255.0);
+ colp[2] = (unsigned char) (rgba[2] * 255.0);
+ colp[3] = (unsigned char) (rgba[3] * 255.0);
}
@@ -75,21 +75,32 @@ void RAS_TexVert::SetXYZ(const MT_Point3& xyz)
xyz.getValue(m_localxyz);
}
-void RAS_TexVert::SetXYZ(const float *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::SetUV(const MT_Point2& uv)
+void RAS_TexVert::SetUV1(const MT_Point2& uv)
{
uv.getValue(m_uv1);
}
+void RAS_TexVert::SetUV1(const float uv[3])
+{
+ m_uv1[0] = uv[0];
+ m_uv1[1] = uv[1];
+}
+
void RAS_TexVert::SetUV2(const MT_Point2& uv)
{
uv.getValue(m_uv2);
}
+void RAS_TexVert::SetUV2(const float uv[3])
+{
+ m_uv2[0] = uv[0];
+ m_uv2[1] = uv[1];
+}
void RAS_TexVert::SetRGBA(const unsigned int rgba)
{
@@ -151,3 +162,12 @@ void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat)
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());
+}
+
+void RAS_TexVert::TransformUV2(const MT_Matrix4x4& mat)
+{
+ SetUV2((mat * MT_Vector4(m_uv2[0], m_uv2[1], 0.0, 1.0)).getValue());
+}
diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h
index 889769da5ed..98ea4dd60aa 100644
--- a/source/gameengine/Rasterizer/RAS_TexVert.h
+++ b/source/gameengine/Rasterizer/RAS_TexVert.h
@@ -122,9 +122,11 @@ public:
}
void SetXYZ(const MT_Point3& xyz);
- void SetXYZ(const float *xyz);
- void SetUV(const MT_Point2& uv);
+ 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 SetRGBA(const unsigned int rgba);
void SetNormal(const MT_Vector3& normal);
@@ -137,6 +139,8 @@ 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);
// 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/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h
index 885eb8e1e90..6b57db1a467 100644
--- a/source/gameengine/SceneGraph/SG_IObject.h
+++ b/source/gameengine/SceneGraph/SG_IObject.h
@@ -127,8 +127,8 @@ struct SG_Callbacks
m_schedulefunc(NULL),
m_reschedulefunc(NULL)
{
- };
-
+ }
+
SG_Callbacks(
SG_ReplicationNewCallback repfunc,
SG_DestructionNewCallback destructfunc,
@@ -142,7 +142,7 @@ struct SG_Callbacks
m_schedulefunc(schedulefunc),
m_reschedulefunc(reschedulefunc)
{
- };
+ }
SG_ReplicationNewCallback m_replicafunc;
SG_DestructionNewCallback m_destructionfunc;
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
index 85857165403..2cc2cfb6bfc 100644
--- a/source/gameengine/VideoTexture/ImageRender.cpp
+++ b/source/gameengine/VideoTexture/ImageRender.cpp
@@ -375,7 +375,7 @@ static PyMethodDef imageRenderMethods[] =
static PyGetSetDef imageRenderGetSets[] =
{
{(char*)"background", (getter)getBackground, (setter)setBackground, (char*)"background color", NULL},
- // attribute from ImageViewport
+ // attribute from ImageViewport
{(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of render area", NULL},
{(char*)"alpha", (getter)ImageViewport_getAlpha, (setter)ImageViewport_setAlpha, (char*)"use alpha in texture", NULL},
{(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to render", NULL},