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.txt12
-rw-r--r--GNUmakefile4
-rw-r--r--SConstruct6
-rwxr-xr-xbuild_files/build_environment/install_deps.sh2
-rw-r--r--build_files/cmake/macros.cmake3
-rw-r--r--build_files/scons/tools/btools.py2
-rw-r--r--doc/python_api/examples/bpy.types.UIList.2.py2
-rw-r--r--extern/libmv/CMakeLists.txt8
-rw-r--r--extern/libmv/SConscript3
-rwxr-xr-xextern/libmv/bundle.sh11
-rw-r--r--extern/libmv/libmv-capi.cc53
-rw-r--r--extern/libmv/libmv-capi.h3
-rw-r--r--extern/libmv/libmv-capi_intern.h59
-rw-r--r--extern/libmv/libmv-capi_stub.cc4
-rw-r--r--extern/libmv/libmv/multiview/fundamental.cc91
-rw-r--r--extern/libmv/libmv/multiview/fundamental.h37
-rw-r--r--extern/libmv/libmv/multiview/homography.cc111
-rw-r--r--extern/libmv/libmv/multiview/homography.h39
-rw-r--r--extern/libmv/libmv/simple_pipeline/keyframe_selection.cc176
-rw-r--r--extern/libmv/third_party/msinttypes/stdint.h12
-rw-r--r--intern/cycles/blender/CMakeLists.txt2
-rw-r--r--intern/cycles/blender/addon/ui.py9
-rw-r--r--intern/cycles/blender/blender_mesh.cpp2
-rw-r--r--intern/cycles/blender/blender_shader.cpp7
-rw-r--r--intern/cycles/blender/blender_sync.cpp3
-rw-r--r--intern/cycles/device/device.cpp75
-rw-r--r--intern/cycles/device/device_cuda.cpp54
-rw-r--r--intern/cycles/device/device_opencl.cpp12
-rw-r--r--intern/cycles/kernel/CMakeLists.txt38
-rw-r--r--intern/cycles/kernel/SConscript34
-rw-r--r--intern/cycles/kernel/kernel_film.h4
-rw-r--r--intern/cycles/kernel/kernel_path.h85
-rw-r--r--intern/cycles/kernel/kernel_shader.h23
-rw-r--r--intern/cycles/kernel/kernel_sse2.cpp3
-rw-r--r--intern/cycles/kernel/kernel_sse3.cpp3
-rw-r--r--intern/cycles/kernel/kernel_subsurface.h159
-rw-r--r--intern/cycles/kernel/kernel_types.h12
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp2
-rw-r--r--intern/cycles/kernel/shaders/SConscript2
-rw-r--r--intern/cycles/kernel/shaders/node_environment_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_hair_bsdf.osl43
-rw-r--r--intern/cycles/kernel/shaders/node_sky_texture.osl12
-rw-r--r--intern/cycles/kernel/shaders/node_subsurface_scattering.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_ward_bsdf.osl2
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h19
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h3
-rw-r--r--intern/cycles/kernel/svm/svm_types.h3
-rw-r--r--intern/cycles/render/CMakeLists.txt2
-rw-r--r--intern/cycles/render/bssrdf.cpp134
-rw-r--r--intern/cycles/render/bssrdf.h29
-rw-r--r--intern/cycles/render/shader.cpp24
-rw-r--r--intern/cycles/render/shader.h1
-rw-r--r--intern/cycles/util/util_opengl.h5
-rw-r--r--intern/cycles/util/util_types.h5
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCocoa.mm5
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c71
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm8
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsX11.cpp9
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp80
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp61
-rw-r--r--intern/guardedalloc/CMakeLists.txt12
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h117
-rw-r--r--intern/guardedalloc/SConscript10
-rw-r--r--intern/guardedalloc/intern/mallocn.c1300
-rw-r--r--intern/guardedalloc/intern/mallocn_guarded_impl.c1114
-rw-r--r--intern/guardedalloc/intern/mallocn_intern.h132
-rw-r--r--intern/guardedalloc/intern/mallocn_lockfree_impl.c376
-rw-r--r--intern/guardedalloc/mmap_win.h2
-rw-r--r--intern/opencolorio/CMakeLists.txt2
-rw-r--r--intern/opencolorio/SConscript7
-rw-r--r--intern/opencolorio/fallback_impl.cc3
-rw-r--r--intern/opencolorio/gpu_shader_display_transform.glsl123
-rw-r--r--intern/opencolorio/ocio_capi.cc5
-rw-r--r--intern/opencolorio/ocio_capi.h59
-rw-r--r--intern/opencolorio/ocio_impl.cc53
-rw-r--r--intern/opencolorio/ocio_impl.h9
-rw-r--r--intern/opencolorio/ocio_impl_glsl.cc164
-rw-r--r--release/datafiles/splash.pngbin139754 -> 256816 bytes
-rw-r--r--release/scripts/modules/bpy/path.py1
-rw-r--r--release/scripts/modules/rna_info.py3
-rw-r--r--release/scripts/modules/rna_keymap_ui.py13
-rw-r--r--release/scripts/presets/keyconfig/maya.py6
-rw-r--r--release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py (renamed from release/scripts/presets/operator/wm.collada_export/second_life_rigged.py)2
-rw-r--r--release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py (renamed from release/scripts/presets/operator/wm.collada_export/second_life_static.py)2
-rw-r--r--release/scripts/startup/bl_operators/node.py7
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py4
-rw-r--r--release/scripts/startup/bl_operators/wm.py10
-rw-r--r--release/scripts/startup/bl_ui/properties_freestyle.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_mask_common.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py19
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py11
-rw-r--r--release/scripts/startup/bl_ui/space_image.py70
-rw-r--r--release/scripts/startup/bl_ui/space_node.py4
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py7
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py126
-rw-r--r--release/scripts/templates_py/custom_nodes.py2
-rw-r--r--release/scripts/templates_py/ui_list.py2
-rw-r--r--source/blender/CMakeLists.txt4
-rw-r--r--source/blender/SConscript3
-rw-r--r--source/blender/blenkernel/BKE_action.h4
-rw-r--r--source/blender/blenkernel/BKE_animsys.h3
-rw-r--r--source/blender/blenkernel/BKE_blender.h6
-rw-r--r--source/blender/blenkernel/BKE_curve.h3
-rw-r--r--source/blender/blenkernel/BKE_deform.h8
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h5
-rw-r--r--source/blender/blenkernel/BKE_mesh.h6
-rw-r--r--source/blender/blenkernel/BKE_node.h31
-rw-r--r--source/blender/blenkernel/BKE_subsurf.h4
-rw-r--r--source/blender/blenkernel/SConscript3
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c19
-rw-r--r--source/blender/blenkernel/intern/action.c16
-rw-r--r--source/blender/blenkernel/intern/anim.c2
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c71
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c2
-rw-r--r--source/blender/blenkernel/intern/colortools.c3
-rw-r--r--source/blender/blenkernel/intern/curve.c121
-rw-r--r--source/blender/blenkernel/intern/customdata.c9
-rw-r--r--source/blender/blenkernel/intern/deform.c115
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c13
-rw-r--r--source/blender/blenkernel/intern/fcurve.c64
-rw-r--r--source/blender/blenkernel/intern/freestyle.c3
-rw-r--r--source/blender/blenkernel/intern/idprop.c118
-rw-r--r--source/blender/blenkernel/intern/image.c6
-rw-r--r--source/blender/blenkernel/intern/library.c2
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c2
-rw-r--r--source/blender/blenkernel/intern/mesh.c91
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c23
-rw-r--r--source/blender/blenkernel/intern/movieclip.c1
-rw-r--r--source/blender/blenkernel/intern/multires.c16
-rw-r--r--source/blender/blenkernel/intern/node.c60
-rw-r--r--source/blender/blenkernel/intern/object.c4
-rw-r--r--source/blender/blenkernel/intern/paint.c4
-rw-r--r--source/blender/blenkernel/intern/particle.c8
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c36
-rw-r--r--source/blender/blenkernel/intern/scene.c13
-rw-r--r--source/blender/blenkernel/intern/sequencer.c5
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c2
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c10
-rw-r--r--source/blender/blenkernel/intern/texture.c12
-rw-r--r--source/blender/blenkernel/intern/tracking.c4
-rw-r--r--source/blender/blenlib/BLI_bitmap.h3
-rw-r--r--source/blender/blenlib/BLI_boxpack2d.h5
-rw-r--r--source/blender/blenlib/BLI_linklist_stack.h2
-rw-r--r--source/blender/blenlib/BLI_math_geom.h9
-rw-r--r--source/blender/blenlib/BLI_memarena.h2
-rw-r--r--source/blender/blenlib/BLI_mempool.h4
-rw-r--r--source/blender/blenlib/BLI_scanfill.h2
-rw-r--r--source/blender/blenlib/BLI_task.h108
-rw-r--r--source/blender/blenlib/BLI_threads.h32
-rw-r--r--source/blender/blenlib/CMakeLists.txt6
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c2
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c2
-rw-r--r--source/blender/blenlib/intern/BLI_memarena.c23
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c51
-rw-r--r--source/blender/blenlib/intern/boxpack2d.c41
-rw-r--r--source/blender/blenlib/intern/lasso.c2
-rw-r--r--source/blender/blenlib/intern/math_geom.c79
-rw-r--r--source/blender/blenlib/intern/math_rotation.c6
-rw-r--r--source/blender/blenlib/intern/noise.c24
-rw-r--r--source/blender/blenlib/intern/smallhash.c2
-rw-r--r--source/blender/blenlib/intern/task.c424
-rw-r--r--source/blender/blenlib/intern/threads.c114
-rw-r--r--source/blender/blenloader/intern/readfile.c88
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c27
-rw-r--r--source/blender/blenloader/intern/writefile.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c12
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c25
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c56
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h15
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c31
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c329
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c96
-rw-r--r--source/blender/bmesh/operators/bmo_bridge.c2
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c2
-rw-r--r--source/blender/bmesh/operators/bmo_connect_nonplanar.c2
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c68
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c2
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c8
-rw-r--r--source/blender/bmesh/operators/bmo_fill_attribute.c2
-rw-r--r--source/blender/bmesh/operators/bmo_fill_holes.c2
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c1
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c12
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c12
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c28
-rw-r--r--source/blender/bmesh/operators/bmo_symmetrize.c5
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c1
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c1
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c14
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.c6
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.c16
-rw-r--r--source/blender/collada/AnimationExporter.cpp4
-rw-r--r--source/blender/collada/ArmatureExporter.cpp8
-rw-r--r--source/blender/collada/ControllerExporter.cpp4
-rw-r--r--source/blender/collada/ExportSettings.h2
-rw-r--r--source/blender/collada/collada.cpp4
-rw-r--r--source/blender/collada/collada.h2
-rw-r--r--source/blender/collada/version.conf1
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cpp2
-rw-r--r--source/blender/editors/animation/anim_filter.c9
-rw-r--r--source/blender/editors/animation/anim_markers.c2
-rw-r--r--source/blender/editors/animation/keyframes_edit.c2
-rw-r--r--source/blender/editors/animation/keyframing.c82
-rw-r--r--source/blender/editors/armature/BIF_retarget.h4
-rw-r--r--source/blender/editors/armature/armature_naming.c28
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c46
-rw-r--r--source/blender/editors/armature/pose_lib.c2
-rw-r--r--source/blender/editors/curve/editcurve_add.c2
-rw-r--r--source/blender/editors/curve/editfont.c2
-rw-r--r--source/blender/editors/include/BIF_glutil.h3
-rw-r--r--source/blender/editors/include/ED_mask.h2
-rw-r--r--source/blender/editors/include/ED_mesh.h2
-rw-r--r--source/blender/editors/include/ED_render.h2
-rw-r--r--source/blender/editors/include/ED_transform.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h3
-rw-r--r--source/blender/editors/interface/CMakeLists.txt1
-rw-r--r--source/blender/editors/interface/interface.c8
-rw-r--r--source/blender/editors/interface/interface_draw.c6
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c642
-rw-r--r--source/blender/editors/interface/interface_handlers.c108
-rw-r--r--source/blender/editors/interface/interface_intern.h6
-rw-r--r--source/blender/editors/interface/interface_layout.c23
-rw-r--r--source/blender/editors/interface/interface_ops.c291
-rw-r--r--source/blender/editors/interface/interface_regions.c2
-rw-r--r--source/blender/editors/interface/view2d_ops.c6
-rw-r--r--source/blender/editors/io/io_collada.c12
-rw-r--r--source/blender/editors/mask/SConscript3
-rw-r--r--source/blender/editors/mask/mask_draw.c118
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c2
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c2
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c2
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c10
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c26
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c7
-rw-r--r--source/blender/editors/mesh/editmesh_select.c156
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c27
-rw-r--r--source/blender/editors/object/object_bake.c36
-rw-r--r--source/blender/editors/object/object_edit.c8
-rw-r--r--source/blender/editors/object/object_group.c4
-rw-r--r--source/blender/editors/object/object_hook.c4
-rw-r--r--source/blender/editors/object/object_vgroup.c33
-rw-r--r--source/blender/editors/physics/particle_edit.c8
-rw-r--r--source/blender/editors/render/render_internal.c4
-rw-r--r--source/blender/editors/render/render_opengl.c23
-rw-r--r--source/blender/editors/render/render_shading.c48
-rw-r--r--source/blender/editors/screen/glutil.c65
-rw-r--r--source/blender/editors/screen/screendump.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c77
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c55
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h2
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c11
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c8
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c41
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c3
-rw-r--r--source/blender/editors/space_clip/clip_editor.c14
-rw-r--r--source/blender/editors/space_clip/space_clip.c4
-rw-r--r--source/blender/editors/space_console/space_console.c1
-rw-r--r--source/blender/editors/space_file/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_file/SConscript3
-rw-r--r--source/blender/editors/space_file/file_intern.h2
-rw-r--r--source/blender/editors/space_file/file_ops.c4
-rw-r--r--source/blender/editors/space_file/file_panels.c2
-rw-r--r--source/blender/editors/space_file/space_file.c2
-rw-r--r--source/blender/editors/space_graph/graph_draw.c2
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_image/SConscript2
-rw-r--r--source/blender/editors/space_image/image_buttons.c2
-rw-r--r--source/blender/editors/space_image/image_draw.c12
-rw-r--r--source/blender/editors/space_image/image_ops.c5
-rw-r--r--source/blender/editors/space_image/space_image.c7
-rw-r--r--source/blender/editors/space_info/info_stats.c6
-rw-r--r--source/blender/editors/space_node/drawnode.c428
-rw-r--r--source/blender/editors/space_node/node_draw.c20
-rw-r--r--source/blender/editors/space_node/node_edit.c10
-rw-r--r--source/blender/editors/space_node/node_templates.c8
-rw-r--r--source/blender/editors/space_node/node_view.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c16
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c3
-rw-r--r--source/blender/editors/space_text/space_text.c2
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c1
-rw-r--r--source/blender/editors/space_text/text_ops.c10
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c16
-rw-r--r--source/blender/editors/space_view3d/drawobject.c4
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c20
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c30
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c16
-rw-r--r--source/blender/editors/transform/transform.c316
-rw-r--r--source/blender/editors/transform/transform.h7
-rw-r--r--source/blender/editors/transform/transform_conversions.c30
-rw-r--r--source/blender/editors/transform/transform_generics.c13
-rw-r--r--source/blender/editors/transform/transform_input.c18
-rw-r--r--source/blender/editors/transform/transform_manipulator.c17
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/editors/transform/transform_orientations.c38
-rw-r--r--source/blender/editors/transform/transform_snap.c3
-rw-r--r--source/blender/editors/util/ed_util.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c4
-rw-r--r--source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp14
-rw-r--r--source/blender/gpu/intern/gpu_material.c6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl14
-rw-r--r--source/blender/imbuf/CMakeLists.txt5
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h9
-rw-r--r--source/blender/imbuf/IMB_imbuf.h2
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h7
-rw-r--r--source/blender/imbuf/SConscript3
-rw-r--r--source/blender/imbuf/intern/IMB_filetype.h3
-rw-r--r--source/blender/imbuf/intern/colormanagement.c135
-rw-r--r--source/blender/imbuf/intern/filetype.c43
-rw-r--r--source/blender/imbuf/intern/indexer.c8
-rw-r--r--source/blender/imbuf/intern/oiio/CMakeLists.txt54
-rw-r--r--source/blender/imbuf/intern/oiio/SConscript49
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_api.cpp256
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_api.h53
-rw-r--r--source/blender/imbuf/intern/readimage.c134
-rw-r--r--source/blender/imbuf/intern/tiff.c8
-rw-r--r--source/blender/imbuf/intern/util.c23
-rw-r--r--source/blender/imbuf/intern/writeimage.c2
-rw-r--r--source/blender/makesdna/DNA_mask_types.h7
-rw-r--r--source/blender/makesdna/DNA_node_types.h29
-rw-r--r--source/blender/makesdna/DNA_scene_types.h52
-rw-r--r--source/blender/makesdna/DNA_space_types.h3
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt7
-rw-r--r--source/blender/makesdna/intern/SConscript2
-rw-r--r--source/blender/makesrna/RNA_define.h8
-rw-r--r--source/blender/makesrna/SConscript3
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt11
-rw-r--r--source/blender/makesrna/intern/SConscript5
-rw-r--r--source/blender/makesrna/intern/makesrna.c2
-rw-r--r--source/blender/makesrna/intern/rna_armature.c3
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c1
-rw-r--r--source/blender/makesrna/intern/rna_define.c9
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c12
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_meta.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c69
-rw-r--r--source/blender/makesrna/intern/rna_object.c16
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c6
-rw-r--r--source/blender/makesrna/intern/rna_pose.c10
-rw-r--r--source/blender/makesrna/intern/rna_render.c4
-rw-r--r--source/blender/makesrna/intern/rna_scene.c36
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c6
-rw-r--r--source/blender/makesrna/intern/rna_space.c37
-rw-r--r--source/blender/makesrna/intern/rna_texture.c10
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_scale.c19
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_gamma.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mapping.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_brick.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_checker.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_gradient.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_magic.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_noise.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_sky.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_wave.c2
-rw-r--r--source/blender/python/intern/CMakeLists.txt4
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.c9
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.h2
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.h2
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c6
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.h4
-rw-r--r--source/blender/render/extern/include/RE_multires_bake.h21
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h4
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h3
-rw-r--r--source/blender/render/intern/include/render_types.h2
-rw-r--r--source/blender/render/intern/source/bake.c204
-rw-r--r--source/blender/render/intern/source/convertblender.c15
-rw-r--r--source/blender/render/intern/source/imagetexture.c2
-rw-r--r--source/blender/render/intern/source/multires_bake.c15
-rw-r--r--source/blender/render/intern/source/pipeline.c4
-rw-r--r--source/blender/render/intern/source/pixelshading.c8
-rw-r--r--source/blender/render/intern/source/rendercore.c5
-rw-r--r--source/blender/render/intern/source/shadbuf.c15
-rw-r--r--source/blender/render/intern/source/shadeinput.c10
-rw-r--r--source/blender/render/intern/source/sss.c2
-rw-r--r--source/blender/render/intern/source/volume_precache.c210
-rw-r--r--source/blender/windowmanager/WM_api.h1
-rw-r--r--source/blender/windowmanager/WM_keymap.h2
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c4
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c2
-rw-r--r--source/blender/windowmanager/intern/wm_files.c5
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c96
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c5
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c22
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c9
-rw-r--r--source/blender/windowmanager/intern/wm_window.c10
-rw-r--r--source/blender/windowmanager/wm_subwindow.h1
-rw-r--r--source/blenderplayer/CMakeLists.txt1
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c1
-rw-r--r--source/creator/CMakeLists.txt1
-rw-r--r--source/creator/creator.c52
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp10
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp3
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RenderTools.cpp19
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp2
416 files changed, 8376 insertions, 5158 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index eed1d64459f..fbb7c17e64b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -203,6 +203,7 @@ option(WITH_MOD_REMESH "Enable Remesh Modifier" ON)
option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF)
# Image format support
+option(WITH_OPENIMAGEIO "Enable OpenImageIO Support (http://www.openimageio.org)" OFF)
option(WITH_IMAGE_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON)
option(WITH_IMAGE_OPENJPEG "Enable OpenJpeg Support (http://www.openjpeg.org)" ON)
option(WITH_IMAGE_TIFF "Enable LibTIFF Support" ON)
@@ -278,13 +279,14 @@ mark_as_advanced(LLVM_STATIC)
option(WITH_MEM_JEMALLOC "Enable malloc replacement (http://www.canonware.com/jemalloc)" OFF)
mark_as_advanced(WITH_MEM_JEMALLOC)
+# currently only used for BLI_mempool
+option(WITH_MEM_VALGRIND "Enable extended valgrind support for better reporting" OFF)
+mark_as_advanced(WITH_MEM_VALGRIND)
+
# Debug
option(WITH_CXX_GUARDEDALLOC "Enable GuardedAlloc for C++ memory allocation tracking (only enable for development)" OFF)
mark_as_advanced(WITH_CXX_GUARDEDALLOC)
-option(WITH_GUARDEDALLOC "Enable GuardedAlloc (DISABLE AT OWN RISK!)" ON)
-mark_as_advanced(WITH_GUARDEDALLOC)
-
option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" OFF)
mark_as_advanced(WITH_ASSERT_ABORT)
@@ -368,7 +370,7 @@ if(APPLE)
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
+ 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")
@@ -2281,10 +2283,12 @@ if(FIRST_RUN)
info_cfg_option(WITH_X11_XF86VMODE)
info_cfg_option(WITH_X11_XINPUT)
info_cfg_option(WITH_MEM_JEMALLOC)
+ info_cfg_option(WITH_MEM_VALGRIND)
info_cfg_option(WITH_SYSTEM_GLEW)
info_cfg_option(WITH_SYSTEM_OPENJPEG)
info_cfg_text("Image Formats:")
+ info_cfg_option(WITH_OPENIMAGEIO)
info_cfg_option(WITH_IMAGE_CINEON)
info_cfg_option(WITH_IMAGE_DDS)
info_cfg_option(WITH_IMAGE_HDR)
diff --git a/GNUmakefile b/GNUmakefile
index d5570a8e170..417ff7770ed 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -182,6 +182,7 @@ help:
@echo " * check_spelling_c_qtc - same as check_spelling_c but outputs QtCreator tasks format"
@echo " * check_spelling_osl - check for spelling errors (OSL only)"
@echo " * check_spelling_py - check for spelling errors (Python only)"
+ @echo " * check_descriptions - check for duplicate/invalid descriptions"
@echo ""
@echo "Utilities (not associated with building blender)"
@echo " * icons - updates PNG icons from SVG files."
@@ -313,6 +314,9 @@ check_spelling_c_qtc:
check_spelling_osl:
cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/intern/cycles/kernel/shaders
+check_descriptions:
+ $(BUILD_DIR)/bin/blender --background -noaudio --factory-startup --python $(BLENDER_DIR)/source/tools/check_descriptions.py
+
# -----------------------------------------------------------------------------
# Utilities
#
diff --git a/SConstruct b/SConstruct
index f95a2903db1..9f9eaa886a3 100644
--- a/SConstruct
+++ b/SConstruct
@@ -246,6 +246,7 @@ if 'blenderlite' in B.targets:
target_env_defs['WITH_BF_CYCLES'] = False
target_env_defs['WITH_BF_OPENAL'] = False
target_env_defs['WITH_BF_OPENEXR'] = False
+ target_env_defs['WITH_BF_PSD'] = False
target_env_defs['WITH_BF_OPENMP'] = False
target_env_defs['WITH_BF_ICONV'] = False
target_env_defs['WITH_BF_INTERNATIONAL'] = False
@@ -289,13 +290,13 @@ if env['OURPLATFORM']=='darwin':
print B.bc.OKGREEN + "Detected Xcode version: -- " + B.bc.ENDC + env['XCODE_CUR_VER'] + " --"
print "Available " + env['MACOSX_SDK_CHECK']
if not 'Mac OS X 10.6' in env['MACOSX_SDK_CHECK']:
- print B.bc.OKGREEN + "Auto-setting available MacOSX SDK -> " + B.bc.ENDC + "MacOSX10.7.sdk"
+ print B.bc.OKGREEN + "Building with user-defined OS X SDK ( Xcode 4.4 or newer )"
elif not 'Mac OS X 10.5' in env['MACOSX_SDK_CHECK']:
print B.bc.OKGREEN + "Auto-setting available MacOSX SDK -> " + B.bc.ENDC + "MacOSX10.6.sdk"
else:
print B.bc.OKGREEN + "Found recommended sdk :" + B.bc.ENDC + " using MacOSX10.5.sdk"
- if env['CXX'].startswith('clang') and env['XCODE_CUR_VER'] >= '5':
+ if env['XCODE_CUR_VER'] >= '5' and not (env['CXX'][:-2].endswith('4.6') or env['CXX'][:-2].endswith('4.8')):
env['CCFLAGS'].append('-ftemplate-depth=1024') # only valid for clang bundled with xcode 5
# for now, Mac builders must download and install the 3DxWare 10 Beta 4 driver framework from 3Dconnexion
@@ -551,6 +552,7 @@ if B.targets != ['cudakernels']:
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl")
+ data_to_c_simple("intern/opencolorio/gpu_shader_display_transform.glsl")
# --- blender ---
data_to_c_simple("release/datafiles/bfont.pfb")
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index 14e1baf4fd4..dc21f85e85c 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -3145,7 +3145,7 @@ print_info() {
fi
if $ALL_STATIC; then
- INFO "LLIB = ["xml2", "expat"] + LLIB"
+ INFO "LLIBS = [\""xml2"\", \""expat"\"] + LLIBS"
fi
INFO ""
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 7dac80ace51..9ded803f45b 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -585,7 +585,8 @@ endmacro()
macro(get_blender_version)
# So cmake depends on BKE_blender.h, beware of inf-loops!
- CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/source/blender/blenkernel/BKE_blender.h ${CMAKE_BINARY_DIR}/source/blender/blenkernel/BKE_blender.h.done)
+ CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/source/blender/blenkernel/BKE_blender.h
+ ${CMAKE_BINARY_DIR}/source/blender/blenkernel/BKE_blender.h.done)
file(STRINGS ${CMAKE_SOURCE_DIR}/source/blender/blenkernel/BKE_blender.h _contents REGEX "^#define[ \t]+BLENDER_.*$")
diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py
index 454e72a1a72..8f0d3ff590b 100644
--- a/build_files/scons/tools/btools.py
+++ b/build_files/scons/tools/btools.py
@@ -576,7 +576,7 @@ def read_opts(env, cfg, args):
('BF_CYCLES_CUDA_BINARIES_ARCH', 'CUDA architectures to compile binaries for', []),
(BoolVariable('WITH_BF_OIIO', 'Build with OpenImageIO', False)),
- (BoolVariable('WITH_BF_STATICOIIO', 'Staticly link to OpenImageIO', False)),
+ (BoolVariable('WITH_BF_STATICOIIO', 'Statically link to OpenImageIO', False)),
('BF_OIIO', 'OIIO root path', ''),
('BF_OIIO_INC', 'OIIO include path', ''),
('BF_OIIO_LIB', 'OIIO library', ''),
diff --git a/doc/python_api/examples/bpy.types.UIList.2.py b/doc/python_api/examples/bpy.types.UIList.2.py
index 3ffd099859a..4e30e6895d6 100644
--- a/doc/python_api/examples/bpy.types.UIList.2.py
+++ b/doc/python_api/examples/bpy.types.UIList.2.py
@@ -8,7 +8,7 @@ example of how to create/use filtering/reordering callbacks.
import bpy
-class MESH_UL_vgroups_slow(UIList):
+class MESH_UL_vgroups_slow(bpy.types.UIList):
# Constants (flags)
# Be careful not to shadow FILTER_ITEM!
VGROUP_EMPTY = 1 << 0
diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt
index 2c9a21965f0..80a212b64f8 100644
--- a/extern/libmv/CMakeLists.txt
+++ b/extern/libmv/CMakeLists.txt
@@ -32,15 +32,19 @@ set(INC
set(SRC
libmv-capi.h
+ libmv-capi_intern.h
)
if(WITH_LIBMV)
add_definitions(
-DWITH_LIBMV
+ -DWITH_LIBMV_GUARDED_ALLOC
+ -DGOOGLE_GLOG_DLL_DECL=
)
list(APPEND INC
third_party/ceres/include
+ ../../intern/guardedalloc
)
set(INC_SYS
@@ -224,10 +228,6 @@ if(WITH_LIBMV)
third_party/glog/src
)
endif()
-
- add_definitions(
- -DGOOGLE_GLOG_DLL_DECL=
- )
else()
list(APPEND SRC
libmv-capi_stub.cc
diff --git a/extern/libmv/SConscript b/extern/libmv/SConscript
index f422eb08c58..6926b36f335 100644
--- a/extern/libmv/SConscript
+++ b/extern/libmv/SConscript
@@ -15,6 +15,7 @@ incs = '.'
if env['WITH_BF_LIBMV']:
defs.append('GOOGLE_GLOG_DLL_DECL=')
defs.append('WITH_LIBMV')
+ defs.append('WITH_LIBMV_GUARDED_ALLOC')
src = env.Glob("libmv-capi.cc")
src += env.Glob('libmv/image/*.cc')
@@ -25,7 +26,7 @@ if env['WITH_BF_LIBMV']:
src += env.Glob('third_party/fast/*.c')
src += env.Glob('third_party/gflags/*.cc')
- incs += ' ../Eigen3 third_party/ceres/include'
+ incs += ' ../Eigen3 third_party/ceres/include ../../intern/guardedalloc'
incs += ' ' + env['BF_PNG_INC']
incs += ' ' + env['BF_ZLIB_INC']
diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh
index 16fb754d30a..57e3598a5ae 100755
--- a/extern/libmv/bundle.sh
+++ b/extern/libmv/bundle.sh
@@ -128,15 +128,19 @@ set(INC
set(SRC
libmv-capi.h
+ libmv-capi_intern.h
)
if(WITH_LIBMV)
add_definitions(
-DWITH_LIBMV
+ -DWITH_LIBMV_GUARDED_ALLOC
+ -DGOOGLE_GLOG_DLL_DECL=
)
list(APPEND INC
third_party/ceres/include
+ ../../intern/guardedalloc
)
set(INC_SYS
@@ -203,10 +207,6 @@ ${third_glog_headers}
third_party/glog/src
)
endif()
-
- add_definitions(
- -DGOOGLE_GLOG_DLL_DECL=
- )
else()
list(APPEND SRC
libmv-capi_stub.cc
@@ -238,11 +238,12 @@ incs = '.'
if env['WITH_BF_LIBMV']:
defs.append('GOOGLE_GLOG_DLL_DECL=')
defs.append('WITH_LIBMV')
+ defs.append('WITH_LIBMV_GUARDED_ALLOC')
src = env.Glob("libmv-capi.cc")
$src
- incs += ' ../Eigen3 third_party/ceres/include'
+ incs += ' ../Eigen3 third_party/ceres/include ../../intern/guardedalloc'
incs += ' ' + env['BF_PNG_INC']
incs += ' ' + env['BF_ZLIB_INC']
diff --git a/extern/libmv/libmv-capi.cc b/extern/libmv/libmv-capi.cc
index a8f396d5df1..11608318a40 100644
--- a/extern/libmv/libmv-capi.cc
+++ b/extern/libmv/libmv-capi.cc
@@ -43,10 +43,10 @@
# include <png.h>
#endif
+#include "libmv-capi_intern.h"
#include "libmv/logging/logging.h"
-
+#include "libmv/multiview/homography.h"
#include "libmv/tracking/track_region.h"
-
#include "libmv/simple_pipeline/callbacks.h"
#include "libmv/simple_pipeline/tracks.h"
#include "libmv/simple_pipeline/initialize_reconstruction.h"
@@ -58,12 +58,6 @@
#include "libmv/simple_pipeline/reconstruction_scale.h"
#include "libmv/simple_pipeline/keyframe_selection.h"
-#include "libmv/multiview/homography.h"
-
-#ifdef _MSC_VER
-# define snprintf _snprintf
-#endif
-
struct libmv_Reconstruction {
libmv::EuclideanReconstruction reconstruction;
@@ -388,14 +382,15 @@ void libmv_samplePlanarPatch(const float *image, int width, int height,
struct libmv_Tracks *libmv_tracksNew(void)
{
- libmv::Tracks *libmv_tracks = new libmv::Tracks();
+ libmv::Tracks *libmv_tracks = LIBMV_OBJECT_NEW(libmv::Tracks);
return (struct libmv_Tracks *)libmv_tracks;
}
void libmv_tracksDestroy(struct libmv_Tracks *libmv_tracks)
{
- delete (libmv::Tracks*) libmv_tracks;
+ using libmv::Tracks;
+ LIBMV_OBJECT_DELETE(libmv_tracks, Tracks);
}
void libmv_tracksInsert(struct libmv_Tracks *libmv_tracks, int image, int track, double x, double y)
@@ -578,7 +573,7 @@ struct libmv_Reconstruction *libmv_solveReconstruction(const struct libmv_Tracks
reconstruct_progress_update_cb progress_update_callback,
void *callback_customdata)
{
- struct libmv_Reconstruction *libmv_reconstruction = new libmv_Reconstruction();
+ struct libmv_Reconstruction *libmv_reconstruction = LIBMV_OBJECT_NEW(libmv_Reconstruction);
libmv::Tracks &tracks = *((libmv::Tracks *) libmv_tracks);
libmv::EuclideanReconstruction &reconstruction = libmv_reconstruction->reconstruction;
@@ -660,7 +655,7 @@ struct libmv_Reconstruction *libmv_solveModal(const struct libmv_Tracks *libmv_t
reconstruct_progress_update_cb progress_update_callback,
void *callback_customdata)
{
- struct libmv_Reconstruction *libmv_reconstruction = new libmv_Reconstruction();
+ struct libmv_Reconstruction *libmv_reconstruction = LIBMV_OBJECT_NEW(libmv_Reconstruction);
libmv::Tracks &tracks = *((libmv::Tracks *) libmv_tracks);
libmv::EuclideanReconstruction &reconstruction = libmv_reconstruction->reconstruction;
@@ -703,7 +698,7 @@ struct libmv_Reconstruction *libmv_solveModal(const struct libmv_Tracks *libmv_t
void libmv_reconstructionDestroy(struct libmv_Reconstruction *libmv_reconstruction)
{
- delete libmv_reconstruction;
+ LIBMV_OBJECT_DELETE(libmv_reconstruction, libmv_Reconstruction);
}
int libmv_reprojectionPointForTrack(const struct libmv_Reconstruction *libmv_reconstruction, int track, double pos[3])
@@ -850,7 +845,7 @@ struct libmv_Features *libmv_detectFeaturesFAST(const unsigned char *data,
{
libmv::Feature *features = NULL;
std::vector<libmv::Feature> v;
- struct libmv_Features *libmv_features = new libmv_Features();
+ struct libmv_Features *libmv_features = LIBMV_STRUCT_NEW(libmv_Features, 1);
int i = 0, count;
if (margin) {
@@ -864,7 +859,7 @@ struct libmv_Features *libmv_detectFeaturesFAST(const unsigned char *data,
count = v.size();
if (count) {
- features = new libmv::Feature[count];
+ features = LIBMV_STRUCT_NEW(libmv::Feature, count);
for(std::vector<libmv::Feature>::iterator it = v.begin(); it != v.end(); it++) {
features[i++] = *it;
@@ -883,7 +878,7 @@ struct libmv_Features *libmv_detectFeaturesMORAVEC(const unsigned char *data,
int margin, int count, int min_distance)
{
libmv::Feature *features = NULL;
- struct libmv_Features *libmv_features = new libmv_Features;
+ struct libmv_Features *libmv_features = LIBMV_STRUCT_NEW(libmv_Features, 1);
if (count) {
if (margin) {
@@ -892,7 +887,7 @@ struct libmv_Features *libmv_detectFeaturesMORAVEC(const unsigned char *data,
height -= 2 * margin;
}
- features = new libmv::Feature[count];
+ features = LIBMV_STRUCT_NEW(libmv::Feature, count);
libmv::DetectMORAVEC(data, stride, width, height, features, &count, min_distance, NULL);
}
@@ -905,10 +900,11 @@ struct libmv_Features *libmv_detectFeaturesMORAVEC(const unsigned char *data,
void libmv_featuresDestroy(struct libmv_Features *libmv_features)
{
- if (libmv_features->features)
- delete [] libmv_features->features;
+ if (libmv_features->features) {
+ LIBMV_STRUCT_DELETE(libmv_features->features);
+ }
- delete libmv_features;
+ LIBMV_STRUCT_DELETE(libmv_features);
}
int libmv_countFeatures(const struct libmv_Features *libmv_features)
@@ -930,14 +926,14 @@ void libmv_getFeature(const struct libmv_Features *libmv_features, int number, d
struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsNewEmpty(void)
{
- libmv::CameraIntrinsics *camera_intrinsics = new libmv::CameraIntrinsics();
+ libmv::CameraIntrinsics *camera_intrinsics = LIBMV_OBJECT_NEW(libmv::CameraIntrinsics);
return (struct libmv_CameraIntrinsics *) camera_intrinsics;
}
struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options)
{
- libmv::CameraIntrinsics *camera_intrinsics = new libmv::CameraIntrinsics();
+ libmv::CameraIntrinsics *camera_intrinsics = LIBMV_OBJECT_NEW(libmv::CameraIntrinsics);
cameraIntrinsicsFromOptions(libmv_camera_intrinsics_options, camera_intrinsics);
@@ -947,16 +943,15 @@ struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(const libmv_CameraIntri
struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(const libmv_CameraIntrinsics *libmvIntrinsics)
{
libmv::CameraIntrinsics *orig_intrinsics = (libmv::CameraIntrinsics *) libmvIntrinsics;
- libmv::CameraIntrinsics *new_intrinsics = new libmv::CameraIntrinsics(*orig_intrinsics);
+ libmv::CameraIntrinsics *new_intrinsics = LIBMV_OBJECT_NEW(libmv::CameraIntrinsics, *orig_intrinsics);
return (struct libmv_CameraIntrinsics *) new_intrinsics;
}
void libmv_cameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmvIntrinsics)
{
- libmv::CameraIntrinsics *intrinsics = (libmv::CameraIntrinsics *) libmvIntrinsics;
-
- delete intrinsics;
+ using libmv::CameraIntrinsics;
+ LIBMV_OBJECT_DELETE(libmvIntrinsics, CameraIntrinsics);
}
void libmv_cameraIntrinsicsUpdate(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options,
@@ -1082,8 +1077,7 @@ void libmv_cameraIntrinsicsInvert(const libmv_CameraIntrinsicsOptions *libmv_cam
}
}
-void libmv_homography2DFromCorrespondencesLinear(double (*x1)[2], double (*x2)[2], int num_points,
- double H[3][3], double expected_precision)
+void libmv_homography2DFromCorrespondencesEuc(double (*x1)[2], double (*x2)[2], int num_points, double H[3][3])
{
libmv::Mat x1_mat, x2_mat;
libmv::Mat3 H_mat;
@@ -1099,7 +1093,8 @@ void libmv_homography2DFromCorrespondencesLinear(double (*x1)[2], double (*x2)[2
LG << "x1: " << x1_mat;
LG << "x2: " << x2_mat;
- libmv::Homography2DFromCorrespondencesLinear(x1_mat, x2_mat, &H_mat, expected_precision);
+ libmv::HomographyEstimationOptions options;
+ libmv::Homography2DFromCorrespondencesEuc(x1_mat, x2_mat, options, &H_mat);
LG << "H: " << H_mat;
diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h
index 37aab2465ed..a872eeb60a1 100644
--- a/extern/libmv/libmv-capi.h
+++ b/extern/libmv/libmv-capi.h
@@ -159,8 +159,7 @@ void libmv_cameraIntrinsicsApply(const libmv_CameraIntrinsicsOptions *libmv_came
void libmv_cameraIntrinsicsInvert(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options,
double x, double y, double *x1, double *y1);
-void libmv_homography2DFromCorrespondencesLinear(double (*x1)[2], double (*x2)[2], int num_points,
- double H[3][3], double expected_precision);
+void libmv_homography2DFromCorrespondencesEuc(double (*x1)[2], double (*x2)[2], int num_points, double H[3][3]);
#ifdef __cplusplus
}
diff --git a/extern/libmv/libmv-capi_intern.h b/extern/libmv/libmv-capi_intern.h
new file mode 100644
index 00000000000..90087c52a6c
--- /dev/null
+++ b/extern/libmv/libmv-capi_intern.h
@@ -0,0 +1,59 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_INTERN_H
+#define LIBMV_C_API_INTERN_H
+
+#if defined(_MSC_VER)
+# define __func__ __FUNCTION__
+# define snprintf _snprintf
+#endif
+
+#ifdef WITH_LIBMV_GUARDED_ALLOC
+# include "MEM_guardedalloc.h"
+# define LIBMV_OBJECT_NEW OBJECT_GUARDED_NEW
+# define LIBMV_OBJECT_DELETE OBJECT_GUARDED_DELETE
+# define LIBMV_OBJECT_DELETE OBJECT_GUARDED_DELETE
+# define LIBMV_STRUCT_NEW(type, count) (type*)MEM_mallocN(sizeof(type) * count, __func__)
+# define LIBMV_STRUCT_DELETE(what) MEM_freeN(what)
+#else
+// Need this to keep libmv-capi potentially standalone.
+# if defined __GNUC__ || defined __sun
+# define LIBMV_OBJECT_NEW(type, args ...) \
+ new(malloc(sizeof(type))) type(args)
+# else
+# define LIBMV_OBJECT_NEW(type, ...) \
+ new(malloc(sizeof(type))) type(__VA_ARGS__)
+#endif
+# define LIBMV_OBJECT_DELETE(what, type) \
+ { if(what) { \
+ ((type*)(what))->~type(); \
+ free(what); \
+ } } (void)0
+# define LIBMV_STRUCT_NEW(type, count) (type*)malloc(sizeof(type) * count)
+# define LIBMV_STRUCT_DELETE(what) { if (what) free(what); } (void)0
+#endif
+
+#endif // LIBMV_C_API_INTERN_H
diff --git a/extern/libmv/libmv-capi_stub.cc b/extern/libmv/libmv-capi_stub.cc
index 4896f4c6949..e6d3753961b 100644
--- a/extern/libmv/libmv-capi_stub.cc
+++ b/extern/libmv/libmv-capi_stub.cc
@@ -277,8 +277,8 @@ void libmv_cameraIntrinsicsInvert(const libmv_CameraIntrinsicsOptions *libmv_cam
*y1 = (y - principal_y) / focal_length;
}
-void libmv_homography2DFromCorrespondencesLinear(double (* /* x1 */)[2], double (* /* x2 */)[2], int /* num_points */,
- double H[3][3], double /* expected_precision */)
+void libmv_homography2DFromCorrespondencesEuc(double (* /* x1 */)[2], double (* /* x2 */)[2], int /* num_points */,
+ double H[3][3])
{
memset(H, 0, sizeof(double[3][3]));
H[0][0] = 1.0f;
diff --git a/extern/libmv/libmv/multiview/fundamental.cc b/extern/libmv/libmv/multiview/fundamental.cc
index a05ef7907a2..ec6c70d81cf 100644
--- a/extern/libmv/libmv/multiview/fundamental.cc
+++ b/extern/libmv/libmv/multiview/fundamental.cc
@@ -20,6 +20,7 @@
#include "libmv/multiview/fundamental.h"
+#include "ceres/ceres.h"
#include "libmv/logging/logging.h"
#include "libmv/numeric/numeric.h"
#include "libmv/numeric/poly.h"
@@ -407,4 +408,94 @@ void FundamentalToEssential(const Mat3 &F, Mat3 *E) {
*E = svd.matrixU() * diag.asDiagonal() * svd.matrixV().transpose();
}
+FundamentalEstimationOptions::FundamentalEstimationOptions(void) :
+ use_refine_if_algebraic_fails(true),
+ max_num_iterations(50),
+ parameter_tolerance(1e-16),
+ function_tolerance(1e-16) {
+}
+
+class FundamentalSymmetricEpipolarCostFunctor {
+ public:
+ FundamentalSymmetricEpipolarCostFunctor(const Vec2 &x,
+ const Vec2 &y)
+ : x_(x), y_(y) {}
+
+ template<typename T>
+ bool operator()(const T *fundamental_parameters, T *residuals) const {
+ typedef Eigen::Matrix<T, 3, 3> Mat3;
+ typedef Eigen::Matrix<T, 3, 1> Vec3;
+
+ Mat3 F(fundamental_parameters);
+
+ Vec3 x(T(x_(0)), T(x_(1)), T(1.0));
+ Vec3 y(T(y_(0)), T(y_(1)), T(1.0));
+
+ Vec3 F_x = F * x;
+ Vec3 Ft_y = F.transpose() * y;
+ T y_F_x = y.dot(F_x);
+
+ residuals[0] = y_F_x * T(1) / F_x.head(2).norm();
+ residuals[1] = y_F_x * T(1) / Ft_y.head(2).norm();
+
+ return true;
+ }
+
+ const Mat x_;
+ const Mat y_;
+};
+
+/* Fundamental transformation estimation. */
+bool FundamentalFromCorrespondencesEuc(
+ const Mat &x1,
+ const Mat &x2,
+ const FundamentalEstimationOptions &options,
+ Mat3 *F) {
+ // Step 1: Algebraic fundamental estimation.
+ bool algebraic_success = NormalizedEightPointSolver(x1, x2, F);
+
+ LG << "Algebraic result " << algebraic_success
+ << ", estimated matrix:\n" << *F;
+
+ if (!algebraic_success && !options.use_refine_if_algebraic_fails) {
+ return false;
+ }
+
+ // Step 2: Refine matrix using Ceres minimizer.
+ ceres::Problem problem;
+ for (int i = 0; i < x1.cols(); i++) {
+ FundamentalSymmetricEpipolarCostFunctor
+ *fundamental_symmetric_epipolar_cost_function =
+ new FundamentalSymmetricEpipolarCostFunctor(x1.col(i),
+ x2.col(i));
+
+ problem.AddResidualBlock(
+ new ceres::AutoDiffCostFunction<
+ FundamentalSymmetricEpipolarCostFunctor,
+ 2, // num_residuals
+ 9>(fundamental_symmetric_epipolar_cost_function),
+ NULL,
+ F->data());
+ }
+
+ // Configure the solve.
+ ceres::Solver::Options solver_options;
+ solver_options.linear_solver_type = ceres::DENSE_QR;
+ solver_options.max_num_iterations = options.max_num_iterations;
+ solver_options.update_state_every_iteration = true;
+ solver_options.parameter_tolerance = options.parameter_tolerance;
+ solver_options.function_tolerance = options.function_tolerance;
+
+ // Run the solve.
+ ceres::Solver::Summary summary;
+ ceres::Solve(solver_options, &problem, &summary);
+
+ VLOG(1) << "Summary:\n" << summary.FullReport();
+
+ LG << "Final refined matrix:\n" << *F;
+
+ return !(summary.termination_type == ceres::DID_NOT_RUN ||
+ summary.termination_type == ceres::NUMERICAL_FAILURE);
+}
+
} // namespace libmv
diff --git a/extern/libmv/libmv/multiview/fundamental.h b/extern/libmv/libmv/multiview/fundamental.h
index 1ad184d8314..2961a46cdc4 100644
--- a/extern/libmv/libmv/multiview/fundamental.h
+++ b/extern/libmv/libmv/multiview/fundamental.h
@@ -144,6 +144,43 @@ bool MotionFromEssentialAndCorrespondence(const Mat3 &E,
*/
void FundamentalToEssential(const Mat3 &F, Mat3 *E);
+/**
+ * This structure contains options that controls how the fundamental
+ * estimation operates.
+ *
+ * Defaults should be suitable for a wide range of use cases, but
+ * better performance and accuracy might require tweaking/
+ */
+struct FundamentalEstimationOptions {
+ // Default constructor which sets up a options for generic usage.
+ FundamentalEstimationOptions(void);
+
+ // Refine fundamental matrix even if algebraic estimation reported failure.
+ bool use_refine_if_algebraic_fails;
+
+ // Maximal number of iterations for refinement step.
+ int max_num_iterations;
+
+ // Paramaneter tolerance used by minimizer termination criteria.
+ float parameter_tolerance;
+
+ // Function tolerance used by minimizer termination criteria.
+ float function_tolerance;
+};
+
+/**
+ * Fundamental transformation estimation.
+ *
+ * This function estimates the fundamental transformation from a list of 2D
+ * correspondences by doing algebraic estimation first followed with result
+ * refinement.
+ */
+bool FundamentalFromCorrespondencesEuc(
+ const Mat &x1,
+ const Mat &x2,
+ const FundamentalEstimationOptions &options,
+ Mat3 *F);
+
} // namespace libmv
#endif // LIBMV_MULTIVIEW_FUNDAMENTAL_H_
diff --git a/extern/libmv/libmv/multiview/homography.cc b/extern/libmv/libmv/multiview/homography.cc
index 317eb3f85c6..6041849d9fe 100644
--- a/extern/libmv/libmv/multiview/homography.cc
+++ b/extern/libmv/libmv/multiview/homography.cc
@@ -20,6 +20,7 @@
#include "libmv/multiview/homography.h"
+#include "ceres/ceres.h"
#include "libmv/logging/logging.h"
#include "libmv/multiview/homography_parameterization.h"
@@ -153,6 +154,116 @@ bool Homography2DFromCorrespondencesLinear(const Mat &x1,
return false;
}
}
+
+HomographyEstimationOptions::HomographyEstimationOptions(void) :
+ expected_algebraic_precision(EigenDouble::dummy_precision()),
+ use_refine_if_algebraic_fails(true),
+ max_num_iterations(50),
+ parameter_tolerance(1e-16),
+ function_tolerance(1e-16) {
+}
+
+class HomographySymmetricGeometricCostFunctor {
+ public:
+ HomographySymmetricGeometricCostFunctor(const Vec2 &x,
+ const Vec2 &y)
+ : x_(x), y_(y) { }
+
+ template<typename T>
+ bool operator()(const T *homography_parameters, T *residuals) const {
+ typedef Eigen::Matrix<T, 3, 3> Mat3;
+ typedef Eigen::Matrix<T, 3, 1> Vec3;
+
+ Mat3 H(homography_parameters);
+
+ Vec3 x(T(x_(0)), T(x_(1)), T(1.0));
+ Vec3 y(T(y_(0)), T(y_(1)), T(1.0));
+
+ Vec3 H_x = H * x;
+ Vec3 Hinv_y = H.inverse() * y;
+
+ H_x /= H_x(2);
+ Hinv_y /= Hinv_y(2);
+
+ // This is a forward error.
+ residuals[0] = H_x(0) - T(y_(0));
+ residuals[1] = H_x(1) - T(y_(1));
+
+ // This is a backward error.
+ residuals[2] = Hinv_y(0) - T(x_(0));
+ residuals[3] = Hinv_y(1) - T(x_(1));
+
+ return true;
+ }
+
+ const Vec2 x_;
+ const Vec2 y_;
+};
+
+/** 2D Homography transformation estimation in the case that points are in
+ * euclidean coordinates.
+ */
+bool Homography2DFromCorrespondencesEuc(
+ const Mat &x1,
+ const Mat &x2,
+ const HomographyEstimationOptions &options,
+ Mat3 *H) {
+ // TODO(sergey): Support homogenous coordinates, not just euclidean.
+
+ assert(2 == x1.rows());
+ assert(4 <= x1.cols());
+ assert(x1.rows() == x2.rows());
+ assert(x1.cols() == x2.cols());
+
+ // Step 1: Algebraic homography estimation.
+ bool algebraic_success =
+ Homography2DFromCorrespondencesLinear(x1, x2, H,
+ options.expected_algebraic_precision);
+
+ LG << "Algebraic result " << algebraic_success
+ << ", estimated matrix:\n" << *H;
+
+ if (!algebraic_success && !options.use_refine_if_algebraic_fails) {
+ return false;
+ }
+
+ // Step 2: Refine matrix using Ceres minimizer.
+ ceres::Problem problem;
+ for (int i = 0; i < x1.cols(); i++) {
+ HomographySymmetricGeometricCostFunctor
+ *homography_symmetric_geometric_cost_function =
+ new HomographySymmetricGeometricCostFunctor(x1.col(i),
+ x2.col(i));
+
+ problem.AddResidualBlock(
+ new ceres::AutoDiffCostFunction<
+ HomographySymmetricGeometricCostFunctor,
+ 4, // num_residuals
+ 9>(homography_symmetric_geometric_cost_function),
+ NULL,
+ H->data());
+ }
+
+ // Configure the solve.
+ ceres::Solver::Options solver_options;
+ solver_options.linear_solver_type = ceres::DENSE_QR;
+ solver_options.max_num_iterations = options.max_num_iterations;
+ solver_options.update_state_every_iteration = true;
+ solver_options.parameter_tolerance = options.parameter_tolerance;
+ solver_options.function_tolerance = options.function_tolerance;
+
+ // Run the solve.
+ ceres::Solver::Summary summary;
+ ceres::Solve(solver_options, &problem, &summary);
+
+ VLOG(1) << "Summary:\n" << summary.FullReport();
+
+ LG << "Final refined matrix:\n" << *H;
+
+ return !(summary.termination_type == ceres::DID_NOT_RUN ||
+ summary.termination_type == ceres::NUMERICAL_FAILURE);
+}
+
/**
* x2 ~ A * x1
* x2^t * Hi * A *x1 = 0
diff --git a/extern/libmv/libmv/multiview/homography.h b/extern/libmv/libmv/multiview/homography.h
index 8d2dff930eb..1928e39dffb 100644
--- a/extern/libmv/libmv/multiview/homography.h
+++ b/extern/libmv/libmv/multiview/homography.h
@@ -54,6 +54,45 @@ bool Homography2DFromCorrespondencesLinear(const Mat &x1,
EigenDouble::dummy_precision());
/**
+ * This structure contains options that controls how the homography
+ * estimation operates.
+ *
+ * Defaults should be suitable for a wide range of use cases, but
+ * better performance and accuracy might require tweaking/
+ */
+struct HomographyEstimationOptions {
+ // Default constructor which sets up a options for generic usage.
+ HomographyEstimationOptions(void);
+
+ // Expected precision of algebraic estimation.
+ double expected_algebraic_precision;
+
+ // Refine homography even if algebraic estimation reported failure.
+ bool use_refine_if_algebraic_fails;
+
+ // Maximal number of iterations for refinement step.
+ int max_num_iterations;
+
+ // Paramaneter tolerance used by minimizer termination criteria.
+ float parameter_tolerance;
+
+ // Function tolerance used by minimizer termination criteria.
+ float function_tolerance;
+};
+
+/**
+ * 2D homography transformation estimation.
+ *
+ * This function estimates the homography transformation from a list of 2D
+ * correspondences by doing algebraic estimation first followed with result
+ * refinement.
+ */
+bool Homography2DFromCorrespondencesEuc(const Mat &x1,
+ const Mat &x2,
+ const HomographyEstimationOptions &options,
+ Mat3 *H);
+
+/**
* 3D Homography transformation estimation.
*
* This function can be used in order to estimate the homography transformation
diff --git a/extern/libmv/libmv/simple_pipeline/keyframe_selection.cc b/extern/libmv/libmv/simple_pipeline/keyframe_selection.cc
index 976adb288b3..d4ddee56fda 100644
--- a/extern/libmv/libmv/simple_pipeline/keyframe_selection.cc
+++ b/extern/libmv/libmv/simple_pipeline/keyframe_selection.cc
@@ -61,161 +61,6 @@ Mat3 IntrinsicsNormalizationMatrix(const CameraIntrinsics &intrinsics) {
return S * T;
}
-class HomographySymmetricGeometricCostFunctor {
- public:
- HomographySymmetricGeometricCostFunctor(const Vec2 &x,
- const Vec2 &y)
- : x_(x), y_(y) { }
-
- template<typename T>
- bool operator()(const T *homography_parameters, T *residuals) const {
- typedef Eigen::Matrix<T, 3, 3> Mat3;
- typedef Eigen::Matrix<T, 3, 1> Vec3;
-
- Mat3 H(homography_parameters);
-
- Vec3 x(T(x_(0)), T(x_(1)), T(1.0));
- Vec3 y(T(y_(0)), T(y_(1)), T(1.0));
-
- Vec3 H_x = H * x;
- Vec3 Hinv_y = H.inverse() * y;
-
- H_x /= H_x(2);
- Hinv_y /= Hinv_y(2);
-
- residuals[0] = H_x(0) - T(y_(0));
- residuals[1] = H_x(1) - T(y_(1));
-
- residuals[2] = Hinv_y(0) - T(x_(0));
- residuals[3] = Hinv_y(1) - T(x_(1));
-
- return true;
- }
-
- const Vec2 x_;
- const Vec2 y_;
-};
-
-void ComputeHomographyFromCorrespondences(const Mat &x1, const Mat &x2,
- CameraIntrinsics &intrinsics,
- Mat3 *H) {
- // Algebraic homography estimation, happens with normalized coordinates
- Homography2DFromCorrespondencesLinear(x1, x2, H, 1e-12);
-
- // Refine matrix using Ceres minimizer
-
- // TODO(sergey): look into refinement in pixel space.
- ceres::Problem problem;
-
- for (int i = 0; i < x1.cols(); i++) {
- HomographySymmetricGeometricCostFunctor
- *homography_symmetric_geometric_cost_function =
- new HomographySymmetricGeometricCostFunctor(x1.col(i),
- x2.col(i));
-
- problem.AddResidualBlock(
- new ceres::AutoDiffCostFunction<
- HomographySymmetricGeometricCostFunctor,
- 4, /* num_residuals */
- 9>(homography_symmetric_geometric_cost_function),
- NULL,
- H->data());
- }
-
- // Configure the solve.
- ceres::Solver::Options solver_options;
- solver_options.linear_solver_type = ceres::DENSE_QR;
- solver_options.max_num_iterations = 50;
- solver_options.update_state_every_iteration = true;
- solver_options.parameter_tolerance = 1e-16;
- solver_options.function_tolerance = 1e-16;
-
- // Run the solve.
- ceres::Solver::Summary summary;
- ceres::Solve(solver_options, &problem, &summary);
-
- VLOG(1) << "Summary:\n" << summary.FullReport();
-
- // Convert homography to original pixel space
- Mat3 N = IntrinsicsNormalizationMatrix(intrinsics);
- *H = N.inverse() * (*H) * N;
-}
-
-class FundamentalSymmetricEpipolarCostFunctor {
- public:
- FundamentalSymmetricEpipolarCostFunctor(const Vec2 &x,
- const Vec2 &y)
- : x_(x), y_(y) {}
-
- template<typename T>
- bool operator()(const T *fundamental_parameters, T *residuals) const {
- typedef Eigen::Matrix<T, 3, 3> Mat3;
- typedef Eigen::Matrix<T, 3, 1> Vec3;
-
- Mat3 F(fundamental_parameters);
-
- Vec3 x(T(x_(0)), T(x_(1)), T(1.0));
- Vec3 y(T(y_(0)), T(y_(1)), T(1.0));
-
- Vec3 F_x = F * x;
- Vec3 Ft_y = F.transpose() * y;
- T y_F_x = y.dot(F_x);
-
- residuals[0] = y_F_x * T(1) / F_x.head(2).norm();
- residuals[1] = y_F_x * T(1) / Ft_y.head(2).norm();
-
- return true;
- }
-
- const Mat x_;
- const Mat y_;
-};
-
-void ComputeFundamentalFromCorrespondences(const Mat &x1, const Mat &x2,
- CameraIntrinsics &intrinsics,
- Mat3 *F) {
- // Algebraic fundamental estimation, happens with normalized coordinates
- NormalizedEightPointSolver(x1, x2, F);
-
- // Refine matrix using Ceres minimizer
-
- // TODO(sergey): look into refinement in pixel space.
- ceres::Problem problem;
-
- for (int i = 0; i < x1.cols(); i++) {
- FundamentalSymmetricEpipolarCostFunctor
- *fundamental_symmetric_epipolar_cost_function =
- new FundamentalSymmetricEpipolarCostFunctor(x1.col(i),
- x2.col(i));
-
- problem.AddResidualBlock(
- new ceres::AutoDiffCostFunction<
- FundamentalSymmetricEpipolarCostFunctor,
- 2, /* num_residuals */
- 9>(fundamental_symmetric_epipolar_cost_function),
- NULL,
- F->data());
- }
-
- // Configure the solve.
- ceres::Solver::Options solver_options;
- solver_options.linear_solver_type = ceres::DENSE_NORMAL_CHOLESKY;
- solver_options.max_num_iterations = 50;
- solver_options.update_state_every_iteration = true;
- solver_options.parameter_tolerance = 1e-16;
- solver_options.function_tolerance = 1e-16;
-
- // Run the solve.
- ceres::Solver::Summary summary;
- ceres::Solve(solver_options, &problem, &summary);
-
- VLOG(1) << "Summary:\n" << summary.FullReport();
-
- // Convert fundamental to original pixel space
- Mat3 N = IntrinsicsNormalizationMatrix(intrinsics);
- *F = N.inverse() * (*F) * N;
-}
-
// P.H.S. Torr
// Geometric Motion Segmentation and Model Selection
//
@@ -360,8 +205,25 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &tracks,
continue;
Mat3 H, F;
- ComputeHomographyFromCorrespondences(x1, x2, intrinsics, &H);
- ComputeFundamentalFromCorrespondences(x1, x2, intrinsics, &F);
+
+ // Estimate homography using default options.
+ HomographyEstimationOptions homography_estimation_options;
+ Homography2DFromCorrespondencesEuc(x1,
+ x2,
+ homography_estimation_options,
+ &H);
+
+ // Convert homography to original pixel space.
+ H = N_inverse * H * N;
+
+ FundamentalEstimationOptions fundamental_estimation_options;
+ FundamentalFromCorrespondencesEuc(x1,
+ x2,
+ fundamental_estimation_options,
+ &F);
+
+ // Convert fundamental to original pixel space.
+ F = N_inverse * F * N;
// TODO(sergey): STEP 2: Discard outlier matches
diff --git a/extern/libmv/third_party/msinttypes/stdint.h b/extern/libmv/third_party/msinttypes/stdint.h
index e236bb00015..189ee34571c 100644
--- a/extern/libmv/third_party/msinttypes/stdint.h
+++ b/extern/libmv/third_party/msinttypes/stdint.h
@@ -72,16 +72,16 @@ extern "C" {
// realize that, e.g. char has the same size as __int8
// so we give up on __intX for them.
#if (_MSC_VER < 1300)
- typedef char int8_t;
- typedef short int16_t;
- typedef int int32_t;
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
- typedef __int8 int8_t;
- typedef __int16 int16_t;
- typedef __int32 int32_t;
+ typedef signed __int8 int8_t;
+ typedef signed __int16 int16_t;
+ typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index 9b72efd90cf..25f91a0caea 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -45,6 +45,8 @@ set(ADDON_FILES
addon/ui.py
)
+add_definitions(-DGLEW_STATIC)
+
blender_add_lib(bf_intern_cycles "${SRC}" "${INC}" "${INC_SYS}")
add_dependencies(bf_intern_cycles bf_rna)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 34585260cdb..7a03df4f35a 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1085,7 +1085,7 @@ class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
mapping = node.texture_mapping
- layout.prop(mapping, "type", expand=True)
+ layout.prop(mapping, "vector_type", expand=True)
row = layout.row()
@@ -1180,7 +1180,7 @@ class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
scene = context.scene
cscene = scene.cycles
psys = context.particle_system
- return CyclesButtonsPanel.poll(context) and psys
+ return CyclesButtonsPanel.poll(context) and psys and psys.settings.type == 'HAIR'
def draw_header(self, context):
ccscene = context.scene.cycles_curves
@@ -1220,8 +1220,9 @@ class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
scene = context.scene
cscene = scene.cycles
ccscene = scene.cycles_curves
- use_curves = ccscene.use_curves and context.particle_system
- return CyclesButtonsPanel.poll(context) and use_curves
+ psys = context.particle_system
+ use_curves = ccscene.use_curves and psys
+ return CyclesButtonsPanel.poll(context) and use_curves and psys.settings.type == 'HAIR'
def draw(self, context):
layout = self.layout
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index caa61e0c5d7..940a923e5af 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -480,7 +480,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, need_undeformed);
if(b_mesh) {
- if(render_layer.use_surfaces && !(hide_tris && experimental)) {
+ if(render_layer.use_surfaces && !hide_tris) {
if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
else
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index d915d51dfd8..b576181d890 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -147,7 +147,7 @@ static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping b_mapping)
mapping->translation = get_float3(b_mapping.translation());
mapping->rotation = get_float3(b_mapping.rotation());
mapping->scale = get_float3(b_mapping.scale());
- mapping->type = (TextureMapping::Type)b_mapping.type();
+ mapping->type = (TextureMapping::Type)b_mapping.vector_type();
mapping->x_mapping = (TextureMapping::Mapping)b_mapping.mapping_x();
mapping->y_mapping = (TextureMapping::Mapping)b_mapping.mapping_y();
@@ -162,7 +162,7 @@ static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_map
mapping->translation = get_float3(b_mapping.translation());
mapping->rotation = get_float3(b_mapping.rotation());
mapping->scale = get_float3(b_mapping.scale());
- mapping->type = (TextureMapping::Type)b_mapping.type();
+ mapping->type = (TextureMapping::Type)b_mapping.vector_type();
mapping->use_minmax = b_mapping.use_min() || b_mapping.use_max();
@@ -322,9 +322,6 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();
switch(b_subsurface_node.falloff()) {
- case BL::ShaderNodeSubsurfaceScattering::falloff_COMPATIBLE:
- subsurface->closure = CLOSURE_BSSRDF_COMPATIBLE_ID;
- break;
case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
subsurface->closure = CLOSURE_BSSRDF_CUBIC_ID;
break;
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 337d075cce4..a349ddc5c3f 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -34,6 +34,7 @@
#include "util_debug.h"
#include "util_foreach.h"
+#include "util_opengl.h"
CCL_NAMESPACE_BEGIN
@@ -494,7 +495,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use
params.shadingsystem = SessionParams::OSL;
/* color managagement */
- params.display_buffer_linear = b_engine.support_display_space_shader(b_scene);
+ params.display_buffer_linear = GLEW_ARB_half_float_pixel && b_engine.support_display_space_shader(b_scene);
return params;
}
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 10d4112b57d..eb262a907a4 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -56,18 +56,6 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w
{
pixels_copy_from(rgba, y, w, h);
- GLuint texid;
- glGenTextures(1, &texid);
- glBindTexture(GL_TEXTURE_2D, texid);
- if(rgba.data_type == TYPE_HALF)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, h, 0, GL_RGBA, GL_HALF_FLOAT, (void*)rgba.data_pointer);
- else
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*)rgba.data_pointer);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
- glEnable(GL_TEXTURE_2D);
-
if(transparent) {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
@@ -75,30 +63,57 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w
glColor3f(1.0f, 1.0f, 1.0f);
- glPushMatrix();
- glTranslatef(0.0f, (float)dy, 0.0f);
+ if(rgba.data_type == TYPE_HALF) {
+ /* draw half float texture, GLSL shader for display transform assumed to be bound */
+ GLuint texid;
+ glGenTextures(1, &texid);
+ glBindTexture(GL_TEXTURE_2D, texid);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, h, 0, GL_RGBA, GL_HALF_FLOAT, (void*)rgba.data_pointer);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glBegin(GL_QUADS);
-
- glTexCoord2f(0.0f, 0.0f);
- glVertex2f(0.0f, 0.0f);
- glTexCoord2f(1.0f, 0.0f);
- glVertex2f((float)width, 0.0f);
- glTexCoord2f(1.0f, 1.0f);
- glVertex2f((float)width, (float)height);
- glTexCoord2f(0.0f, 1.0f);
- glVertex2f(0.0f, (float)height);
+ glEnable(GL_TEXTURE_2D);
+
+ glPushMatrix();
+ glTranslatef(0.0f, (float)dy, 0.0f);
+
+ glBegin(GL_QUADS);
+
+ glTexCoord2f(0.0f, 0.0f);
+ glVertex2f(0.0f, 0.0f);
+ glTexCoord2f(1.0f, 0.0f);
+ glVertex2f((float)width, 0.0f);
+ glTexCoord2f(1.0f, 1.0f);
+ glVertex2f((float)width, (float)height);
+ glTexCoord2f(0.0f, 1.0f);
+ glVertex2f(0.0f, (float)height);
- glEnd();
+ glEnd();
- glPopMatrix();
+ glPopMatrix();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+ glDeleteTextures(1, &texid);
+ }
+ else {
+ /* fallback for old graphics cards that don't support GLSL, half float,
+ * and non-power-of-two textures */
+ glPixelZoom((float)width/(float)w, (float)height/(float)h);
+ glRasterPos2f(0, dy);
+
+ uint8_t *pixels = (uint8_t*)rgba.data_pointer;
+
+ pixels += 4*y*w;
+
+ glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+ glRasterPos2f(0.0f, 0.0f);
+ glPixelZoom(1.0f, 1.0f);
+ }
if(transparent)
glDisable(GL_BLEND);
-
- glBindTexture(GL_TEXTURE_2D, 0);
- glDisable(GL_TEXTURE_2D);
- glDeleteTextures(1, &texid);
}
Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 5440bd91987..4ce7f6fd729 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -227,14 +227,12 @@ public:
bool support_device(bool experimental)
{
- if(!experimental) {
- int major, minor;
- cuDeviceComputeCapability(&major, &minor, cuDevId);
+ int major, minor;
+ cuDeviceComputeCapability(&major, &minor, cuDevId);
- if(major < 2) {
- cuda_error_message(string_printf("CUDA device supported only with compute capability 2.0 or up, found %d.%d.", major, minor));
- return false;
- }
+ if(major < 2) {
+ cuda_error_message(string_printf("CUDA device supported only with compute capability 2.0 or up, found %d.%d.", major, minor));
+ return false;
}
return true;
@@ -286,8 +284,12 @@ public:
cuda_error_message("CUDA nvcc compiler version could not be parsed.");
return "";
}
+ if(cuda_version < 50) {
+ printf("Unsupported CUDA version %d.%d detected, you need CUDA 5.0.\n", cuda_version/10, cuda_version%10);
+ return "";
+ }
- if(cuda_version != 50)
+ else if(cuda_version > 50)
printf("CUDA version %d.%d detected, build may succeed but only CUDA 5.0 is officially supported.\n", cuda_version/10, cuda_version%10);
/* compile */
@@ -296,36 +298,14 @@ public:
const int machine = system_cpu_bits();
string arch_flags;
- /* build flags depending on CUDA version and arch */
- if(cuda_version < 50) {
- /* CUDA 4.x */
- if(major == 1) {
- /* sm_1x */
- arch_flags = "--maxrregcount=24 --opencc-options -OPT:Olimit=0";
- }
- else if(major == 2) {
- /* sm_2x */
- arch_flags = "--maxrregcount=24";
- }
- else {
- /* sm_3x */
- arch_flags = "--maxrregcount=32";
- }
+ /* CUDA 5.x build flags for different archs */
+ if(major == 2) {
+ /* sm_2x */
+ arch_flags = "--maxrregcount=32 --use_fast_math";
}
- else {
- /* CUDA 5.x */
- if(major == 1) {
- /* sm_1x */
- arch_flags = "--maxrregcount=24 --opencc-options -OPT:Olimit=0 --use_fast_math";
- }
- else if(major == 2) {
- /* sm_2x */
- arch_flags = "--maxrregcount=32 --use_fast_math";
- }
- else {
- /* sm_3x */
- arch_flags = "--maxrregcount=32 --use_fast_math";
- }
+ else if(major == 3) {
+ /* sm_3x */
+ arch_flags = "--maxrregcount=32 --use_fast_math";
}
double starttime = time_dt();
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index d723df70c89..11c7bc6f099 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -892,8 +892,16 @@ public:
void tex_free(device_memory& mem)
{
- if(mem.data_pointer)
+ if(mem.device_pointer) {
+ foreach(const MemMap::value_type& value, mem_map) {
+ if(value.second == mem.device_pointer) {
+ mem_map.erase(value.first);
+ break;
+ }
+ }
+
mem_free(mem);
+ }
}
size_t global_size_round_up(int group_size, int global_size)
@@ -1086,7 +1094,7 @@ public:
tile.sample = sample + 1;
- //task->update_progress(tile);
+ task->update_progress(tile);
}
task->release_tile(tile);
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index eaa4e304ebb..56ba0e08743 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -151,36 +151,16 @@ if(WITH_CYCLES_CUDA_BINARIES)
set(cuda_version_flags "-D__KERNEL_CUDA_VERSION__=${CUDA_VERSION}")
- # build flags depending on CUDA version and arch
- if(CUDA_VERSION LESS 50)
- # CUDA 4.x
- if(${arch} MATCHES "sm_1[0-9]")
- # sm_1x
- set(cuda_arch_flags "--maxrregcount=24 --opencc-options -OPT:Olimit=0")
- elseif(${arch} MATCHES "sm_2[0-9]")
- # sm_2x
- set(cuda_arch_flags "--maxrregcount=24")
- else()
- # sm_3x
- set(cuda_arch_flags "--maxrregcount=32")
- endif()
-
- set(cuda_math_flags "")
- else()
- # CUDA 5.x
- if(${arch} MATCHES "sm_1[0-9]")
- # sm_1x
- set(cuda_arch_flags "--maxrregcount=24 --opencc-options -OPT:Olimit=0")
- elseif(${arch} MATCHES "sm_2[0-9]")
- # sm_2x
- set(cuda_arch_flags "--maxrregcount=32")
- else()
- # sm_3x
- set(cuda_arch_flags "--maxrregcount=32")
- endif()
-
- set(cuda_math_flags "--use_fast_math")
+ # CUDA 5.x build flags for different archs
+ if(${arch} MATCHES "sm_2[0-9]")
+ # sm_2x
+ set(cuda_arch_flags "--maxrregcount=32")
+ elseif(${arch} MATCHES "sm_3[0-9]")
+ # sm_3x
+ set(cuda_arch_flags "--maxrregcount=32")
endif()
+
+ set(cuda_math_flags "--use_fast_math")
if(CUDA_VERSION LESS 50 AND ${arch} MATCHES "sm_35")
message(WARNING "Can't build kernel for CUDA sm_35 architecture, skipping")
diff --git a/intern/cycles/kernel/SConscript b/intern/cycles/kernel/SConscript
index 6459c3ed183..a0522d9ba8e 100644
--- a/intern/cycles/kernel/SConscript
+++ b/intern/cycles/kernel/SConscript
@@ -86,33 +86,13 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']:
for arch in cuda_archs:
cubin_file = os.path.join(build_dir, "kernel_%s.cubin" % arch)
- # build flags depending on CUDA version and arch
- if cuda_version < 50:
- if arch == "sm_35":
- print("Can't build kernel for CUDA sm_35 architecture, skipping")
- continue
-
- # CUDA 4.x
- if arch.startswith("sm_1"):
- # sm_1x
- cuda_arch_flags = "--maxrregcount=24 --opencc-options -OPT:Olimit=0"
- elif arch.startswith("sm_2"):
- # sm_2x
- cuda_arch_flags = "--maxrregcount=24"
- else:
- # sm_3x
- cuda_arch_flags = "--maxrregcount=32"
- else:
- # CUDA 5.x
- if arch.startswith("sm_1"):
- # sm_1x
- cuda_arch_flags = "--maxrregcount=24 --opencc-options -OPT:Olimit=0 --use_fast_math"
- elif arch.startswith("sm_2"):
- # sm_2x
- cuda_arch_flags = "--maxrregcount=32 --use_fast_math"
- else:
- # sm_3x
- cuda_arch_flags = "--maxrregcount=32 --use_fast_math"
+ # CUDA 5.x build flags for different archs
+ if arch.startswith("sm_2"):
+ # sm_2x
+ cuda_arch_flags = "--maxrregcount=32 --use_fast_math"
+ elif arch.startswith("sm_3"):
+ # sm_3x
+ cuda_arch_flags = "--maxrregcount=32 --use_fast_math"
command = "\"%s\" -arch=%s %s %s \"%s\" -o \"%s\"" % (nvcc, arch, nvcc_flags, cuda_arch_flags, kernel_file, cubin_file)
diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h
index 8868a335037..721eceabc37 100644
--- a/intern/cycles/kernel/kernel_film.h
+++ b/intern/cycles/kernel/kernel_film.h
@@ -70,8 +70,8 @@ __device void kernel_film_convert_to_half_float(KernelGlobals *kg,
/* buffer offset */
int index = offset + x + y*stride;
- float4 *in = (float4*)(buffer + index*kernel_data.film.pass_stride);
- half *out = (half*)rgba + index*4;
+ __global float4 *in = (__global float4*)(buffer + index*kernel_data.film.pass_stride);
+ __global half *out = (__global half*)rgba + index*4;
float scale = kernel_data.film.exposure*sample_scale;
float4_store_half(out, in, scale);
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 1afe8480616..5354738d378 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -266,14 +266,9 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
if(sc) {
uint lcg_state = lcg_init(*rng + rng_offset + sample*0x68bc21eb);
- if(old_subsurface_scatter_use(&sd)) {
- old_subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, false);
- }
- else {
- float bssrdf_u, bssrdf_v;
- path_rng_2D(kg, rng, sample, num_total_samples, rng_offset + PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
- subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
- }
+ float bssrdf_u, bssrdf_v;
+ path_rng_2D(kg, rng, sample, num_total_samples, rng_offset + PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+ subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
state.flag |= PATH_RAY_BSSRDF_ANCESTOR;
}
@@ -468,7 +463,9 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
float min_ray_pdf = FLT_MAX;
float ray_pdf = 0.0f;
+#ifdef __LAMP_MIS__
float ray_t = 0.0f;
+#endif
PathState state;
int rng_offset = PRNG_BASE_NUM;
#ifdef __CMJ__
@@ -662,41 +659,35 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
if(sc) {
uint lcg_state = lcg_init(*rng + rng_offset + sample*0x68bc21eb);
- if(old_subsurface_scatter_use(&sd)) {
- old_subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, false);
- }
- else {
- ShaderData bssrdf_sd[BSSRDF_MAX_HITS];
- float bssrdf_u, bssrdf_v;
- path_rng_2D(kg, rng, sample, num_samples, rng_offset + PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
- int num_hits = subsurface_scatter_multi_step(kg, &sd, bssrdf_sd, state.flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
-
- /* compute lighting with the BSDF closure */
- for(int hit = 0; hit < num_hits; hit++) {
- float3 tp = throughput;
- PathState hit_state = state;
- Ray hit_ray = ray;
- float hit_ray_t = ray_t;
- float hit_ray_pdf = ray_pdf;
- float hit_min_ray_pdf = min_ray_pdf;
-
- hit_state.flag |= PATH_RAY_BSSRDF_ANCESTOR;
-
- if(kernel_path_integrate_lighting(kg, rng, sample, num_samples, &bssrdf_sd[hit],
- &tp, &hit_min_ray_pdf, &hit_ray_pdf, &hit_state, rng_offset+PRNG_BOUNCE_NUM, &L, &hit_ray, &hit_ray_t)) {
- kernel_path_indirect(kg, rng, sample, hit_ray, buffer,
- tp, num_samples, num_samples,
- hit_min_ray_pdf, hit_ray_pdf, hit_state, rng_offset+PRNG_BOUNCE_NUM*2, &L);
-
- /* for render passes, sum and reset indirect light pass variables
- * for the next samples */
- path_radiance_sum_indirect(&L);
- path_radiance_reset_indirect(&L);
- }
+ ShaderData bssrdf_sd[BSSRDF_MAX_HITS];
+ float bssrdf_u, bssrdf_v;
+ path_rng_2D(kg, rng, sample, num_samples, rng_offset + PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+ int num_hits = subsurface_scatter_multi_step(kg, &sd, bssrdf_sd, state.flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
+
+ /* compute lighting with the BSDF closure */
+ for(int hit = 0; hit < num_hits; hit++) {
+ float3 tp = throughput;
+ PathState hit_state = state;
+ Ray hit_ray = ray;
+ float hit_ray_t = ray_t;
+ float hit_ray_pdf = ray_pdf;
+ float hit_min_ray_pdf = min_ray_pdf;
+
+ hit_state.flag |= PATH_RAY_BSSRDF_ANCESTOR;
+
+ if(kernel_path_integrate_lighting(kg, rng, sample, num_samples, &bssrdf_sd[hit],
+ &tp, &hit_min_ray_pdf, &hit_ray_pdf, &hit_state, rng_offset+PRNG_BOUNCE_NUM, &L, &hit_ray, &hit_ray_t)) {
+ kernel_path_indirect(kg, rng, sample, hit_ray, buffer,
+ tp, num_samples, num_samples,
+ hit_min_ray_pdf, hit_ray_pdf, hit_state, rng_offset+PRNG_BOUNCE_NUM*2, &L);
+
+ /* for render passes, sum and reset indirect light pass variables
+ * for the next samples */
+ path_radiance_sum_indirect(&L);
+ path_radiance_reset_indirect(&L);
}
-
- break;
}
+ break;
}
}
#endif
@@ -1129,17 +1120,6 @@ __device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, int
/* do subsurface scatter step with copy of shader data, this will
* replace the BSSRDF with a diffuse BSDF closure */
for(int j = 0; j < num_samples; j++) {
- if(old_subsurface_scatter_use(&sd)) {
- ShaderData bssrdf_sd = sd;
- old_subsurface_scatter_step(kg, &bssrdf_sd, state.flag, sc, &lcg_state, true);
-
- /* compute lighting with the BSDF closure */
- kernel_branched_path_integrate_lighting(kg, rng, sample*num_samples + j,
- aa_samples*num_samples,
- &bssrdf_sd, throughput, num_samples_inv,
- ray_pdf, ray_pdf, state, rng_offset, &L, buffer);
- }
- else {
ShaderData bssrdf_sd[BSSRDF_MAX_HITS];
float bssrdf_u, bssrdf_v;
path_rng_2D(kg, &bssrdf_rng, sample*num_samples + j, aa_samples*num_samples, rng_offset + PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
@@ -1151,7 +1131,6 @@ __device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, int
aa_samples*num_samples,
&bssrdf_sd[hit], throughput, num_samples_inv,
ray_pdf, ray_pdf, state, rng_offset+PRNG_BOUNCE_NUM, &L, buffer);
- }
}
state.flag &= ~PATH_RAY_BSSRDF_ANCESTOR;
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index ee71a0cfcf4..81630caed9a 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -36,15 +36,8 @@ CCL_NAMESPACE_BEGIN
/* ShaderData setup from incoming ray */
#ifdef __OBJECT_MOTION__
-#if defined(__KERNEL_CUDA_VERSION__) && __KERNEL_CUDA_VERSION__ <= 42
-__device_noinline
-#else
-__device
-#endif
-void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time)
+__device void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time)
{
- /* note that this is a separate non-inlined function to work around crash
- * on CUDA sm 2.0, otherwise kernel execution crashes (compiler bug?) */
if(sd->flag & SD_OBJECT_MOTION) {
sd->ob_tfm = object_fetch_transform_motion(kg, sd->object, time);
sd->ob_itfm= transform_quick_inverse(sd->ob_tfm);
@@ -56,12 +49,7 @@ void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float tim
}
#endif
-#if defined(__KERNEL_CUDA_VERSION__) && __KERNEL_CUDA_VERSION__ <= 42
-__device_noinline
-#else
-__device
-#endif
-void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
+__device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
const Intersection *isect, const Ray *ray, int bounce)
{
#ifdef __INSTANCING__
@@ -249,12 +237,7 @@ __device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderData
/* ShaderData setup from position sampled on mesh */
-#if defined(__KERNEL_CUDA_VERSION__) && __KERNEL_CUDA_VERSION__ <= 42
-__device_noinline
-#else
-__device
-#endif
-void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
+__device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
const float3 P, const float3 Ng, const float3 I,
int shader, int object, int prim, float u, float v, float t, float time, int bounce, int segment)
{
diff --git a/intern/cycles/kernel/kernel_sse2.cpp b/intern/cycles/kernel/kernel_sse2.cpp
index 862626d6899..9c69e519dca 100644
--- a/intern/cycles/kernel/kernel_sse2.cpp
+++ b/intern/cycles/kernel/kernel_sse2.cpp
@@ -20,7 +20,10 @@
#ifdef WITH_OPTIMIZED_KERNEL
+/* SSE optimization disabled for now on 32 bit, see bug #36316 */
+#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
#define __KERNEL_SSE2__
+#endif
#include "kernel.h"
#include "kernel_compat_cpu.h"
diff --git a/intern/cycles/kernel/kernel_sse3.cpp b/intern/cycles/kernel/kernel_sse3.cpp
index c44098606a5..05877a41b4a 100644
--- a/intern/cycles/kernel/kernel_sse3.cpp
+++ b/intern/cycles/kernel/kernel_sse3.cpp
@@ -20,9 +20,12 @@
#ifdef WITH_OPTIMIZED_KERNEL
+/* SSE optimization disabled for now on 32 bit, see bug #36316 */
+#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
#define __KERNEL_SSE2__
#define __KERNEL_SSE3__
#define __KERNEL_SSSE3__
+#endif
#include "kernel.h"
#include "kernel_compat_cpu.h"
diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
index 4567f2ff0ce..d16b9328bf2 100644
--- a/intern/cycles/kernel/kernel_subsurface.h
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -403,164 +403,5 @@ __device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd,
subsurface_scatter_setup_diffuse_bsdf(sd, eval, (num_hits > 0), N);
}
-
-/* OLD BSSRDF */
-
-__device float old_bssrdf_sample_distance(KernelGlobals *kg, float radius, float refl, float u)
-{
- int table_offset = kernel_data.bssrdf.table_offset;
- float r = lookup_table_read_2D(kg, u, refl, table_offset, BSSRDF_RADIUS_TABLE_SIZE, BSSRDF_REFL_TABLE_SIZE);
-
- return r*radius;
-}
-
-#ifdef BSSRDF_MULTI_EVAL
-__device float old_bssrdf_pdf(KernelGlobals *kg, float radius, float refl, float r)
-{
- if(r >= radius)
- return 0.0f;
-
- /* todo: when we use the real BSSRDF this will need to be divided by the maximum
- * radius instead of the average radius */
- float t = r/radius;
-
- int table_offset = kernel_data.bssrdf.table_offset + BSSRDF_PDF_TABLE_OFFSET;
- float pdf = lookup_table_read_2D(kg, t, refl, table_offset, BSSRDF_RADIUS_TABLE_SIZE, BSSRDF_REFL_TABLE_SIZE);
-
- pdf /= radius;
-
- return pdf;
-}
-#endif
-
-#ifdef BSSRDF_MULTI_EVAL
-__device float3 old_subsurface_scatter_multi_eval(KernelGlobals *kg, ShaderData *sd, bool hit, float refl, float *r, int num_r, bool all)
-{
- /* compute pdf */
- float3 eval_sum = make_float3(0.0f, 0.0f, 0.0f);
- float pdf_sum = 0.0f;
- float sample_weight_sum = 0.0f;
- int num_bssrdf = 0;
-
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
-
- if(CLOSURE_IS_BSSRDF(sc->type)) {
- float sample_weight = (all)? 1.0f: sc->sample_weight;
-
- /* compute pdf */
- float pdf = 1.0f;
- for(int i = 0; i < num_r; i++)
- pdf *= old_bssrdf_pdf(kg, sc->data0, refl, r[i]);
-
- eval_sum += sc->weight*pdf;
- pdf_sum += sample_weight*pdf;
-
- sample_weight_sum += sample_weight;
- num_bssrdf++;
- }
- }
-
- float inv_pdf_sum;
-
- if(pdf_sum > 0.0f) {
- /* in case of branched path integrate we sample all bssrdf's once,
- * for path trace we pick one, so adjust pdf for that */
- if(all)
- inv_pdf_sum = 1.0f/pdf_sum;
- else
- inv_pdf_sum = sample_weight_sum/pdf_sum;
- }
- else
- inv_pdf_sum = 0.0f;
-
- float3 weight = eval_sum * inv_pdf_sum;
-
- return weight;
-}
-#endif
-
-/* subsurface scattering step, from a point on the surface to another nearby point on the same object */
-__device void old_subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, int state_flag, ShaderClosure *sc, uint *lcg_state, bool all)
-{
- float radius = sc->data0;
- float refl = max(average(sc->weight)*3.0f, 0.0f);
- float r = 0.0f;
- bool hit = false;
- float3 weight = make_float3(1.0f, 1.0f, 1.0f);
-#ifdef BSSRDF_MULTI_EVAL
- float r_attempts[BSSRDF_MAX_ATTEMPTS];
-#endif
- int num_attempts;
-
- /* attempt to find a hit a given number of times before giving up */
- for(num_attempts = 0; num_attempts < kernel_data.bssrdf.num_attempts; num_attempts++) {
- /* random numbers for sampling */
- float u1 = lcg_step_float(lcg_state);
- float u2 = lcg_step_float(lcg_state);
- float u3 = lcg_step_float(lcg_state);
- float u4 = lcg_step_float(lcg_state);
- float u5 = lcg_step_float(lcg_state);
-
- r = old_bssrdf_sample_distance(kg, radius, refl, u5);
-#ifdef BSSRDF_MULTI_EVAL
- r_attempts[num_attempts] = r;
-#endif
-
- float3 p1 = sd->P + sample_uniform_sphere(u1, u2)*r;
- float3 p2 = sd->P + sample_uniform_sphere(u3, u4)*r;
-
- /* create ray */
- Ray ray;
- ray.P = p1;
- ray.D = normalize_len(p2 - p1, &ray.t);
- ray.dP = sd->dP;
- ray.dD = differential3_zero();
- ray.time = sd->time;
-
- /* intersect with the same object. if multiple intersections are
- * found it will randomly pick one of them */
- Intersection isect;
- if(scene_intersect_subsurface(kg, &ray, &isect, sd->object, lcg_state, 1) == 0)
- continue;
-
- /* setup new shading point */
- shader_setup_from_subsurface(kg, sd, &isect, &ray);
-
- hit = true;
- num_attempts++;
- break;
- }
-
- /* evaluate subsurface scattering closures */
-#ifdef BSSRDF_MULTI_EVAL
- weight *= old_subsurface_scatter_multi_eval(kg, sd, hit, refl, r_attempts, num_attempts, all);
-#else
- weight *= sc->weight;
-#endif
-
- if(!hit)
- weight = make_float3(0.0f, 0.0f, 0.0f);
-
- /* optionally blur colors and bump mapping */
- float3 N = sd->N;
- subsurface_color_bump_blur(kg, sd, sd, state_flag, &weight, &N);
-
- /* replace closures with a single diffuse BSDF */
- subsurface_scatter_setup_diffuse_bsdf(sd, weight, hit, N);
-}
-
-__device bool old_subsurface_scatter_use(ShaderData *sd)
-{
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
-
- if(sc->type == CLOSURE_BSSRDF_COMPATIBLE_ID)
- return true;
- }
-
- return false;
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index d039b708bd4..3371c580c71 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -35,12 +35,7 @@ CCL_NAMESPACE_BEGIN
#define PARTICLE_SIZE 5
#define TIME_INVALID FLT_MAX
-#define BSSRDF_RADIUS_TABLE_SIZE 1024
-#define BSSRDF_REFL_TABLE_SIZE 256
-#define BSSRDF_PDF_TABLE_OFFSET (BSSRDF_RADIUS_TABLE_SIZE*BSSRDF_REFL_TABLE_SIZE)
-#define BSSRDF_LOOKUP_TABLE_SIZE (BSSRDF_RADIUS_TABLE_SIZE*BSSRDF_REFL_TABLE_SIZE*2)
#define BSSRDF_MIN_RADIUS 1e-8f
-#define BSSRDF_MAX_ATTEMPTS 8
#define BSSRDF_MAX_HITS 4
#define BB_DRAPPER 800.0f
@@ -815,12 +810,6 @@ typedef struct KernelCurves {
int pad2;
} KernelCurves;
-typedef struct KernelBSSRDF {
- int table_offset;
- int num_attempts;
- int pad1, pad2;
-} KernelBSSRDF;
-
typedef struct KernelBlackbody {
int table_offset;
int pad1, pad2, pad3;
@@ -834,7 +823,6 @@ typedef struct KernelData {
KernelIntegrator integrator;
KernelBVH bvh;
KernelCurves curve;
- KernelBSSRDF bssrdf;
KernelBlackbody blackbody;
} KernelData;
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 625ad263f7f..18e8fee4348 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -253,7 +253,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
/* disable in case of diffuse ancestor, can't see it well then and
* adds considerably noise due to probabilities of continuing path
* getting lower and lower */
- if(sc.type != CLOSURE_BSSRDF_COMPATIBLE_ID && (path_flag & PATH_RAY_DIFFUSE_ANCESTOR))
+ if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
bssrdf->radius = make_float3(0.0f, 0.0f, 0.0f);
/* create one closure for each color channel */
diff --git a/intern/cycles/kernel/shaders/SConscript b/intern/cycles/kernel/shaders/SConscript
index aad6e23e4d4..8bc1c2206e0 100644
--- a/intern/cycles/kernel/shaders/SConscript
+++ b/intern/cycles/kernel/shaders/SConscript
@@ -57,7 +57,7 @@ if env['WITH_BF_CYCLES_OSL']:
osl_file = os.path.join(source_dir, f)
oso_file = os.path.join(build_dir, f.replace('.osl', '.oso'))
- command = "%s -q -O2 -I%s -o %s %s" % (osl_compiler, source_dir, oso_file, osl_file)
+ command = "\"%s\" -q -O2 -I\"%s\" -o \"%s\" \"%s\"" % (osl_compiler, source_dir, oso_file, osl_file)
shaders.Command(oso_file, f, command)
shaders.Depends(oso_file, [f] + dependencies)
diff --git a/intern/cycles/kernel/shaders/node_environment_texture.osl b/intern/cycles/kernel/shaders/node_environment_texture.osl
index 6b61c689066..136ccdf8b18 100644
--- a/intern/cycles/kernel/shaders/node_environment_texture.osl
+++ b/intern/cycles/kernel/shaders/node_environment_texture.osl
@@ -19,7 +19,7 @@
vector environment_texture_direction_to_equirectangular(vector dir)
{
- float u = -atan2(dir[1], dir[0]) / (2.0 * M_PI) + 0.5;
+ float u = -atan2(dir[1], dir[0]) / (M_2PI) + 0.5;
float v = atan2(dir[2], hypot(dir[0], dir[1])) / M_PI + 0.5;
return vector(u, v, 0.0);
diff --git a/intern/cycles/kernel/shaders/node_hair_bsdf.osl b/intern/cycles/kernel/shaders/node_hair_bsdf.osl
index d1d7d0fb6a6..54d4cb67c3b 100644
--- a/intern/cycles/kernel/shaders/node_hair_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_hair_bsdf.osl
@@ -19,8 +19,8 @@
#include "stdosl.h"
shader node_hair_bsdf(
- color Color = 0.8,
- string component = "Reflection",
+ color Color = 0.8,
+ string component = "Reflection",
float Offset = 0.0,
float RoughnessU = 0.1,
float RoughnessV = 1.0,
@@ -28,29 +28,30 @@ shader node_hair_bsdf(
output closure color BSDF = 0)
{
float IsStrand;
- float roughnessh = clamp(RoughnessU, 0.001,1.0);
- float roughnessv = clamp(RoughnessV, 0.001,1.0);
+ float roughnessh = clamp(RoughnessU, 0.001, 1.0);
+ float roughnessv = clamp(RoughnessV, 0.001, 1.0);
getattribute("geom:is_curve", IsStrand);
- if (!IsStrand) {
- if (backfacing())
- BSDF = transparent();
- else {
- if (component == "Reflection")
- BSDF = Color * hair_reflection(Normal, roughnessh, roughnessv, normalize(dPdv), 0.0);
- else
- BSDF = Color * hair_transmission(Normal, roughnessh, roughnessv, normalize(dPdv), 0.0);
+ if (!IsStrand) {
+ if (backfacing()) {
+ BSDF = transparent();
+ }
+ else {
+ if (component == "Reflection")
+ BSDF = Color * hair_reflection(Normal, roughnessh, roughnessv, normalize(dPdv), 0.0);
+ else
+ BSDF = Color * hair_transmission(Normal, roughnessh, roughnessv, normalize(dPdv), 0.0);
}
}
- else {
- if (backfacing())
- BSDF = transparent();
- else {
- if (component == "Reflection")
- BSDF = Color * hair_reflection(Normal, roughnessh, roughnessv, dPdu, -Offset);
- else
- BSDF = Color * hair_transmission(Normal, roughnessh, roughnessv, dPdu, -Offset);
+ else {
+ if (backfacing()) {
+ BSDF = transparent();
+ }
+ else {
+ if (component == "Reflection")
+ BSDF = Color * hair_reflection(Normal, roughnessh, roughnessv, dPdu, -Offset);
+ else
+ BSDF = Color * hair_transmission(Normal, roughnessh, roughnessv, dPdu, -Offset);
}
}
}
-
diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl
index 3ed791fdc92..85c2dbdb2c2 100644
--- a/intern/cycles/kernel/shaders/node_sky_texture.osl
+++ b/intern/cycles/kernel/shaders/node_sky_texture.osl
@@ -44,8 +44,8 @@ float sky_perez_function(float lam[9], float theta, float gamma)
}
color sky_radiance_old(normal dir,
- float sunphi, float suntheta, color radiance,
- float config_x[9], float config_y[9], float config_z[9])
+ float sunphi, float suntheta, color radiance,
+ float config_x[9], float config_y[9], float config_z[9])
{
/* convert vector to spherical coordinates */
vector spherical = sky_spherical_coordinates(dir);
@@ -76,7 +76,7 @@ float sky_radiance_internal(float config[9], float theta, float gamma)
float expM = exp(config[4] * gamma);
float rayM = cgamma * cgamma;
- float mieM = (1.0 + rayM) / pow((1.0 + config[8]*config[8] - 2.0*config[8]*cgamma), 1.5);
+ float mieM = (1.0 + rayM) / pow((1.0 + config[8] * config[8] - 2.0 * config[8] * cgamma), 1.5);
float zenith = sqrt(ctheta);
return (1.0 + config[0] * exp(config[1] / (ctheta + 0.01))) *
@@ -84,8 +84,8 @@ float sky_radiance_internal(float config[9], float theta, float gamma)
}
color sky_radiance_new(normal dir,
- float sunphi, float suntheta, color radiance,
- float config_x[9], float config_y[9], float config_z[9])
+ float sunphi, float suntheta, color radiance,
+ float config_x[9], float config_y[9], float config_z[9])
{
/* convert vector to spherical coordinates */
vector spherical = sky_spherical_coordinates(dir);
@@ -104,7 +104,7 @@ color sky_radiance_new(normal dir,
float z = sky_radiance_internal(config_z, theta, gamma) * radiance[2];
/* convert to RGB and adjust strength */
- return xyz_to_rgb(x, y, z) * (M_2PI/683);
+ return xyz_to_rgb(x, y, z) * (M_2PI / 683);
}
shader node_sky_texture(
diff --git a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
index 5c1d1be0ee7..1c0cd74c0be 100644
--- a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
+++ b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
@@ -26,7 +26,7 @@ shader node_subsurface_scattering(
normal Normal = N,
output closure color BSSRDF = 0)
{
- if(Falloff == "Gaussian")
+ if (Falloff == "Gaussian")
BSSRDF = Color * bssrdf_gaussian(N, Scale * Radius, TextureBlur);
else
BSSRDF = Color * bssrdf_cubic(N, Scale * Radius, TextureBlur, Sharpness);
diff --git a/intern/cycles/kernel/shaders/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_ward_bsdf.osl
index a21dd24059d..2d360d594f2 100644
--- a/intern/cycles/kernel/shaders/node_ward_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_ward_bsdf.osl
@@ -29,7 +29,7 @@ shader node_ward_bsdf(
vector T = Tangent;
if (Rotation != 0.0)
- T = rotate(T, Rotation * 2.0 * M_PI, point(0.0, 0.0, 0.0), Normal);
+ T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
/* compute roughness */
float RoughnessU, RoughnessV;
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index 424ca335903..47c5dc27f2b 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -134,12 +134,16 @@ normal mod (normal a, float b) { return a - b*floor(a/b); }
color mod (color a, float b) { return a - b*floor(a/b); }
float mod (float a, float b) { return a - b*floor(a/b); }
PERCOMP2 (min)
+int min (int a, int b) BUILTIN;
PERCOMP2 (max)
+int max (int a, int b) BUILTIN;
normal clamp (normal x, normal minval, normal maxval) { return max(min(x,maxval),minval); }
vector clamp (vector x, vector minval, vector maxval) { return max(min(x,maxval),minval); }
point clamp (point x, point minval, point maxval) { return max(min(x,maxval),minval); }
color clamp (color x, color minval, color maxval) { return max(min(x,maxval),minval); }
float clamp (float x, float minval, float maxval) { return max(min(x,maxval),minval); }
+int clamp (int x, int minval, int maxval) { return max(min(x,maxval),minval); }
+#if 0
normal mix (normal x, normal y, normal a) { return x*(1-a) + y*a; }
normal mix (normal x, normal y, float a) { return x*(1-a) + y*a; }
vector mix (vector x, vector y, vector a) { return x*(1-a) + y*a; }
@@ -149,6 +153,17 @@ point mix (point x, point y, float a) { return x*(1-a) + y*a; }
color mix (color x, color y, color a) { return x*(1-a) + y*a; }
color mix (color x, color y, float a) { return x*(1-a) + y*a; }
float mix (float x, float y, float a) { return x*(1-a) + y*a; }
+#else
+normal mix (normal x, normal y, normal a) BUILTIN;
+normal mix (normal x, normal y, float a) BUILTIN;
+vector mix (vector x, vector y, vector a) BUILTIN;
+vector mix (vector x, vector y, float a) BUILTIN;
+point mix (point x, point y, point a) BUILTIN;
+point mix (point x, point y, float a) BUILTIN;
+color mix (color x, color y, color a) BUILTIN;
+color mix (color x, color y, float a) BUILTIN;
+float mix (float x, float y, float a) BUILTIN;
+#endif
int isnan (float x) BUILTIN;
int isinf (float x) BUILTIN;
int isfinite (float x) BUILTIN;
@@ -418,8 +433,8 @@ int startswith (string s, string prefix) BUILTIN;
int endswith (string s, string suffix) BUILTIN;
string substr (string s, int start, int len) BUILTIN;
string substr (string s, int start) { return substr (s, start, strlen(s)); }
-float strtof (string str) BUILTIN;
-int strtoi (string str) BUILTIN;
+float stof (string str) BUILTIN;
+int stoi (string str) BUILTIN;
// Define concat in terms of shorter concat
string concat (string a, string b, string c) {
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 6d9c4e215e6..0d4716ab078 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -378,7 +378,6 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
#endif
#ifdef __SUBSURFACE__
- case CLOSURE_BSSRDF_COMPATIBLE_ID:
case CLOSURE_BSSRDF_CUBIC_ID:
case CLOSURE_BSSRDF_GAUSSIAN_ID: {
ShaderClosure *sc = &sd->closure[sd->num_closure];
@@ -388,7 +387,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
/* disable in case of diffuse ancestor, can't see it well then and
* adds considerably noise due to probabilities of continuing path
* getting lower and lower */
- if(type != CLOSURE_BSSRDF_COMPATIBLE_ID && (path_flag & PATH_RAY_DIFFUSE_ANCESTOR))
+ if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
param1 = 0.0f;
if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) {
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 50daf159f26..abd63530d63 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -377,7 +377,6 @@ typedef enum ClosureType {
CLOSURE_BSDF_TRANSPARENT_ID,
/* BSSRDF */
- CLOSURE_BSSRDF_COMPATIBLE_ID,
CLOSURE_BSSRDF_CUBIC_ID,
CLOSURE_BSSRDF_GAUSSIAN_ID,
@@ -402,7 +401,7 @@ typedef enum ClosureType {
#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID)
#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
#define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID)
-#define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_COMPATIBLE_ID && type <= CLOSURE_BSSRDF_GAUSSIAN_ID)
+#define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_GAUSSIAN_ID)
#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID)
#define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID)
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index dbbfe2ee7c9..7d00ed92164 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -18,7 +18,6 @@ set(SRC
background.cpp
blackbody.cpp
buffers.cpp
- bssrdf.cpp
camera.cpp
film.cpp
graph.cpp
@@ -47,7 +46,6 @@ set(SRC_HEADERS
background.h
blackbody.h
buffers.h
- bssrdf.h
camera.h
film.h
graph.h
diff --git a/intern/cycles/render/bssrdf.cpp b/intern/cycles/render/bssrdf.cpp
deleted file mode 100644
index 69cab5e1824..00000000000
--- a/intern/cycles/render/bssrdf.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#include "bssrdf.h"
-
-#include "util_algorithm.h"
-#include "util_math.h"
-#include "util_types.h"
-
-#include "kernel_types.h"
-#include "kernel_montecarlo.h"
-
-CCL_NAMESPACE_BEGIN
-
-static float bssrdf_cubic(float ld, float r)
-{
- if(ld == 0.0f)
- return (r == 0.0f)? 1.0f: 0.0f;
-
- return powf(ld - min(r, ld), 3.0f) * 4.0f/powf(ld, 4.0f);
-}
-
-/* Cumulative density function utilities */
-
-static float cdf_lookup_inverse(const vector<float>& table, float2 range, float x)
-{
- int index = upper_bound(table.begin(), table.end(), x) - table.begin();
-
- if(index == 0)
- return range[0];
- else if(index == table.size())
- return range[1];
- else
- index--;
-
- float t = (x - table[index])/(table[index+1] - table[index]);
- float y = ((index + t)/(table.size() - 1));
-
- return y*(range[1] - range[0]) + range[0];
-}
-
-static void cdf_invert(vector<float>& to, float2 to_range, const vector<float>& from, float2 from_range)
-{
- float step = 1.0f/(float)(to.size() - 1);
-
- for(int i = 0; i < to.size(); i++) {
- float x = (i*step)*(from_range[1] - from_range[0]) + from_range[0];
- to[i] = cdf_lookup_inverse(from, to_range, x);
- }
-}
-
-/* BSSRDF */
-
-static void bssrdf_lookup_table_create(float ld, vector<float>& sample_table, vector<float>& pdf_table)
-{
- const int size = BSSRDF_RADIUS_TABLE_SIZE;
- vector<float> cdf(size);
- vector<float> pdf(size);
- float step = 1.0f/(float)(size - 1);
- float max_radius = ld;
- float pdf_sum = 0.0f;
-
- /* compute the probability density function */
- for(int i = 0; i < pdf.size(); i++) {
- float x = (i*step)*max_radius;
- pdf[i] = bssrdf_cubic(ld, x);
- pdf_sum += pdf[i];
- }
-
- /* adjust for area covered by each distance */
- for(int i = 0; i < pdf.size(); i++) {
- float x = (i*step)*max_radius;
- pdf[i] *= M_2PI_F*x;
- }
-
- /* normalize pdf, we multiply in reflectance later */
- if(pdf_sum > 0.0f)
- for(int i = 0; i < pdf.size(); i++)
- pdf[i] /= pdf_sum;
-
- /* sum to account for sampling which uses overlapping sphere */
- for(int i = pdf.size() - 2; i >= 0; i--)
- pdf[i] = pdf[i] + pdf[i+1];
-
- /* compute the cumulative density function */
- cdf[0] = 0.0f;
-
- for(int i = 1; i < size; i++)
- cdf[i] = cdf[i-1] + 0.5f*(pdf[i-1] + pdf[i])*step*max_radius;
-
- /* invert cumulative density function for importance sampling */
- float2 cdf_range = make_float2(0.0f, cdf[size - 1]);
- float2 table_range = make_float2(0.0f, max_radius);
-
- cdf_invert(sample_table, table_range, cdf, cdf_range);
-
- /* copy pdf table */
- for(int i = 0; i < pdf.size(); i++)
- pdf_table[i] = pdf[i];
-}
-
-void bssrdf_table_build(vector<float>& table)
-{
- vector<float> sample_table(BSSRDF_RADIUS_TABLE_SIZE);
- vector<float> pdf_table(BSSRDF_RADIUS_TABLE_SIZE);
-
- table.resize(BSSRDF_LOOKUP_TABLE_SIZE);
-
- /* create a 2D lookup table, for reflection x sample radius */
- for(int i = 0; i < BSSRDF_REFL_TABLE_SIZE; i++) {
- float radius = 1.0f;
-
- bssrdf_lookup_table_create(radius, sample_table, pdf_table);
-
- memcpy(&table[i*BSSRDF_RADIUS_TABLE_SIZE], &sample_table[0], BSSRDF_RADIUS_TABLE_SIZE*sizeof(float));
- memcpy(&table[BSSRDF_PDF_TABLE_OFFSET + i*BSSRDF_RADIUS_TABLE_SIZE], &pdf_table[0], BSSRDF_RADIUS_TABLE_SIZE*sizeof(float));
- }
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/render/bssrdf.h b/intern/cycles/render/bssrdf.h
deleted file mode 100644
index b8f0d44bc34..00000000000
--- a/intern/cycles/render/bssrdf.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#ifndef __BSSRDF_H__
-#define __BSSRDF_H__
-
-#include "util_vector.h"
-
-CCL_NAMESPACE_BEGIN
-
-void bssrdf_table_build(vector<float>& table);
-
-CCL_NAMESPACE_END
-
-#endif /* __BSSRDF_H__ */
-
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 385395e3752..26af60572f6 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -15,7 +15,6 @@
*/
#include "background.h"
-#include "bssrdf.h"
#include "blackbody.h"
#include "device.h"
#include "graph.h"
@@ -127,7 +126,6 @@ void Shader::tag_used(Scene *scene)
ShaderManager::ShaderManager()
{
need_update = true;
- bssrdf_table_offset = TABLE_OFFSET_INVALID;
blackbody_table_offset = TABLE_OFFSET_INVALID;
}
@@ -254,23 +252,6 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
device->tex_alloc("__shader_flag", dscene->shader_flag);
- /* bssrdf lookup table */
- KernelBSSRDF *kbssrdf = &dscene->data.bssrdf;
-
- if(has_surface_bssrdf && bssrdf_table_offset == TABLE_OFFSET_INVALID) {
- vector<float> table;
-
- bssrdf_table_build(table);
- bssrdf_table_offset = scene->lookup_tables->add_table(dscene, table);
-
- kbssrdf->table_offset = (int)bssrdf_table_offset;
- kbssrdf->num_attempts = BSSRDF_MAX_ATTEMPTS;
- }
- else if(!has_surface_bssrdf && bssrdf_table_offset != TABLE_OFFSET_INVALID) {
- scene->lookup_tables->remove_table(bssrdf_table_offset);
- bssrdf_table_offset = TABLE_OFFSET_INVALID;
- }
-
/* blackbody lookup table */
KernelBlackbody *kblackbody = &dscene->data.blackbody;
@@ -289,11 +270,6 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scene *scene)
{
- if(bssrdf_table_offset != TABLE_OFFSET_INVALID) {
- scene->lookup_tables->remove_table(bssrdf_table_offset);
- bssrdf_table_offset = TABLE_OFFSET_INVALID;
- }
-
if(blackbody_table_offset != TABLE_OFFSET_INVALID) {
scene->lookup_tables->remove_table(blackbody_table_offset);
blackbody_table_offset = TABLE_OFFSET_INVALID;
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index a58d6955da0..6869a651b46 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -141,7 +141,6 @@ protected:
typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap;
AttributeIDMap unique_attribute_id;
- size_t bssrdf_table_offset;
size_t blackbody_table_offset;
};
diff --git a/intern/cycles/util/util_opengl.h b/intern/cycles/util/util_opengl.h
index 07a296ed1e6..04a3e039c9d 100644
--- a/intern/cycles/util/util_opengl.h
+++ b/intern/cycles/util/util_opengl.h
@@ -20,12 +20,7 @@
/* OpenGL header includes, used everywhere we use OpenGL, to deal with
* platform differences in one central place. */
-#ifdef __APPLE__
-#include <OpenGL/gl.h>
-#include <OpenGL/glu.h>
-#else
#include <GL/glew.h>
-#endif
#endif /* __UTIL_OPENGL_H__ */
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index f48fd1e124b..a8f514864db 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -545,10 +545,7 @@ template<size_t i0, size_t i1, size_t i2, size_t i3> __device_inline const __m12
#ifdef __KERNEL_OPENCL__
-__device_inline void float4_store_half(half *h, const float4 *f, float scale)
-{
- vstore_half4(*f * scale, 0, h);
-}
+#define float4_store_half(h, f, scale) vstore_half4(*(f) * (scale), 0, h);
#else
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
index 88f338c0649..876be90025f 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
+++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
@@ -52,8 +52,6 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplays(GHOST_TUns8& numDisplay
GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const
{
- GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getNumDisplaySettings(): only main display is supported");
-
numSettings = (GHOST_TInt32)3; //Width, Height, BitsPerPixel
return GHOST_kSuccess;
@@ -62,11 +60,8 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplaySettings(GHOST_TUns8 disp
GHOST_TSuccess GHOST_DisplayManagerCocoa::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
{
- //Note that only current display setting is available
NSScreen *askedDisplay;
- GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getDisplaySetting(): only main display is supported");
-
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if (display == kMainDisplay) //Screen #0 may not be the main one
diff --git a/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c b/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c
index 2efa0e6d5e8..9df9a56f8b8 100644
--- a/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c
+++ b/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c
@@ -30,7 +30,7 @@
/* It is to be noted that these implementations are linked in as
* 'extern "C"' calls from GHOST_NDOFManagerCocoa.
-
+
* This is done in order to
* preserve weak linking capability (which as of clang-3.3 and xcode5
* breaks weak linking when there is name mangling of c++ libraries.)
@@ -42,42 +42,53 @@
OSErr GHOST_NDOFManager3Dconnexion_available(void)
{
- // extern unsigned int InstallConnexionHandlers() __attribute__((weak_import));
- // Make the linker happy for the framework check (see link below for more info)
- // http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html
- return InstallConnexionHandlers != 0;
- // this means that the driver is installed and dynamically linked to blender
+ // extern unsigned int InstallConnexionHandlers() __attribute__((weak_import));
+ // Make the linker happy for the framework check (see link below for more info)
+ // http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html
+ return InstallConnexionHandlers != 0;
+ // this means that the driver is installed and dynamically linked to blender
}
OSErr GHOST_NDOFManager3Dconnexion_oldDRV()
{
- //extern unsigned int SetConnexionClientButtonMask() __attribute__((weak_import));
- // Make the linker happy for the framework check (see link below for more info)
- // http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html
- return SetConnexionClientButtonMask != 0;
- // this means that the driver has this symbol
+ //extern unsigned int SetConnexionClientButtonMask() __attribute__((weak_import));
+ // Make the linker happy for the framework check (see link below for more info)
+ // http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html
+ return SetConnexionClientButtonMask != 0;
+ // this means that the driver has this symbol
+}
+
+UInt16 GHOST_NDOFManager3Dconnexion_RegisterConnexionClient(UInt32 signature, UInt8 *name, UInt16 mode, UInt32 mask)
+{
+ return RegisterConnexionClient(signature, name, mode, mask);
+}
+
+void GHOST_NDOFManager3Dconnexion_SetConnexionClientButtonMask(UInt16 clientID, UInt32 buttonMask)
+{
+ return SetConnexionClientButtonMask( clientID, buttonMask);
+}
+
+void GHOST_NDOFManager3Dconnexion_UnregisterConnexionClient(UInt16 clientID)
+{
+ return UnregisterConnexionClient( clientID);
+}
+
+OSErr GHOST_NDOFManager3Dconnexion_InstallConnexionHandlers(
+ ConnexionMessageHandlerProc messageHandler,
+ ConnexionAddedHandlerProc addedHandler,
+ ConnexionRemovedHandlerProc removedHandler)
+{
+ return InstallConnexionHandlers( messageHandler, addedHandler, removedHandler);
}
-UInt16 GHOST_NDOFManager3Dconnexion_RegisterConnexionClient (UInt32 signature, UInt8 *name, UInt16 mode, UInt32 mask) {
- return RegisterConnexionClient(signature, name, mode, mask);
-};
-void GHOST_NDOFManager3Dconnexion_SetConnexionClientButtonMask (UInt16 clientID, UInt32 buttonMask){
- return SetConnexionClientButtonMask( clientID, buttonMask);
-};
-void GHOST_NDOFManager3Dconnexion_UnregisterConnexionClient (UInt16 clientID){
- return UnregisterConnexionClient( clientID);
-};
-OSErr GHOST_NDOFManager3Dconnexion_InstallConnexionHandlers (ConnexionMessageHandlerProc messageHandler, ConnexionAddedHandlerProc addedHandler, ConnexionRemovedHandlerProc removedHandler){
- return InstallConnexionHandlers( messageHandler, addedHandler, removedHandler);
-
-
-};
-void GHOST_NDOFManager3Dconnexion_CleanupConnexionHandlers (void){
- return CleanupConnexionHandlers();
-};
-OSErr GHOST_NDOFManager3Dconnexion_ConnexionControl(UInt32 message, SInt32 param, SInt32 *result){
-return ConnexionControl( message, param, result);
+void GHOST_NDOFManager3Dconnexion_CleanupConnexionHandlers(void)
+{
+ return CleanupConnexionHandlers();
}
+OSErr GHOST_NDOFManager3Dconnexion_ConnexionControl(UInt32 message, SInt32 param, SInt32 *result)
+{
+ return ConnexionControl( message, param, result);
+}
#endif // WITH_INPUT_NDOF
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 013d1e09066..fcf39523917 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -1025,8 +1025,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType,
}
switch (eventType) {
case GHOST_kEventWindowClose:
- // check for index 1 and discard close for mainwindow as it would quit blender without dialog
- if ([windowsList count] > 1 && (window->getCocoaWindow() != [windowsList objectAtIndex:1])) {
+ // check for index of mainwindow as it would quit blender without dialog and discard
+ if ([windowsList count] > 1 && window->getCocoaWindow() != [windowsList objectAtIndex:[windowsList count] - 1]) {
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
}
else {
@@ -1771,6 +1771,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
if ((keyCode > 266) && (keyCode < 271))
utf8_buf[0] = '\0';
+ /* no text with command key pressed */
+ if (m_modifierMask & NSCommandKeyMask)
+ utf8_buf[0] = '\0';
+
if ((keyCode == GHOST_kKeyQ) && (m_modifierMask & NSCommandKeyMask))
break; //Cmd-Q is directly handled by Cocoa
diff --git a/intern/ghost/intern/GHOST_SystemPathsX11.cpp b/intern/ghost/intern/GHOST_SystemPathsX11.cpp
index 50eb68d9264..e2d9733a9b2 100644
--- a/intern/ghost/intern/GHOST_SystemPathsX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemPathsX11.cpp
@@ -74,13 +74,16 @@ const GHOST_TUns8 *GHOST_SystemPathsX11::getSystemDir(int, const char *versionst
const GHOST_TUns8 *GHOST_SystemPathsX11::getUserDir(int version, const char *versionstr) const
{
static string user_path = "";
+ static int last_version = 0;
/* in blender 2.64, we migrate to XDG. to ensure the copy previous settings
* operator works we give a different path depending on the requested version */
if (version < 264) {
- if (user_path.empty()) {
+ if (user_path.empty() || last_version != version) {
const char *home = getenv("HOME");
+ last_version = version;
+
if (home) {
user_path = string(home) + "/.blender/" + versionstr;
}
@@ -91,9 +94,11 @@ const GHOST_TUns8 *GHOST_SystemPathsX11::getUserDir(int version, const char *ver
return (GHOST_TUns8 *)user_path.c_str();
}
else {
- if (user_path.empty()) {
+ if (user_path.empty() || last_version != version) {
const char *home = getenv("XDG_CONFIG_HOME");
+ last_version = version;
+
if (home) {
user_path = string(home) + "/blender/" + versionstr;
}
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index a409f5c357a..8290f4ee205 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -176,44 +176,58 @@ GHOST_WindowWin32::GHOST_WindowWin32(
}
if (state != GHOST_kWindowStateFullScreen) {
- RECT rect, desktop;
- int wintype = WS_OVERLAPPEDWINDOW;
+ RECT rect;
+ MONITORINFO monitor;
+ GHOST_TUns32 tw, th;
- if (m_parentWindowHwnd != 0) {
- wintype = WS_CHILD;
- /* check against parent window if given */
- GetWindowRect((HWND)m_parentWindowHwnd, &rect);
- }
- else {
- int framex = GetSystemMetrics(SM_CXSIZEFRAME);
- int framey = GetSystemMetrics(SM_CYSIZEFRAME);
- int caption = GetSystemMetrics(SM_CYCAPTION);
-
- /* set up total window rect, taking in account window decorations. */
- rect.left = left - framex;
- rect.right = rect.left + width + framex*2;
- rect.top = top - (caption + framey);
- rect.bottom = rect.top + height + (caption + framey * 2);
- }
+ width += GetSystemMetrics(SM_CXSIZEFRAME) * 2;
+ height += GetSystemMetrics(SM_CYSIZEFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
+
+ rect.left = left;
+ rect.right = left + width;
+ rect.top = top;
+ rect.bottom = top + height;
+
+ monitor.cbSize = sizeof(monitor);
+ monitor.dwFlags = 0;
+
+ // take taskbar into account
+ GetMonitorInfo(MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST), &monitor);
- /* ask how large virtual screen is */
- desktop.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
- desktop.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
- desktop.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
- desktop.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+ th = monitor.rcWork.bottom - monitor.rcWork.top;
+ tw = monitor.rcWork.right - monitor.rcWork.left;
- /* virtual screen (desktop) bound checks */
- if (rect.left < desktop.left) rect.left = desktop.left;
- if (rect.top < desktop.top) rect.top = desktop.top;
- if (rect.bottom > desktop.bottom) rect.bottom = desktop.bottom;
- if (rect.right > desktop.right) rect.right = desktop.right;
+ if (tw < width)
+ {
+ width = tw;
+ left = monitor.rcWork.left;
+ }
+ else if (monitor.rcWork.right < left + (int)width)
+ left = monitor.rcWork.right - width;
+ else if (left < monitor.rcWork.left)
+ left = monitor.rcWork.left;
- /* dimension vars to use in window creation */
- left = rect.left;
- top = rect.top;
- width = rect.right - rect.left;
- height = rect.bottom - rect.top;
+ if (th < height)
+ {
+ height = th;
+ top = monitor.rcWork.top;
+ }
+ else if (monitor.rcWork.bottom < top + (int)height)
+ top = monitor.rcWork.bottom - height;
+ else if (top < monitor.rcWork.top)
+ top = monitor.rcWork.top;
+ int wintype = WS_OVERLAPPEDWINDOW;
+ if (m_parentWindowHwnd != 0)
+ {
+ wintype = WS_CHILD;
+ GetWindowRect((HWND)m_parentWindowHwnd, &rect);
+ left = 0;
+ top = 0;
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+ }
+
wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
m_hWnd = ::CreateWindowW(
s_windowClassName, // pointer to registered class name
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 25c74a0a6cb..c32b2727c4c 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -65,6 +65,14 @@ typedef struct {
long input_mode;
} MotifWmHints;
+// Workaround for MESA bug #54080
+// https://bugs.freedesktop.org/show_bug.cgi?id=54080()
+#define SWAP_INTERVALS_WORKAROUND
+
+#ifdef SWAP_INTERVALS_WORKAROUND
+static bool g_swap_interval_disabled = false;
+#endif // SWAP_INTERVALS_WORKAROUND
+
#define MWM_HINTS_DECORATIONS (1L << 1)
@@ -1519,18 +1527,67 @@ endFullScreen() const
GHOST_TSuccess
GHOST_WindowX11::
setSwapInterval(int interval) {
- if (!GLX_EXT_swap_control)
+ if (!GLX_EXT_swap_control || !glXSwapIntervalEXT
+#ifdef SWAP_INTERVALS_WORKAROUND
+ || g_swap_interval_disabled
+#endif // SWAP_INTERVALS_WORKAROUND
+ )
+ {
return GHOST_kFailure;
+ }
glXSwapIntervalEXT(m_display, m_window, interval);
return GHOST_kSuccess;
}
+#ifdef SWAP_INTERVALS_WORKAROUND
+static int QueryDrawable_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
+{
+ fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
+ theEvent->error_code, theEvent->request_code);
+ if (!g_swap_interval_disabled) {
+ fprintf(stderr, "Disabling SWAP INTERVALS extension\n");
+ g_swap_interval_disabled = true;
+ }
+ return 0;
+}
+
+static int QueryDrawable_ApplicationIOErrorHandler(Display *display)
+{
+ fprintf(stderr, "Ignoring Xlib error: error IO\n");
+ if (!g_swap_interval_disabled) {
+ fprintf(stderr, "Disabling SWAP INTERVALS extension\n");
+ g_swap_interval_disabled = true;
+ }
+ return 0;
+}
+#endif // SWAP_INTERVALS_WORKAROUND
+
int
GHOST_WindowX11::
getSwapInterval() {
if (GLX_EXT_swap_control) {
- unsigned int value;
+#ifdef SWAP_INTERVALS_WORKAROUND
+ /* XXX: Current MESA driver will give GLXBadDrawable for all
+ * the glXQueryDrawable requests with direct contexts.
+ *
+ * To prevent crashes and unexpected behaviors, we will
+ * disable swap intervals extension if query fails here.
+ * (because if we will override interval without having
+ * old value we couldn't restore it properly).
+ */
+ XErrorHandler old_handler = XSetErrorHandler(QueryDrawable_ApplicationErrorHandler);
+ XIOErrorHandler old_handler_io = XSetIOErrorHandler(QueryDrawable_ApplicationIOErrorHandler);
+#endif // SWAP_INTERVALS_WORKAROUND
+
+ unsigned int value = 0;
glXQueryDrawable(m_display, m_window, GLX_SWAP_INTERVAL_EXT, &value);
+
+#ifdef SWAP_INTERVALS_WORKAROUND
+ /* Restore handler */
+ (void) XSetErrorHandler(old_handler);
+ (void) XSetIOErrorHandler(old_handler_io);
+#endif // SWAP_INTERVALS_WORKAROUND
+
return (int)value;
}
return 0;
diff --git a/intern/guardedalloc/CMakeLists.txt b/intern/guardedalloc/CMakeLists.txt
index 1e140c5b674..b7a59da7813 100644
--- a/intern/guardedalloc/CMakeLists.txt
+++ b/intern/guardedalloc/CMakeLists.txt
@@ -34,11 +34,11 @@ set(INC_SYS
set(SRC
./intern/mallocn.c
+ ./intern/mallocn_guarded_impl.c
+ ./intern/mallocn_lockfree_impl.c
MEM_guardedalloc.h
-
- # include here since its a header-only
- ../atomic/atomic_ops.h
+ ./intern/mallocn_intern.h
)
if(WIN32 AND NOT UNIX)
@@ -49,12 +49,6 @@ if(WIN32 AND NOT UNIX)
)
endif()
-if (WITH_GUARDEDALLOC)
- add_definitions(-DWITH_GUARDEDALLOC)
-else()
- message(WARNING "Disabling GuardedAlloc is experemental, use at own risk!")
-endif()
-
blender_add_lib(bf_intern_guardedalloc "${SRC}" "${INC}" "${INC_SYS}")
# Override C++ alloc, optional.
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
index d5ba2f5bd68..4fb68965338 100644
--- a/intern/guardedalloc/MEM_guardedalloc.h
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -62,11 +62,9 @@
#include <stdio.h> /* needed for FILE* */
-/* needed for uintptr_t, exception, dont use BLI anywhere else in MEM_* */
+/* needed for uintptr_t and attributes, exception, dont use BLI anywhere else in MEM_* */
#include "../../source/blender/blenlib/BLI_sys_types.h"
-
-/* some GNU attributes are only available from GCC 4.3 */
-#define MEM_GNU_ATTRIBUTES (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403))
+#include "../../source/blender/blenlib/BLI_compiler_attrs.h"
#ifdef __cplusplus
extern "C" {
@@ -75,57 +73,36 @@ extern "C" {
/** Returns the length of the allocated memory segment pointed at
* by vmemh. If the pointer was not previously allocated by this
* module, the result is undefined.*/
- size_t MEM_allocN_len(const void *vmemh)
-#if MEM_GNU_ATTRIBUTES
- __attribute__((warn_unused_result))
-#endif
- ;
+ extern size_t (*MEM_allocN_len)(const void *vmemh) ATTR_WARN_UNUSED_RESULT;
/**
* Release memory previously allocatred by this module.
*/
- void MEM_freeN(void *vmemh);
+ extern void (*MEM_freeN)(void *vmemh);
#if 0 /* UNUSED */
/**
* Return zero if memory is not in allocated list
*/
- short MEM_testN(void *vmemh);
+ extern short (*MEM_testN)(void *vmemh);
#endif
/**
* Duplicates a block of memory, and returns a pointer to the
* newly allocated block. */
- void *MEM_dupallocN(const void *vmemh)
-#if MEM_GNU_ATTRIBUTES
- __attribute__((malloc))
- __attribute__((warn_unused_result))
-#endif
- ;
+ extern void *(*MEM_dupallocN)(const void *vmemh) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT;
/**
* Reallocates a block of memory, and returns pointer to the newly
* allocated block, the old one is freed. this is not as optimized
* as a system realloc but just makes a new allocation and copies
* over from existing memory. */
- void *MEM_reallocN_id(void *vmemh, size_t len, const char *str)
-#if MEM_GNU_ATTRIBUTES
- __attribute__((malloc))
- __attribute__((warn_unused_result))
- __attribute__((alloc_size(2)))
-#endif
- ;
+ extern void *(*MEM_reallocN_id)(void *vmemh, size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(2);
/**
* A variant of realloc which zeros new bytes
*/
- void *MEM_recallocN_id(void *vmemh, size_t len, const char *str)
-#if MEM_GNU_ATTRIBUTES
- __attribute__((malloc))
- __attribute__((warn_unused_result))
- __attribute__((alloc_size(2)))
-#endif
- ;
+ extern void *(*MEM_recallocN_id)(void *vmemh, size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(2);
#define MEM_reallocN(vmemh, len) MEM_reallocN_id(vmemh, len, __func__)
#define MEM_recallocN(vmemh, len) MEM_recallocN_id(vmemh, len, __func__)
@@ -134,97 +111,79 @@ extern "C" {
* Allocate a block of memory of size len, with tag name str. The
* memory is cleared. The name must be static, because only a
* pointer to it is stored ! */
- void *MEM_callocN(size_t len, const char *str)
-#if MEM_GNU_ATTRIBUTES
- __attribute__((malloc))
- __attribute__((warn_unused_result))
- __attribute__((nonnull(2)))
- __attribute__((alloc_size(1)))
-#endif
- ;
+ extern void *(*MEM_callocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
/**
* Allocate a block of memory of size len, with tag name str. The
* name must be a static, because only a pointer to it is stored !
* */
- void *MEM_mallocN(size_t len, const char *str)
-#if MEM_GNU_ATTRIBUTES
- __attribute__((malloc))
- __attribute__((warn_unused_result))
- __attribute__((nonnull(2)))
- __attribute__((alloc_size(1)))
-#endif
- ;
+ extern void *(*MEM_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
/**
* Same as callocN, clears memory and uses mmap (disk cached) if supported.
* Can be free'd with MEM_freeN as usual.
* */
- void *MEM_mapallocN(size_t len, const char *str)
-#if MEM_GNU_ATTRIBUTES
- __attribute__((malloc))
- __attribute__((warn_unused_result))
- __attribute__((nonnull(2)))
- __attribute__((alloc_size(1)))
-#endif
- ;
+ extern void *(*MEM_mapallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
/** Print a list of the names and sizes of all allocated memory
* blocks. as a python dict for easy investigation */
- void MEM_printmemlist_pydict(void);
+ extern void (*MEM_printmemlist_pydict)(void);
/** Print a list of the names and sizes of all allocated memory
* blocks. */
- void MEM_printmemlist(void);
+ extern void (*MEM_printmemlist)(void);
/** calls the function on all allocated memory blocks. */
- void MEM_callbackmemlist(void (*func)(void *));
+ extern void (*MEM_callbackmemlist)(void (*func)(void *));
/** Print statistics about memory usage */
- void MEM_printmemlist_stats(void);
+ extern void (*MEM_printmemlist_stats)(void);
/** Set the callback function for error output. */
- void MEM_set_error_callback(void (*func)(const char *));
+ extern void (*MEM_set_error_callback)(void (*func)(const char *));
/**
* Are the start/end block markers still correct ?
*
* @retval 0 for correct memory, 1 for corrupted memory. */
- bool MEM_check_memory_integrity(void);
+ extern bool (*MEM_check_memory_integrity)(void);
/** Set thread locking functions for safe memory allocation from multiple
* threads, pass NULL pointers to disable thread locking again. */
- void MEM_set_lock_callback(void (*lock)(void), void (*unlock)(void));
+ extern void (*MEM_set_lock_callback)(void (*lock)(void), void (*unlock)(void));
/** Attempt to enforce OSX (or other OS's) to have malloc and stack nonzero */
- void MEM_set_memory_debug(void);
+ extern void (*MEM_set_memory_debug)(void);
/**
* Memory usage stats
* - MEM_get_memory_in_use is all memory
* - MEM_get_mapped_memory_in_use is a subset of all memory */
- uintptr_t MEM_get_memory_in_use(void);
+ extern uintptr_t (*MEM_get_memory_in_use)(void);
/** Get mapped memory usage. */
- uintptr_t MEM_get_mapped_memory_in_use(void);
+ extern uintptr_t (*MEM_get_mapped_memory_in_use)(void);
/** Get amount of memory blocks in use. */
- unsigned int MEM_get_memory_blocks_in_use(void);
+ extern unsigned int (*MEM_get_memory_blocks_in_use)(void);
/** Reset the peak memory statistic to zero. */
- void MEM_reset_peak_memory(void);
+ extern void (*MEM_reset_peak_memory)(void);
/** Get the peak memory usage in bytes, including mmap allocations. */
- size_t MEM_get_peak_memory(void)
-#if MEM_GNU_ATTRIBUTES
- __attribute__((warn_unused_result))
-#endif
- ;
+ extern size_t (*MEM_get_peak_memory)(void) ATTR_WARN_UNUSED_RESULT;
#define MEM_SAFE_FREE(v) if (v) { MEM_freeN(v); v = NULL; } (void)0
+/* overhead for lockfree allocator (use to avoid slop-space) */
+#define MEM_SIZE_OVERHEAD sizeof(size_t)
+#define MEM_SIZE_OPTIMAL(size) ((size) - MEM_SIZE_OVERHEAD)
+
#ifndef NDEBUG
-const char *MEM_name_ptr(void *vmemh);
+extern const char *(*MEM_name_ptr)(void *vmemh);
#endif
+/* Switch allocator to slower but fully guarded mode. */
+void MEM_use_guarded_allocator(void);
+
#ifdef __cplusplus
/* alloc funcs for C++ only */
#define MEM_CXX_CLASS_ALLOC_FUNCS(_id) \
@@ -244,6 +203,18 @@ public: \
MEM_freeN(mem); \
} \
+#if defined __GNUC__ || defined __sun
+# define OBJECT_GUARDED_NEW(type, args ...) \
+ new(MEM_mallocN(sizeof(type), __func__)) type(args)
+#else
+# define OBJECT_GUARDED_NEW(type, ...) \
+ new(MEM_mallocN(sizeof(type), __FUNCTION__)) type(__VA_ARGS__)
+#endif
+#define OBJECT_GUARDED_DELETE(what, type) \
+ { if(what) { \
+ ((type*)(what))->~type(); \
+ MEM_freeN(what); \
+ } } (void)0
#endif /* __cplusplus */
#ifdef __cplusplus
diff --git a/intern/guardedalloc/SConscript b/intern/guardedalloc/SConscript
index e3f787fe6c2..3bae808cc94 100644
--- a/intern/guardedalloc/SConscript
+++ b/intern/guardedalloc/SConscript
@@ -29,10 +29,12 @@ Import('env')
defs = []
-sources = ['intern/mallocn.c', 'intern/mmap_win.c']
-
-# could make this optional
-defs.append('WITH_GUARDEDALLOC')
+sources = [
+ 'intern/mallocn.c',
+ 'intern/mallocn_guarded_impl.c',
+ 'intern/mallocn_lockfree_impl.c',
+ 'intern/mmap_win.c'
+]
if env['WITH_BF_CXX_GUARDEDALLOC']:
sources.append('cpp/mallocn.cpp')
diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c
index e8102d98345..2ac01a6c7e4 100644
--- a/intern/guardedalloc/intern/mallocn.c
+++ b/intern/guardedalloc/intern/mallocn.c
@@ -32,1262 +32,64 @@
* Guarded memory allocation, and boundary-write detection.
*/
-#include <stdlib.h>
-#include <string.h> /* memcpy */
-#include <stdarg.h>
-#include <sys/types.h>
-
-/* mmap exception */
-#if defined(WIN32)
-# include "mmap_win.h"
-#else
-# include <sys/mman.h>
-#endif
-
-#if defined(_MSC_VER)
-# define __func__ __FUNCTION__
-#endif
-
-/* only for utility functions */
-#if defined(__GNUC__) && defined(__linux__)
-#include <malloc.h>
-# define HAVE_MALLOC_H
-#endif
-
#include "MEM_guardedalloc.h"
/* to ensure strict conversions */
#include "../../source/blender/blenlib/BLI_strict_flags.h"
-
-/* should always be defined except for experimental cases */
-#ifdef WITH_GUARDEDALLOC
-
-#include "atomic_ops.h"
-
-/* Only for debugging:
- * store original buffer's name when doing MEM_dupallocN
- * helpful to profile issues with non-freed "dup_alloc" buffers,
- * but this introduces some overhead to memory header and makes
- * things slower a bit, so better to keep disabled by default
- */
-//#define DEBUG_MEMDUPLINAME
-
-/* Only for debugging:
- * lets you count the allocations so as to find the allocator of unfreed memory
- * in situations where the leak is predictable */
-
-//#define DEBUG_MEMCOUNTER
-
-/* Only for debugging:
- * defining DEBUG_THREADS will enable check whether memory manager
- * is locked with a mutex when allocation is called from non-main
- * thread.
- *
- * This helps troubleshooting memory issues caused by the fact
- * guarded allocator is not thread-safe, however this check will
- * fail to check allocations from openmp threads.
- */
-//#define DEBUG_THREADS
-
-/* Only for debugging:
- * Defining DEBUG_BACKTRACE will store a backtrace from where
- * memory block was allocated and print this trace for all
- * unfreed blocks.
- */
-//#define DEBUG_BACKTRACE
-
-#ifdef DEBUG_BACKTRACE
-# define BACKTRACE_SIZE 100
-#endif
-
-#ifdef DEBUG_MEMCOUNTER
- /* set this to the value that isn't being freed */
-# define DEBUG_MEMCOUNTER_ERROR_VAL 0
-static int _mallocn_count = 0;
-
-/* breakpoint here */
-static void memcount_raise(const char *name)
-{
- fprintf(stderr, "%s: memcount-leak, %d\n", name, _mallocn_count);
-}
-#endif
-
-/* Blame Microsoft for LLP64 and no inttypes.h, quick workaround needed: */
-#if defined(WIN64)
-# define SIZET_FORMAT "%I64u"
-# define SIZET_ARG(a) ((unsigned long long)(a))
-#else
-# define SIZET_FORMAT "%lu"
-# define SIZET_ARG(a) ((unsigned long)(a))
-#endif
-
-#define SIZET_ALIGN_4(len) ((len + 3) & ~(size_t)3)
-
-
-/* --------------------------------------------------------------------- */
-/* Data definition */
-/* --------------------------------------------------------------------- */
-/* all memory chunks are put in linked lists */
-typedef struct localLink {
- struct localLink *next, *prev;
-} localLink;
-
-typedef struct localListBase {
- void *first, *last;
-} localListBase;
-
-/* note: keep this struct aligned (e.g., irix/gcc) - Hos */
-typedef struct MemHead {
- int tag1;
- size_t len;
- struct MemHead *next, *prev;
- const char *name;
- const char *nextname;
- int tag2;
- int mmap; /* if true, memory was mmapped */
-#ifdef DEBUG_MEMCOUNTER
- int _count;
-#endif
-
-#ifdef DEBUG_MEMDUPLINAME
- int need_free_name, pad;
-#endif
-
-#ifdef DEBUG_BACKTRACE
- void *backtrace[BACKTRACE_SIZE];
- int backtrace_size;
-#endif
-} MemHead;
-
-/* for openmp threading asserts, saves time troubleshooting
- * we may need to extend this if blender code starts using MEM_
- * functions inside OpenMP correctly with omp_set_lock() */
-
-#if 0 /* disable for now, only use to debug openmp code which doesn lock threads for malloc */
-#if defined(_OPENMP) && defined(DEBUG)
-# include <assert.h>
-# include <omp.h>
-# define DEBUG_OMP_MALLOC
-#endif
-#endif
-
-#ifdef DEBUG_THREADS
-# include <assert.h>
-# include <pthread.h>
-static pthread_t mainid;
-#endif
-
-#ifdef DEBUG_BACKTRACE
-# if defined(__linux__) || defined(__APPLE__)
-# include <execinfo.h>
-// Windows is not supported yet.
-//# elif defined(_MSV_VER)
-//# include <DbgHelp.h>
-# endif
-#endif
-
-typedef struct MemTail {
- int tag3, pad;
-} MemTail;
-
-
-/* --------------------------------------------------------------------- */
-/* local functions */
-/* --------------------------------------------------------------------- */
-
-static void addtail(volatile localListBase *listbase, void *vlink);
-static void remlink(volatile localListBase *listbase, void *vlink);
-static void rem_memblock(MemHead *memh);
-static void MemorY_ErroR(const char *block, const char *error);
-static const char *check_memlist(MemHead *memh);
-
-/* --------------------------------------------------------------------- */
-/* locally used defines */
-/* --------------------------------------------------------------------- */
-
-#ifdef __BIG_ENDIAN__
-# define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
-#else
-# define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
-#endif
-
-#define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O')
-#define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L')
-#define MEMTAG3 MAKE_ID('O', 'C', 'K', '!')
-#define MEMFREE MAKE_ID('F', 'R', 'E', 'E')
-
-#define MEMNEXT(x) \
- ((MemHead *)(((char *) x) - ((char *) &(((MemHead *)0)->next))))
-
-/* --------------------------------------------------------------------- */
-/* vars */
-/* --------------------------------------------------------------------- */
-
-
-static unsigned int totblock = 0;
-static size_t mem_in_use = 0, mmap_in_use = 0, peak_mem = 0;
-
-static volatile struct localListBase _membase;
-static volatile struct localListBase *membase = &_membase;
-static void (*error_callback)(const char *) = NULL;
-static void (*thread_lock_callback)(void) = NULL;
-static void (*thread_unlock_callback)(void) = NULL;
-
-static bool malloc_debug_memset = false;
-
-#ifdef malloc
-#undef malloc
-#endif
-
-#ifdef calloc
-#undef calloc
-#endif
-
-#ifdef free
-#undef free
-#endif
-
-
-/* --------------------------------------------------------------------- */
-/* implementation */
-/* --------------------------------------------------------------------- */
-
-#ifdef __GNUC__
-__attribute__ ((format(printf, 1, 2)))
-#endif
-static void print_error(const char *str, ...)
-{
- char buf[512];
- va_list ap;
-
- va_start(ap, str);
- vsnprintf(buf, sizeof(buf), str, ap);
- va_end(ap);
- buf[sizeof(buf) - 1] = '\0';
-
- if (error_callback) error_callback(buf);
-}
-
-static void mem_lock_thread(void)
-{
-#ifdef DEBUG_THREADS
- static int initialized = 0;
-
- if (initialized == 0) {
- /* assume first allocation happens from main thread */
- mainid = pthread_self();
- initialized = 1;
- }
-
- if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) {
- assert(!"Memory function is called from non-main thread without lock");
- }
-#endif
-
-#ifdef DEBUG_OMP_MALLOC
- assert(omp_in_parallel() == 0);
-#endif
-
- if (thread_lock_callback)
- thread_lock_callback();
-}
-
-static void mem_unlock_thread(void)
-{
-#ifdef DEBUG_THREADS
- if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) {
- assert(!"Thread lock was removed while allocation from thread is in progress");
- }
-#endif
-
- if (thread_unlock_callback)
- thread_unlock_callback();
-}
-
-bool MEM_check_memory_integrity(void)
-{
- const char *err_val = NULL;
- MemHead *listend;
- /* check_memlist starts from the front, and runs until it finds
- * the requested chunk. For this test, that's the last one. */
- listend = membase->last;
-
- err_val = check_memlist(listend);
-
- return (err_val != NULL);
-}
-
-
-void MEM_set_error_callback(void (*func)(const char *))
-{
- error_callback = func;
-}
-
-void MEM_set_lock_callback(void (*lock)(void), void (*unlock)(void))
-{
- thread_lock_callback = lock;
- thread_unlock_callback = unlock;
-}
-
-void MEM_set_memory_debug(void)
-{
- malloc_debug_memset = true;
-}
-
-size_t MEM_allocN_len(const void *vmemh)
-{
- if (vmemh) {
- const MemHead *memh = vmemh;
-
- memh--;
- return memh->len;
- }
- else {
- return 0;
- }
-}
-
-void *MEM_dupallocN(const void *vmemh)
-{
- void *newp = NULL;
-
- if (vmemh) {
- const MemHead *memh = vmemh;
- memh--;
-
-#ifndef DEBUG_MEMDUPLINAME
- if (memh->mmap)
- newp = MEM_mapallocN(memh->len, "dupli_mapalloc");
- else
- newp = MEM_mallocN(memh->len, "dupli_alloc");
-
- if (newp == NULL) return NULL;
-#else
- {
- MemHead *nmemh;
- char *name = malloc(strlen(memh->name) + 24);
-
- if (memh->mmap) {
- sprintf(name, "%s %s", "dupli_mapalloc", memh->name);
- newp = MEM_mapallocN(memh->len, name);
- }
- else {
- sprintf(name, "%s %s", "dupli_alloc", memh->name);
- newp = MEM_mallocN(memh->len, name);
- }
-
- if (newp == NULL) return NULL;
-
- nmemh = newp;
- nmemh--;
-
- nmemh->need_free_name = 1;
- }
-#endif
-
- memcpy(newp, vmemh, memh->len);
- }
-
- return newp;
-}
-
-void *MEM_reallocN_id(void *vmemh, size_t len, const char *str)
-{
- void *newp = NULL;
-
- if (vmemh) {
- MemHead *memh = vmemh;
- memh--;
-
- newp = MEM_mallocN(len, memh->name);
- if (newp) {
- if (len < memh->len) {
- /* shrink */
- memcpy(newp, vmemh, len);
- }
- else {
- /* grow (or remain same size) */
- memcpy(newp, vmemh, memh->len);
- }
- }
-
- MEM_freeN(vmemh);
- }
- else {
- newp = MEM_mallocN(len, str);
- }
-
- return newp;
-}
-
-void *MEM_recallocN_id(void *vmemh, size_t len, const char *str)
-{
- void *newp = NULL;
-
- if (vmemh) {
- MemHead *memh = vmemh;
- memh--;
-
- newp = MEM_mallocN(len, memh->name);
- if (newp) {
- if (len < memh->len) {
- /* shrink */
- memcpy(newp, vmemh, len);
- }
- else {
- memcpy(newp, vmemh, memh->len);
-
- if (len > memh->len) {
- /* grow */
- /* zero new bytes */
- memset(((char *)newp) + memh->len, 0, len - memh->len);
- }
- }
- }
-
- MEM_freeN(vmemh);
- }
- else {
- newp = MEM_callocN(len, str);
- }
-
- return newp;
-}
-
-#ifdef DEBUG_BACKTRACE
-# if defined(__linux__) || defined(__APPLE__)
-static void make_memhead_backtrace(MemHead *memh)
-{
- memh->backtrace_size = backtrace(memh->backtrace, BACKTRACE_SIZE);
-}
-
-static void print_memhead_backtrace(MemHead *memh)
-{
- char **strings;
- int i;
-
- strings = backtrace_symbols(memh->backtrace, memh->backtrace_size);
- for (i = 0; i < memh->backtrace_size; i++) {
- print_error(" %s\n", strings[i]);
- }
-
- free(strings);
-}
-# else
-static void make_memhead_backtrace(MemHead *memh)
-{
- (void) memh; /* Ignored. */
-}
-
-static void print_memhead_backtrace(MemHead *memh)
-{
- (void) memh; /* Ignored. */
-}
-# endif /* defined(__linux__) || defined(__APPLE__) */
-#endif /* DEBUG_BACKTRACE */
-
-static void make_memhead_header(MemHead *memh, size_t len, const char *str)
-{
- MemTail *memt;
-
- memh->tag1 = MEMTAG1;
- memh->name = str;
- memh->nextname = NULL;
- memh->len = len;
- memh->mmap = 0;
- memh->tag2 = MEMTAG2;
-
-#ifdef DEBUG_MEMDUPLINAME
- memh->need_free_name = 0;
-#endif
-
-#ifdef DEBUG_BACKTRACE
- make_memhead_backtrace(memh);
-#endif
-
- memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + len);
- memt->tag3 = MEMTAG3;
-
- atomic_add_u(&totblock, 1);
- atomic_add_z(&mem_in_use, len);
-
- mem_lock_thread();
- addtail(membase, &memh->next);
- if (memh->next) {
- memh->nextname = MEMNEXT(memh->next)->name;
- }
- peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem;
- mem_unlock_thread();
-}
-
-void *MEM_mallocN(size_t len, const char *str)
-{
- MemHead *memh;
-
- len = SIZET_ALIGN_4(len);
-
- memh = (MemHead *)malloc(len + sizeof(MemHead) + sizeof(MemTail));
-
- if (memh) {
- make_memhead_header(memh, len, str);
- if (malloc_debug_memset && len)
- memset(memh + 1, 255, len);
-
-#ifdef DEBUG_MEMCOUNTER
- if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
- memcount_raise(__func__);
- memh->_count = _mallocn_count++;
-#endif
- return (++memh);
- }
- print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
- SIZET_ARG(len), str, (unsigned int) mem_in_use);
- return NULL;
-}
-
-void *MEM_callocN(size_t len, const char *str)
-{
- MemHead *memh;
-
- len = SIZET_ALIGN_4(len);
-
- memh = (MemHead *)calloc(len + sizeof(MemHead) + sizeof(MemTail), 1);
-
- if (memh) {
- make_memhead_header(memh, len, str);
-#ifdef DEBUG_MEMCOUNTER
- if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
- memcount_raise(__func__);
- memh->_count = _mallocn_count++;
-#endif
- return (++memh);
- }
- print_error("Calloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
- SIZET_ARG(len), str, (unsigned int) mem_in_use);
- return NULL;
-}
-
-/* note; mmap returns zero'd memory */
-void *MEM_mapallocN(size_t len, const char *str)
-{
- MemHead *memh;
-
- len = SIZET_ALIGN_4(len);
-
-#if defined(WIN32)
- /* our windows mmap implementation is not thread safe */
- mem_lock_thread();
-#endif
- memh = mmap(NULL, len + sizeof(MemHead) + sizeof(MemTail),
- PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
-#if defined(WIN32)
- mem_unlock_thread();
-#endif
-
- if (memh != (MemHead *)-1) {
- make_memhead_header(memh, len, str);
- memh->mmap = 1;
- atomic_add_z(&mmap_in_use, len);
- mem_lock_thread();
- peak_mem = mmap_in_use > peak_mem ? mmap_in_use : peak_mem;
- mem_unlock_thread();
-#ifdef DEBUG_MEMCOUNTER
- if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
- memcount_raise(__func__);
- memh->_count = _mallocn_count++;
-#endif
- return (++memh);
- }
- else {
- print_error("Mapalloc returns null, fallback to regular malloc: "
- "len=" SIZET_FORMAT " in %s, total %u\n",
- SIZET_ARG(len), str, (unsigned int) mmap_in_use);
- return MEM_callocN(len, str);
- }
-}
-
-/* Memory statistics print */
-typedef struct MemPrintBlock {
- const char *name;
- uintptr_t len;
- int items;
-} MemPrintBlock;
-
-static int compare_name(const void *p1, const void *p2)
-{
- const MemPrintBlock *pb1 = (const MemPrintBlock *)p1;
- const MemPrintBlock *pb2 = (const MemPrintBlock *)p2;
-
- return strcmp(pb1->name, pb2->name);
-}
-
-static int compare_len(const void *p1, const void *p2)
-{
- const MemPrintBlock *pb1 = (const MemPrintBlock *)p1;
- const MemPrintBlock *pb2 = (const MemPrintBlock *)p2;
-
- if (pb1->len < pb2->len)
- return 1;
- else if (pb1->len == pb2->len)
- return 0;
- else
- return -1;
-}
-
-void MEM_printmemlist_stats(void)
-{
- MemHead *membl;
- MemPrintBlock *pb, *printblock;
- unsigned int totpb, a, b;
-#ifdef HAVE_MALLOC_H
- size_t mem_in_use_slop = 0;
-#endif
- mem_lock_thread();
-
- /* put memory blocks into array */
- printblock = malloc(sizeof(MemPrintBlock) * totblock);
-
- pb = printblock;
- totpb = 0;
-
- membl = membase->first;
- if (membl) membl = MEMNEXT(membl);
-
- while (membl) {
- pb->name = membl->name;
- pb->len = membl->len;
- pb->items = 1;
-
- totpb++;
- pb++;
-
-#ifdef HAVE_MALLOC_H
- if (!membl->mmap) {
- mem_in_use_slop += (sizeof(MemHead) + sizeof(MemTail) +
- malloc_usable_size((void *)membl)) - membl->len;
- }
-#endif
-
- if (membl->next)
- membl = MEMNEXT(membl->next);
- else break;
- }
-
- /* sort by name and add together blocks with the same name */
- qsort(printblock, totpb, sizeof(MemPrintBlock), compare_name);
- for (a = 0, b = 0; a < totpb; a++) {
- if (a == b) {
- continue;
- }
- else if (strcmp(printblock[a].name, printblock[b].name) == 0) {
- printblock[b].len += printblock[a].len;
- printblock[b].items++;
- }
- else {
- b++;
- memcpy(&printblock[b], &printblock[a], sizeof(MemPrintBlock));
- }
- }
- totpb = b + 1;
-
- /* sort by length and print */
- qsort(printblock, totpb, sizeof(MemPrintBlock), compare_len);
- printf("\ntotal memory len: %.3f MB\n",
- (double)mem_in_use / (double)(1024 * 1024));
- printf("peak memory len: %.3f MB\n",
- (double)peak_mem / (double)(1024 * 1024));
-#ifdef HAVE_MALLOC_H
- printf("slop memory len: %.3f MB\n",
- (double)mem_in_use_slop / (double)(1024 * 1024));
-#endif
- printf(" ITEMS TOTAL-MiB AVERAGE-KiB TYPE\n");
- for (a = 0, pb = printblock; a < totpb; a++, pb++) {
- printf("%6d (%8.3f %8.3f) %s\n",
- pb->items, (double)pb->len / (double)(1024 * 1024),
- (double)pb->len / 1024.0 / (double)pb->items, pb->name);
- }
- free(printblock);
-
- mem_unlock_thread();
-
-#ifdef HAVE_MALLOC_H /* GLIBC only */
- printf("System Statistics:\n");
- malloc_stats();
-#endif
-}
-
-static const char mem_printmemlist_pydict_script[] =
-"mb_userinfo = {}\n"
-"totmem = 0\n"
-"for mb_item in membase:\n"
-" mb_item_user_size = mb_userinfo.setdefault(mb_item['name'], [0,0])\n"
-" mb_item_user_size[0] += 1 # Add a user\n"
-" mb_item_user_size[1] += mb_item['len'] # Increment the size\n"
-" totmem += mb_item['len']\n"
-"print('(membase) items:', len(membase), '| unique-names:',\n"
-" len(mb_userinfo), '| total-mem:', totmem)\n"
-"mb_userinfo_sort = list(mb_userinfo.items())\n"
-"for sort_name, sort_func in (('size', lambda a: -a[1][1]),\n"
-" ('users', lambda a: -a[1][0]),\n"
-" ('name', lambda a: a[0])):\n"
-" print('\\nSorting by:', sort_name)\n"
-" mb_userinfo_sort.sort(key = sort_func)\n"
-" for item in mb_userinfo_sort:\n"
-" print('name:%%s, users:%%i, len:%%i' %%\n"
-" (item[0], item[1][0], item[1][1]))\n";
-
-/* Prints in python syntax for easy */
-static void MEM_printmemlist_internal(int pydict)
-{
- MemHead *membl;
-
- mem_lock_thread();
-
- membl = membase->first;
- if (membl) membl = MEMNEXT(membl);
-
- if (pydict) {
- print_error("# membase_debug.py\n");
- print_error("membase = [\n");
- }
- while (membl) {
- if (pydict) {
- fprintf(stderr,
- " {'len':" SIZET_FORMAT ", "
- "'name':'''%s''', "
- "'pointer':'%p'},\n",
- SIZET_ARG(membl->len), membl->name, (void *)(membl + 1));
- }
- else {
-#ifdef DEBUG_MEMCOUNTER
- print_error("%s len: " SIZET_FORMAT " %p, count: %d\n",
- membl->name, SIZET_ARG(membl->len), membl + 1,
- membl->_count);
-#else
- print_error("%s len: " SIZET_FORMAT " %p\n",
- membl->name, SIZET_ARG(membl->len), membl + 1);
-#endif
-#ifdef DEBUG_BACKTRACE
- print_memhead_backtrace(membl);
-#endif
- }
- if (membl->next)
- membl = MEMNEXT(membl->next);
- else break;
- }
- if (pydict) {
- fprintf(stderr, "]\n\n");
- fprintf(stderr, mem_printmemlist_pydict_script);
- }
-
- mem_unlock_thread();
-}
-
-void MEM_callbackmemlist(void (*func)(void *))
-{
- MemHead *membl;
-
- mem_lock_thread();
-
- membl = membase->first;
- if (membl) membl = MEMNEXT(membl);
-
- while (membl) {
- func(membl + 1);
- if (membl->next)
- membl = MEMNEXT(membl->next);
- else break;
- }
-
- mem_unlock_thread();
-}
-
-#if 0
-short MEM_testN(void *vmemh)
-{
- MemHead *membl;
-
- mem_lock_thread();
-
- membl = membase->first;
- if (membl) membl = MEMNEXT(membl);
-
- while (membl) {
- if (vmemh == membl + 1) {
- mem_unlock_thread();
- return 1;
- }
-
- if (membl->next)
- membl = MEMNEXT(membl->next);
- else break;
- }
-
- mem_unlock_thread();
-
- print_error("Memoryblock %p: pointer not in memlist\n", vmemh);
- return 0;
-}
-#endif
-
-void MEM_printmemlist(void)
-{
- MEM_printmemlist_internal(0);
-}
-void MEM_printmemlist_pydict(void)
-{
- MEM_printmemlist_internal(1);
-}
-
-void MEM_freeN(void *vmemh)
-{
- MemTail *memt;
- MemHead *memh = vmemh;
- const char *name;
-
- if (memh == NULL) {
- MemorY_ErroR("free", "attempt to free NULL pointer");
- /* print_error(err_stream, "%d\n", (memh+4000)->tag1); */
- return;
- }
-
- if (sizeof(intptr_t) == 8) {
- if (((intptr_t) memh) & 0x7) {
- MemorY_ErroR("free", "attempt to free illegal pointer");
- return;
- }
- }
- else {
- if (((intptr_t) memh) & 0x3) {
- MemorY_ErroR("free", "attempt to free illegal pointer");
- return;
- }
- }
-
- memh--;
- if (memh->tag1 == MEMFREE && memh->tag2 == MEMFREE) {
- MemorY_ErroR(memh->name, "double free");
- return;
- }
-
- if ((memh->tag1 == MEMTAG1) &&
- (memh->tag2 == MEMTAG2) &&
- ((memh->len & 0x3) == 0))
- {
- memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + memh->len);
- if (memt->tag3 == MEMTAG3) {
-
- memh->tag1 = MEMFREE;
- memh->tag2 = MEMFREE;
- memt->tag3 = MEMFREE;
- /* after tags !!! */
- rem_memblock(memh);
-
- return;
- }
- MemorY_ErroR(memh->name, "end corrupt");
- name = check_memlist(memh);
- if (name != NULL) {
- if (name != memh->name) MemorY_ErroR(name, "is also corrupt");
- }
- }
- else {
- mem_lock_thread();
- name = check_memlist(memh);
- mem_unlock_thread();
- if (name == NULL)
- MemorY_ErroR("free", "pointer not in memlist");
- else
- MemorY_ErroR(name, "error in header");
- }
-
- totblock--;
- /* here a DUMP should happen */
-
- return;
-}
-
-/* --------------------------------------------------------------------- */
-/* local functions */
-/* --------------------------------------------------------------------- */
-
-static void addtail(volatile localListBase *listbase, void *vlink)
-{
- struct localLink *link = vlink;
-
- /* for a generic API error checks here is fine but
- * the limited use here they will never be NULL */
-#if 0
- if (link == NULL) return;
- if (listbase == NULL) return;
-#endif
-
- link->next = NULL;
- link->prev = listbase->last;
-
- if (listbase->last) ((struct localLink *)listbase->last)->next = link;
- if (listbase->first == NULL) listbase->first = link;
- listbase->last = link;
-}
-
-static void remlink(volatile localListBase *listbase, void *vlink)
-{
- struct localLink *link = vlink;
-
- /* for a generic API error checks here is fine but
- * the limited use here they will never be NULL */
-#if 0
- if (link == NULL) return;
- if (listbase == NULL) return;
-#endif
-
- if (link->next) link->next->prev = link->prev;
- if (link->prev) link->prev->next = link->next;
-
- if (listbase->last == link) listbase->last = link->prev;
- if (listbase->first == link) listbase->first = link->next;
-}
-
-static void rem_memblock(MemHead *memh)
-{
- mem_lock_thread();
- remlink(membase, &memh->next);
- if (memh->prev) {
- if (memh->next)
- MEMNEXT(memh->prev)->nextname = MEMNEXT(memh->next)->name;
- else
- MEMNEXT(memh->prev)->nextname = NULL;
- }
- mem_unlock_thread();
-
- atomic_sub_u(&totblock, 1);
- atomic_sub_z(&mem_in_use, memh->len);
-
-#ifdef DEBUG_MEMDUPLINAME
- if (memh->need_free_name)
- free((char *) memh->name);
-#endif
-
- if (memh->mmap) {
- atomic_sub_z(&mmap_in_use, memh->len);
-#if defined(WIN32)
- /* our windows mmap implementation is not thread safe */
- mem_lock_thread();
-#endif
- if (munmap(memh, memh->len + sizeof(MemHead) + sizeof(MemTail)))
- printf("Couldn't unmap memory %s\n", memh->name);
-#if defined(WIN32)
- mem_unlock_thread();
-#endif
- }
- else {
- if (malloc_debug_memset && memh->len)
- memset(memh + 1, 255, memh->len);
- free(memh);
- }
-}
-
-static void MemorY_ErroR(const char *block, const char *error)
-{
- print_error("Memoryblock %s: %s\n", block, error);
-
-#ifdef WITH_ASSERT_ABORT
- abort();
-#endif
-}
-
-static const char *check_memlist(MemHead *memh)
-{
- MemHead *forw, *back, *forwok, *backok;
- const char *name;
-
- forw = membase->first;
- if (forw) forw = MEMNEXT(forw);
- forwok = NULL;
- while (forw) {
- if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break;
- forwok = forw;
- if (forw->next) forw = MEMNEXT(forw->next);
- else forw = NULL;
- }
-
- back = (MemHead *) membase->last;
- if (back) back = MEMNEXT(back);
- backok = NULL;
- while (back) {
- if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break;
- backok = back;
- if (back->prev) back = MEMNEXT(back->prev);
- else back = NULL;
- }
-
- if (forw != back) return ("MORE THAN 1 MEMORYBLOCK CORRUPT");
-
- if (forw == NULL && back == NULL) {
- /* no wrong headers found then but in search of memblock */
-
- forw = membase->first;
- if (forw) forw = MEMNEXT(forw);
- forwok = NULL;
- while (forw) {
- if (forw == memh) break;
- if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break;
- forwok = forw;
- if (forw->next) forw = MEMNEXT(forw->next);
- else forw = NULL;
- }
- if (forw == NULL) return NULL;
-
- back = (MemHead *) membase->last;
- if (back) back = MEMNEXT(back);
- backok = NULL;
- while (back) {
- if (back == memh) break;
- if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break;
- backok = back;
- if (back->prev) back = MEMNEXT(back->prev);
- else back = NULL;
- }
- }
-
- if (forwok) name = forwok->nextname;
- else name = "No name found";
-
- if (forw == memh) {
- /* to be sure but this block is removed from the list */
- if (forwok) {
- if (backok) {
- forwok->next = (MemHead *)&backok->next;
- backok->prev = (MemHead *)&forwok->next;
- forwok->nextname = backok->name;
- }
- else {
- forwok->next = NULL;
- membase->last = (struct localLink *) &forwok->next;
- }
- }
- else {
- if (backok) {
- backok->prev = NULL;
- membase->first = &backok->next;
- }
- else {
- membase->first = membase->last = NULL;
- }
- }
- }
- else {
- MemorY_ErroR(name, "Additional error in header");
- return("Additional error in header");
- }
-
- return(name);
-}
-
-size_t MEM_get_peak_memory(void)
-{
- size_t _peak_mem;
-
- mem_lock_thread();
- _peak_mem = peak_mem;
- mem_unlock_thread();
-
- return _peak_mem;
-}
-
-void MEM_reset_peak_memory(void)
-{
- mem_lock_thread();
- peak_mem = 0;
- mem_unlock_thread();
-}
-
-uintptr_t MEM_get_memory_in_use(void)
-{
- uintptr_t _mem_in_use;
-
- mem_lock_thread();
- _mem_in_use = mem_in_use;
- mem_unlock_thread();
-
- return _mem_in_use;
-}
-
-uintptr_t MEM_get_mapped_memory_in_use(void)
-{
- uintptr_t _mmap_in_use;
-
- mem_lock_thread();
- _mmap_in_use = mmap_in_use;
- mem_unlock_thread();
-
- return _mmap_in_use;
-}
-
-unsigned int MEM_get_memory_blocks_in_use(void)
-{
- unsigned int _totblock;
-
- mem_lock_thread();
- _totblock = totblock;
- mem_unlock_thread();
-
- return _totblock;
-}
+#include "mallocn_intern.h"
+
+size_t (*MEM_allocN_len)(const void *vmemh) = MEM_lockfree_allocN_len;
+void (*MEM_freeN)(void *vmemh) = MEM_lockfree_freeN;
+void *(*MEM_dupallocN)(const void *vmemh) = MEM_lockfree_dupallocN;
+void *(*MEM_reallocN_id)(void *vmemh, size_t len, const char *str) = MEM_lockfree_reallocN_id;
+void *(*MEM_recallocN_id)(void *vmemh, size_t len, const char *str) = MEM_lockfree_recallocN_id;;
+void *(*MEM_callocN)(size_t len, const char *str) = MEM_lockfree_callocN;
+void *(*MEM_mallocN)(size_t len, const char *str) = MEM_lockfree_mallocN;
+void *(*MEM_mapallocN)(size_t len, const char *str) = MEM_lockfree_mapallocN;
+void (*MEM_printmemlist_pydict)(void) = MEM_lockfree_printmemlist_pydict;
+void (*MEM_printmemlist)(void) = MEM_lockfree_printmemlist;
+void (*MEM_callbackmemlist)(void (*func)(void *)) = MEM_lockfree_callbackmemlist;
+void (*MEM_printmemlist_stats)(void) = MEM_lockfree_printmemlist_stats;
+void (*MEM_set_error_callback)(void (*func)(const char *)) = MEM_lockfree_set_error_callback;
+bool (*MEM_check_memory_integrity)(void) = MEM_lockfree_check_memory_integrity;
+void (*MEM_set_lock_callback)(void (*lock)(void), void (*unlock)(void)) = MEM_lockfree_set_lock_callback;
+void (*MEM_set_memory_debug)(void) = MEM_lockfree_set_memory_debug;
+uintptr_t (*MEM_get_memory_in_use)(void) = MEM_lockfree_get_memory_in_use;
+uintptr_t (*MEM_get_mapped_memory_in_use)(void) = MEM_lockfree_get_mapped_memory_in_use;
+unsigned int (*MEM_get_memory_blocks_in_use)(void) = MEM_lockfree_get_memory_blocks_in_use;
+void (*MEM_reset_peak_memory)(void) = MEM_lockfree_reset_peak_memory;
+uintptr_t (*MEM_get_peak_memory)(void) = MEM_lockfree_get_peak_memory;
#ifndef NDEBUG
-const char *MEM_name_ptr(void *vmemh)
-{
- if (vmemh) {
- MemHead *memh = vmemh;
- memh--;
- return memh->name;
- }
- else {
- return "MEM_name_ptr(NULL)";
- }
-}
-#endif /* NDEBUG */
+const char *(*MEM_name_ptr)(void *vmemh) = MEM_lockfree_name_ptr;
+#endif
+
+void MEM_use_guarded_allocator(void)
+{
+ MEM_allocN_len = MEM_guarded_allocN_len;
+ MEM_freeN = MEM_guarded_freeN;
+ MEM_dupallocN = MEM_guarded_dupallocN;
+ MEM_reallocN_id = MEM_guarded_reallocN_id;
+ MEM_recallocN_id = MEM_guarded_recallocN_id;;
+ MEM_callocN = MEM_guarded_callocN;
+ MEM_mallocN = MEM_guarded_mallocN;
+ MEM_mapallocN = MEM_guarded_mapallocN;
+ MEM_printmemlist_pydict = MEM_guarded_printmemlist_pydict;
+ MEM_printmemlist = MEM_guarded_printmemlist;
+ MEM_callbackmemlist = MEM_guarded_callbackmemlist;
+ MEM_printmemlist_stats = MEM_guarded_printmemlist_stats;
+ MEM_set_error_callback = MEM_guarded_set_error_callback;
+ MEM_check_memory_integrity = MEM_guarded_check_memory_integrity;
+ MEM_set_lock_callback = MEM_guarded_set_lock_callback;
+ MEM_set_memory_debug = MEM_guarded_set_memory_debug;
+ MEM_get_memory_in_use = MEM_guarded_get_memory_in_use;
+ MEM_get_mapped_memory_in_use = MEM_guarded_get_mapped_memory_in_use;
+ MEM_get_memory_blocks_in_use = MEM_guarded_get_memory_blocks_in_use;
+ MEM_reset_peak_memory = MEM_guarded_reset_peak_memory;
+ MEM_get_peak_memory = MEM_guarded_get_peak_memory;
-#else /* !WITH_GUARDEDALLOC */
-
-#ifdef __GNUC__
-# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
-#else
-# define UNUSED(x) UNUSED_ ## x
+#ifndef NDEBUG
+ MEM_name_ptr = MEM_guarded_name_ptr;
#endif
-
-#include <malloc.h>
-
-size_t MEM_allocN_len(const void *vmemh)
-{
- return malloc_usable_size((void *)vmemh);
-}
-
-void MEM_freeN(void *vmemh)
-{
- free(vmemh);
-}
-
-void *MEM_dupallocN(const void *vmemh)
-{
- void *newp = NULL;
- if (vmemh) {
- const size_t prev_size = MEM_allocN_len(vmemh);
- newp = malloc(prev_size);
- memcpy(newp, vmemh, prev_size);
- }
- return newp;
-}
-
-void *MEM_reallocN_id(void *vmemh, size_t len, const char *UNUSED(str))
-{
- return realloc(vmemh, len);
}
-
-void *MEM_recallocN_id(void *vmemh, size_t len, const char *UNUSED(str))
-{
- void *newp = NULL;
-
- if (vmemh) {
- size_t vmemh_len = MEM_allocN_len(vmemh);
- newp = malloc(len);
- if (newp) {
- if (len < vmemh_len) {
- /* shrink */
- memcpy(newp, vmemh, len);
- }
- else {
- memcpy(newp, vmemh, vmemh_len);
-
- if (len > vmemh_len) {
- /* grow */
- /* zero new bytes */
- memset(((char *)newp) + vmemh_len, 0, len - vmemh_len);
- }
- }
- }
-
- free(vmemh);
- }
- else {
- newp = calloc(1, len);
- }
-
- return newp;
-}
-
-void *MEM_callocN(size_t len, const char *UNUSED(str))
-{
- return calloc(1, len);
-}
-
-void *MEM_mallocN(size_t len, const char *UNUSED(str))
-{
- return malloc(len);
-}
-
-void *MEM_mapallocN(size_t len, const char *UNUSED(str))
-{
- /* could us mmap */
- return calloc(1, len);
-}
-
-void MEM_printmemlist_pydict(void) {}
-void MEM_printmemlist(void) {}
-
-/* unused */
-void MEM_callbackmemlist(void (*func)(void *))
-{
- (void)func;
-}
-
-void MEM_printmemlist_stats(void) {}
-
-void MEM_set_error_callback(void (*func)(const char *))
-{
- (void)func;
-}
-
-int MEM_check_memory_integrity(void)
-{
- return 1;
-}
-
-void MEM_set_lock_callback(void (*lock)(void), void (*unlock)(void))
-{
- (void)lock;
- (void)unlock;
-}
-
-void MEM_set_memory_debug(void) {}
-
-uintptr_t MEM_get_memory_in_use(void)
-{
- struct mallinfo mi;
- mi = mallinfo();
- return mi.uordblks;
-}
-
-uintptr_t MEM_get_mapped_memory_in_use(void)
-{
- return MEM_get_memory_in_use();
-}
-
-int MEM_get_memory_blocks_in_use(void)
-{
- struct mallinfo mi;
- mi = mallinfo();
- return mi.smblks + mi.hblks;
-}
-
-/* dummy */
-void MEM_reset_peak_memory(void) {}
-
-uintptr_t MEM_get_peak_memory(void)
-{
- return MEM_get_memory_in_use();
-}
-
-#endif /* WITH_GUARDEDALLOC */
diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.c b/intern/guardedalloc/intern/mallocn_guarded_impl.c
new file mode 100644
index 00000000000..92392ce4dd3
--- /dev/null
+++ b/intern/guardedalloc/intern/mallocn_guarded_impl.c
@@ -0,0 +1,1114 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel
+ * Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file guardedalloc/intern/mallocn.c
+ * \ingroup MEM
+ *
+ * Guarded memory allocation, and boundary-write detection.
+ */
+
+#include <stdlib.h>
+#include <string.h> /* memcpy */
+#include <stdarg.h>
+#include <sys/types.h>
+
+#include "MEM_guardedalloc.h"
+
+/* to ensure strict conversions */
+#include "../../source/blender/blenlib/BLI_strict_flags.h"
+
+#include "mallocn_intern.h"
+#include "atomic_ops.h"
+
+/* Only for debugging:
+ * store original buffer's name when doing MEM_dupallocN
+ * helpful to profile issues with non-freed "dup_alloc" buffers,
+ * but this introduces some overhead to memory header and makes
+ * things slower a bit, so better to keep disabled by default
+ */
+//#define DEBUG_MEMDUPLINAME
+
+/* Only for debugging:
+ * lets you count the allocations so as to find the allocator of unfreed memory
+ * in situations where the leak is predictable */
+
+//#define DEBUG_MEMCOUNTER
+
+/* Only for debugging:
+ * defining DEBUG_THREADS will enable check whether memory manager
+ * is locked with a mutex when allocation is called from non-main
+ * thread.
+ *
+ * This helps troubleshooting memory issues caused by the fact
+ * guarded allocator is not thread-safe, however this check will
+ * fail to check allocations from openmp threads.
+ */
+//#define DEBUG_THREADS
+
+/* Only for debugging:
+ * Defining DEBUG_BACKTRACE will store a backtrace from where
+ * memory block was allocated and print this trace for all
+ * unfreed blocks.
+ */
+//#define DEBUG_BACKTRACE
+
+#ifdef DEBUG_BACKTRACE
+# define BACKTRACE_SIZE 100
+#endif
+
+#ifdef DEBUG_MEMCOUNTER
+ /* set this to the value that isn't being freed */
+# define DEBUG_MEMCOUNTER_ERROR_VAL 0
+static int _mallocn_count = 0;
+
+/* breakpoint here */
+static void memcount_raise(const char *name)
+{
+ fprintf(stderr, "%s: memcount-leak, %d\n", name, _mallocn_count);
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+/* Data definition */
+/* --------------------------------------------------------------------- */
+/* all memory chunks are put in linked lists */
+typedef struct localLink {
+ struct localLink *next, *prev;
+} localLink;
+
+typedef struct localListBase {
+ void *first, *last;
+} localListBase;
+
+/* note: keep this struct aligned (e.g., irix/gcc) - Hos */
+typedef struct MemHead {
+ int tag1;
+ size_t len;
+ struct MemHead *next, *prev;
+ const char *name;
+ const char *nextname;
+ int tag2;
+ int mmap; /* if true, memory was mmapped */
+#ifdef DEBUG_MEMCOUNTER
+ int _count;
+#endif
+
+#ifdef DEBUG_MEMDUPLINAME
+ int need_free_name, pad;
+#endif
+
+#ifdef DEBUG_BACKTRACE
+ void *backtrace[BACKTRACE_SIZE];
+ int backtrace_size;
+#endif
+} MemHead;
+
+/* for openmp threading asserts, saves time troubleshooting
+ * we may need to extend this if blender code starts using MEM_
+ * functions inside OpenMP correctly with omp_set_lock() */
+
+#if 0 /* disable for now, only use to debug openmp code which doesn lock threads for malloc */
+#if defined(_OPENMP) && defined(DEBUG)
+# include <assert.h>
+# include <omp.h>
+# define DEBUG_OMP_MALLOC
+#endif
+#endif
+
+#ifdef DEBUG_THREADS
+# include <assert.h>
+# include <pthread.h>
+static pthread_t mainid;
+#endif
+
+#ifdef DEBUG_BACKTRACE
+# if defined(__linux__) || defined(__APPLE__)
+# include <execinfo.h>
+// Windows is not supported yet.
+//# elif defined(_MSV_VER)
+//# include <DbgHelp.h>
+# endif
+#endif
+
+typedef struct MemTail {
+ int tag3, pad;
+} MemTail;
+
+
+/* --------------------------------------------------------------------- */
+/* local functions */
+/* --------------------------------------------------------------------- */
+
+static void addtail(volatile localListBase *listbase, void *vlink);
+static void remlink(volatile localListBase *listbase, void *vlink);
+static void rem_memblock(MemHead *memh);
+static void MemorY_ErroR(const char *block, const char *error);
+static const char *check_memlist(MemHead *memh);
+
+/* --------------------------------------------------------------------- */
+/* locally used defines */
+/* --------------------------------------------------------------------- */
+
+#ifdef __BIG_ENDIAN__
+# define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
+#else
+# define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
+#endif
+
+#define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O')
+#define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L')
+#define MEMTAG3 MAKE_ID('O', 'C', 'K', '!')
+#define MEMFREE MAKE_ID('F', 'R', 'E', 'E')
+
+#define MEMNEXT(x) \
+ ((MemHead *)(((char *) x) - ((char *) &(((MemHead *)0)->next))))
+
+/* --------------------------------------------------------------------- */
+/* vars */
+/* --------------------------------------------------------------------- */
+
+
+static unsigned int totblock = 0;
+static size_t mem_in_use = 0, mmap_in_use = 0, peak_mem = 0;
+
+static volatile struct localListBase _membase;
+static volatile struct localListBase *membase = &_membase;
+static void (*error_callback)(const char *) = NULL;
+static void (*thread_lock_callback)(void) = NULL;
+static void (*thread_unlock_callback)(void) = NULL;
+
+static bool malloc_debug_memset = false;
+
+#ifdef malloc
+#undef malloc
+#endif
+
+#ifdef calloc
+#undef calloc
+#endif
+
+#ifdef free
+#undef free
+#endif
+
+
+/* --------------------------------------------------------------------- */
+/* implementation */
+/* --------------------------------------------------------------------- */
+
+#ifdef __GNUC__
+__attribute__ ((format(printf, 1, 2)))
+#endif
+static void print_error(const char *str, ...)
+{
+ char buf[512];
+ va_list ap;
+
+ va_start(ap, str);
+ vsnprintf(buf, sizeof(buf), str, ap);
+ va_end(ap);
+ buf[sizeof(buf) - 1] = '\0';
+
+ if (error_callback) error_callback(buf);
+}
+
+static void mem_lock_thread(void)
+{
+#ifdef DEBUG_THREADS
+ static int initialized = 0;
+
+ if (initialized == 0) {
+ /* assume first allocation happens from main thread */
+ mainid = pthread_self();
+ initialized = 1;
+ }
+
+ if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) {
+ assert(!"Memory function is called from non-main thread without lock");
+ }
+#endif
+
+#ifdef DEBUG_OMP_MALLOC
+ assert(omp_in_parallel() == 0);
+#endif
+
+ if (thread_lock_callback)
+ thread_lock_callback();
+}
+
+static void mem_unlock_thread(void)
+{
+#ifdef DEBUG_THREADS
+ if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) {
+ assert(!"Thread lock was removed while allocation from thread is in progress");
+ }
+#endif
+
+ if (thread_unlock_callback)
+ thread_unlock_callback();
+}
+
+bool MEM_guarded_check_memory_integrity(void)
+{
+ const char *err_val = NULL;
+ MemHead *listend;
+ /* check_memlist starts from the front, and runs until it finds
+ * the requested chunk. For this test, that's the last one. */
+ listend = membase->last;
+
+ err_val = check_memlist(listend);
+
+ return (err_val != NULL);
+}
+
+
+void MEM_guarded_set_error_callback(void (*func)(const char *))
+{
+ error_callback = func;
+}
+
+void MEM_guarded_set_lock_callback(void (*lock)(void), void (*unlock)(void))
+{
+ thread_lock_callback = lock;
+ thread_unlock_callback = unlock;
+}
+
+void MEM_guarded_set_memory_debug(void)
+{
+ malloc_debug_memset = true;
+}
+
+size_t MEM_guarded_allocN_len(const void *vmemh)
+{
+ if (vmemh) {
+ const MemHead *memh = vmemh;
+
+ memh--;
+ return memh->len;
+ }
+ else {
+ return 0;
+ }
+}
+
+void *MEM_guarded_dupallocN(const void *vmemh)
+{
+ void *newp = NULL;
+
+ if (vmemh) {
+ const MemHead *memh = vmemh;
+ memh--;
+
+#ifndef DEBUG_MEMDUPLINAME
+ if (memh->mmap)
+ newp = MEM_guarded_mapallocN(memh->len, "dupli_mapalloc");
+ else
+ newp = MEM_guarded_mallocN(memh->len, "dupli_alloc");
+
+ if (newp == NULL) return NULL;
+#else
+ {
+ MemHead *nmemh;
+ char *name = malloc(strlen(memh->name) + 24);
+
+ if (memh->mmap) {
+ sprintf(name, "%s %s", "dupli_mapalloc", memh->name);
+ newp = MEM_guarded_mapallocN(memh->len, name);
+ }
+ else {
+ sprintf(name, "%s %s", "dupli_alloc", memh->name);
+ newp = MEM_guarded_mallocN(memh->len, name);
+ }
+
+ if (newp == NULL) return NULL;
+
+ nmemh = newp;
+ nmemh--;
+
+ nmemh->need_free_name = 1;
+ }
+#endif
+
+ memcpy(newp, vmemh, memh->len);
+ }
+
+ return newp;
+}
+
+void *MEM_guarded_reallocN_id(void *vmemh, size_t len, const char *str)
+{
+ void *newp = NULL;
+
+ if (vmemh) {
+ MemHead *memh = vmemh;
+ memh--;
+
+ newp = MEM_guarded_mallocN(len, memh->name);
+ if (newp) {
+ if (len < memh->len) {
+ /* shrink */
+ memcpy(newp, vmemh, len);
+ }
+ else {
+ /* grow (or remain same size) */
+ memcpy(newp, vmemh, memh->len);
+ }
+ }
+
+ MEM_guarded_freeN(vmemh);
+ }
+ else {
+ newp = MEM_guarded_mallocN(len, str);
+ }
+
+ return newp;
+}
+
+void *MEM_guarded_recallocN_id(void *vmemh, size_t len, const char *str)
+{
+ void *newp = NULL;
+
+ if (vmemh) {
+ MemHead *memh = vmemh;
+ memh--;
+
+ newp = MEM_guarded_mallocN(len, memh->name);
+ if (newp) {
+ if (len < memh->len) {
+ /* shrink */
+ memcpy(newp, vmemh, len);
+ }
+ else {
+ memcpy(newp, vmemh, memh->len);
+
+ if (len > memh->len) {
+ /* grow */
+ /* zero new bytes */
+ memset(((char *)newp) + memh->len, 0, len - memh->len);
+ }
+ }
+ }
+
+ MEM_guarded_freeN(vmemh);
+ }
+ else {
+ newp = MEM_guarded_callocN(len, str);
+ }
+
+ return newp;
+}
+
+#ifdef DEBUG_BACKTRACE
+# if defined(__linux__) || defined(__APPLE__)
+static void make_memhead_backtrace(MemHead *memh)
+{
+ memh->backtrace_size = backtrace(memh->backtrace, BACKTRACE_SIZE);
+}
+
+static void print_memhead_backtrace(MemHead *memh)
+{
+ char **strings;
+ int i;
+
+ strings = backtrace_symbols(memh->backtrace, memh->backtrace_size);
+ for (i = 0; i < memh->backtrace_size; i++) {
+ print_error(" %s\n", strings[i]);
+ }
+
+ free(strings);
+}
+# else
+static void make_memhead_backtrace(MemHead *memh)
+{
+ (void) memh; /* Ignored. */
+}
+
+static void print_memhead_backtrace(MemHead *memh)
+{
+ (void) memh; /* Ignored. */
+}
+# endif /* defined(__linux__) || defined(__APPLE__) */
+#endif /* DEBUG_BACKTRACE */
+
+static void make_memhead_header(MemHead *memh, size_t len, const char *str)
+{
+ MemTail *memt;
+
+ memh->tag1 = MEMTAG1;
+ memh->name = str;
+ memh->nextname = NULL;
+ memh->len = len;
+ memh->mmap = 0;
+ memh->tag2 = MEMTAG2;
+
+#ifdef DEBUG_MEMDUPLINAME
+ memh->need_free_name = 0;
+#endif
+
+#ifdef DEBUG_BACKTRACE
+ make_memhead_backtrace(memh);
+#endif
+
+ memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + len);
+ memt->tag3 = MEMTAG3;
+
+ atomic_add_u(&totblock, 1);
+ atomic_add_z(&mem_in_use, len);
+
+ mem_lock_thread();
+ addtail(membase, &memh->next);
+ if (memh->next) {
+ memh->nextname = MEMNEXT(memh->next)->name;
+ }
+ peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem;
+ mem_unlock_thread();
+}
+
+void *MEM_guarded_mallocN(size_t len, const char *str)
+{
+ MemHead *memh;
+
+ len = SIZET_ALIGN_4(len);
+
+ memh = (MemHead *)malloc(len + sizeof(MemHead) + sizeof(MemTail));
+
+ if (memh) {
+ make_memhead_header(memh, len, str);
+ if (malloc_debug_memset && len)
+ memset(memh + 1, 255, len);
+
+#ifdef DEBUG_MEMCOUNTER
+ if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
+ memcount_raise(__func__);
+ memh->_count = _mallocn_count++;
+#endif
+ return (++memh);
+ }
+ print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
+ SIZET_ARG(len), str, (unsigned int) mem_in_use);
+ return NULL;
+}
+
+void *MEM_guarded_callocN(size_t len, const char *str)
+{
+ MemHead *memh;
+
+ len = SIZET_ALIGN_4(len);
+
+ memh = (MemHead *)calloc(len + sizeof(MemHead) + sizeof(MemTail), 1);
+
+ if (memh) {
+ make_memhead_header(memh, len, str);
+#ifdef DEBUG_MEMCOUNTER
+ if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
+ memcount_raise(__func__);
+ memh->_count = _mallocn_count++;
+#endif
+ return (++memh);
+ }
+ print_error("Calloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
+ SIZET_ARG(len), str, (unsigned int) mem_in_use);
+ return NULL;
+}
+
+/* note; mmap returns zero'd memory */
+void *MEM_guarded_mapallocN(size_t len, const char *str)
+{
+ MemHead *memh;
+
+ len = SIZET_ALIGN_4(len);
+
+#if defined(WIN32)
+ /* our windows mmap implementation is not thread safe */
+ mem_lock_thread();
+#endif
+ memh = mmap(NULL, len + sizeof(MemHead) + sizeof(MemTail),
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+#if defined(WIN32)
+ mem_unlock_thread();
+#endif
+
+ if (memh != (MemHead *)-1) {
+ make_memhead_header(memh, len, str);
+ memh->mmap = 1;
+ atomic_add_z(&mmap_in_use, len);
+ mem_lock_thread();
+ peak_mem = mmap_in_use > peak_mem ? mmap_in_use : peak_mem;
+ mem_unlock_thread();
+#ifdef DEBUG_MEMCOUNTER
+ if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
+ memcount_raise(__func__);
+ memh->_count = _mallocn_count++;
+#endif
+ return (++memh);
+ }
+ else {
+ print_error("Mapalloc returns null, fallback to regular malloc: "
+ "len=" SIZET_FORMAT " in %s, total %u\n",
+ SIZET_ARG(len), str, (unsigned int) mmap_in_use);
+ return MEM_guarded_callocN(len, str);
+ }
+}
+
+/* Memory statistics print */
+typedef struct MemPrintBlock {
+ const char *name;
+ uintptr_t len;
+ int items;
+} MemPrintBlock;
+
+static int compare_name(const void *p1, const void *p2)
+{
+ const MemPrintBlock *pb1 = (const MemPrintBlock *)p1;
+ const MemPrintBlock *pb2 = (const MemPrintBlock *)p2;
+
+ return strcmp(pb1->name, pb2->name);
+}
+
+static int compare_len(const void *p1, const void *p2)
+{
+ const MemPrintBlock *pb1 = (const MemPrintBlock *)p1;
+ const MemPrintBlock *pb2 = (const MemPrintBlock *)p2;
+
+ if (pb1->len < pb2->len)
+ return 1;
+ else if (pb1->len == pb2->len)
+ return 0;
+ else
+ return -1;
+}
+
+void MEM_guarded_printmemlist_stats(void)
+{
+ MemHead *membl;
+ MemPrintBlock *pb, *printblock;
+ unsigned int totpb, a, b;
+ size_t mem_in_use_slop = 0;
+
+ mem_lock_thread();
+
+ /* put memory blocks into array */
+ printblock = malloc(sizeof(MemPrintBlock) * totblock);
+
+ pb = printblock;
+ totpb = 0;
+
+ membl = membase->first;
+ if (membl) membl = MEMNEXT(membl);
+
+ while (membl) {
+ pb->name = membl->name;
+ pb->len = membl->len;
+ pb->items = 1;
+
+ totpb++;
+ pb++;
+
+ if (!membl->mmap) {
+ mem_in_use_slop += (sizeof(MemHead) + sizeof(MemTail) +
+ malloc_usable_size((void *)membl)) - membl->len;
+ }
+
+ if (membl->next)
+ membl = MEMNEXT(membl->next);
+ else break;
+ }
+
+ /* sort by name and add together blocks with the same name */
+ qsort(printblock, totpb, sizeof(MemPrintBlock), compare_name);
+ for (a = 0, b = 0; a < totpb; a++) {
+ if (a == b) {
+ continue;
+ }
+ else if (strcmp(printblock[a].name, printblock[b].name) == 0) {
+ printblock[b].len += printblock[a].len;
+ printblock[b].items++;
+ }
+ else {
+ b++;
+ memcpy(&printblock[b], &printblock[a], sizeof(MemPrintBlock));
+ }
+ }
+ totpb = b + 1;
+
+ /* sort by length and print */
+ qsort(printblock, totpb, sizeof(MemPrintBlock), compare_len);
+ printf("\ntotal memory len: %.3f MB\n",
+ (double)mem_in_use / (double)(1024 * 1024));
+ printf("peak memory len: %.3f MB\n",
+ (double)peak_mem / (double)(1024 * 1024));
+ printf("slop memory len: %.3f MB\n",
+ (double)mem_in_use_slop / (double)(1024 * 1024));
+ printf(" ITEMS TOTAL-MiB AVERAGE-KiB TYPE\n");
+ for (a = 0, pb = printblock; a < totpb; a++, pb++) {
+ printf("%6d (%8.3f %8.3f) %s\n",
+ pb->items, (double)pb->len / (double)(1024 * 1024),
+ (double)pb->len / 1024.0 / (double)pb->items, pb->name);
+ }
+ free(printblock);
+
+ mem_unlock_thread();
+
+#ifdef HAVE_MALLOC_STATS
+ printf("System Statistics:\n");
+ malloc_stats();
+#endif
+}
+
+static const char mem_printmemlist_pydict_script[] =
+"mb_userinfo = {}\n"
+"totmem = 0\n"
+"for mb_item in membase:\n"
+" mb_item_user_size = mb_userinfo.setdefault(mb_item['name'], [0,0])\n"
+" mb_item_user_size[0] += 1 # Add a user\n"
+" mb_item_user_size[1] += mb_item['len'] # Increment the size\n"
+" totmem += mb_item['len']\n"
+"print('(membase) items:', len(membase), '| unique-names:',\n"
+" len(mb_userinfo), '| total-mem:', totmem)\n"
+"mb_userinfo_sort = list(mb_userinfo.items())\n"
+"for sort_name, sort_func in (('size', lambda a: -a[1][1]),\n"
+" ('users', lambda a: -a[1][0]),\n"
+" ('name', lambda a: a[0])):\n"
+" print('\\nSorting by:', sort_name)\n"
+" mb_userinfo_sort.sort(key = sort_func)\n"
+" for item in mb_userinfo_sort:\n"
+" print('name:%%s, users:%%i, len:%%i' %%\n"
+" (item[0], item[1][0], item[1][1]))\n";
+
+/* Prints in python syntax for easy */
+static void MEM_guarded_printmemlist_internal(int pydict)
+{
+ MemHead *membl;
+
+ mem_lock_thread();
+
+ membl = membase->first;
+ if (membl) membl = MEMNEXT(membl);
+
+ if (pydict) {
+ print_error("# membase_debug.py\n");
+ print_error("membase = [\n");
+ }
+ while (membl) {
+ if (pydict) {
+ fprintf(stderr,
+ " {'len':" SIZET_FORMAT ", "
+ "'name':'''%s''', "
+ "'pointer':'%p'},\n",
+ SIZET_ARG(membl->len), membl->name, (void *)(membl + 1));
+ }
+ else {
+#ifdef DEBUG_MEMCOUNTER
+ print_error("%s len: " SIZET_FORMAT " %p, count: %d\n",
+ membl->name, SIZET_ARG(membl->len), membl + 1,
+ membl->_count);
+#else
+ print_error("%s len: " SIZET_FORMAT " %p\n",
+ membl->name, SIZET_ARG(membl->len), membl + 1);
+#endif
+#ifdef DEBUG_BACKTRACE
+ print_memhead_backtrace(membl);
+#endif
+ }
+ if (membl->next)
+ membl = MEMNEXT(membl->next);
+ else break;
+ }
+ if (pydict) {
+ fprintf(stderr, "]\n\n");
+ fprintf(stderr, mem_printmemlist_pydict_script);
+ }
+
+ mem_unlock_thread();
+}
+
+void MEM_guarded_callbackmemlist(void (*func)(void *))
+{
+ MemHead *membl;
+
+ mem_lock_thread();
+
+ membl = membase->first;
+ if (membl) membl = MEMNEXT(membl);
+
+ while (membl) {
+ func(membl + 1);
+ if (membl->next)
+ membl = MEMNEXT(membl->next);
+ else break;
+ }
+
+ mem_unlock_thread();
+}
+
+#if 0
+short MEM_guarded_testN(void *vmemh)
+{
+ MemHead *membl;
+
+ mem_lock_thread();
+
+ membl = membase->first;
+ if (membl) membl = MEMNEXT(membl);
+
+ while (membl) {
+ if (vmemh == membl + 1) {
+ mem_unlock_thread();
+ return 1;
+ }
+
+ if (membl->next)
+ membl = MEMNEXT(membl->next);
+ else break;
+ }
+
+ mem_unlock_thread();
+
+ print_error("Memoryblock %p: pointer not in memlist\n", vmemh);
+ return 0;
+}
+#endif
+
+void MEM_guarded_printmemlist(void)
+{
+ MEM_guarded_printmemlist_internal(0);
+}
+void MEM_guarded_printmemlist_pydict(void)
+{
+ MEM_guarded_printmemlist_internal(1);
+}
+
+void MEM_guarded_freeN(void *vmemh)
+{
+ MemTail *memt;
+ MemHead *memh = vmemh;
+ const char *name;
+
+ if (memh == NULL) {
+ MemorY_ErroR("free", "attempt to free NULL pointer");
+ /* print_error(err_stream, "%d\n", (memh+4000)->tag1); */
+ return;
+ }
+
+ if (sizeof(intptr_t) == 8) {
+ if (((intptr_t) memh) & 0x7) {
+ MemorY_ErroR("free", "attempt to free illegal pointer");
+ return;
+ }
+ }
+ else {
+ if (((intptr_t) memh) & 0x3) {
+ MemorY_ErroR("free", "attempt to free illegal pointer");
+ return;
+ }
+ }
+
+ memh--;
+ if (memh->tag1 == MEMFREE && memh->tag2 == MEMFREE) {
+ MemorY_ErroR(memh->name, "double free");
+ return;
+ }
+
+ if ((memh->tag1 == MEMTAG1) &&
+ (memh->tag2 == MEMTAG2) &&
+ ((memh->len & 0x3) == 0))
+ {
+ memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + memh->len);
+ if (memt->tag3 == MEMTAG3) {
+
+ memh->tag1 = MEMFREE;
+ memh->tag2 = MEMFREE;
+ memt->tag3 = MEMFREE;
+ /* after tags !!! */
+ rem_memblock(memh);
+
+ return;
+ }
+ MemorY_ErroR(memh->name, "end corrupt");
+ name = check_memlist(memh);
+ if (name != NULL) {
+ if (name != memh->name) MemorY_ErroR(name, "is also corrupt");
+ }
+ }
+ else {
+ mem_lock_thread();
+ name = check_memlist(memh);
+ mem_unlock_thread();
+ if (name == NULL)
+ MemorY_ErroR("free", "pointer not in memlist");
+ else
+ MemorY_ErroR(name, "error in header");
+ }
+
+ totblock--;
+ /* here a DUMP should happen */
+
+ return;
+}
+
+/* --------------------------------------------------------------------- */
+/* local functions */
+/* --------------------------------------------------------------------- */
+
+static void addtail(volatile localListBase *listbase, void *vlink)
+{
+ struct localLink *link = vlink;
+
+ /* for a generic API error checks here is fine but
+ * the limited use here they will never be NULL */
+#if 0
+ if (link == NULL) return;
+ if (listbase == NULL) return;
+#endif
+
+ link->next = NULL;
+ link->prev = listbase->last;
+
+ if (listbase->last) ((struct localLink *)listbase->last)->next = link;
+ if (listbase->first == NULL) listbase->first = link;
+ listbase->last = link;
+}
+
+static void remlink(volatile localListBase *listbase, void *vlink)
+{
+ struct localLink *link = vlink;
+
+ /* for a generic API error checks here is fine but
+ * the limited use here they will never be NULL */
+#if 0
+ if (link == NULL) return;
+ if (listbase == NULL) return;
+#endif
+
+ if (link->next) link->next->prev = link->prev;
+ if (link->prev) link->prev->next = link->next;
+
+ if (listbase->last == link) listbase->last = link->prev;
+ if (listbase->first == link) listbase->first = link->next;
+}
+
+static void rem_memblock(MemHead *memh)
+{
+ mem_lock_thread();
+ remlink(membase, &memh->next);
+ if (memh->prev) {
+ if (memh->next)
+ MEMNEXT(memh->prev)->nextname = MEMNEXT(memh->next)->name;
+ else
+ MEMNEXT(memh->prev)->nextname = NULL;
+ }
+ mem_unlock_thread();
+
+ atomic_sub_u(&totblock, 1);
+ atomic_sub_z(&mem_in_use, memh->len);
+
+#ifdef DEBUG_MEMDUPLINAME
+ if (memh->need_free_name)
+ free((char *) memh->name);
+#endif
+
+ if (memh->mmap) {
+ atomic_sub_z(&mmap_in_use, memh->len);
+#if defined(WIN32)
+ /* our windows mmap implementation is not thread safe */
+ mem_lock_thread();
+#endif
+ if (munmap(memh, memh->len + sizeof(MemHead) + sizeof(MemTail)))
+ printf("Couldn't unmap memory %s\n", memh->name);
+#if defined(WIN32)
+ mem_unlock_thread();
+#endif
+ }
+ else {
+ if (malloc_debug_memset && memh->len)
+ memset(memh + 1, 255, memh->len);
+ free(memh);
+ }
+}
+
+static void MemorY_ErroR(const char *block, const char *error)
+{
+ print_error("Memoryblock %s: %s\n", block, error);
+
+#ifdef WITH_ASSERT_ABORT
+ abort();
+#endif
+}
+
+static const char *check_memlist(MemHead *memh)
+{
+ MemHead *forw, *back, *forwok, *backok;
+ const char *name;
+
+ forw = membase->first;
+ if (forw) forw = MEMNEXT(forw);
+ forwok = NULL;
+ while (forw) {
+ if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break;
+ forwok = forw;
+ if (forw->next) forw = MEMNEXT(forw->next);
+ else forw = NULL;
+ }
+
+ back = (MemHead *) membase->last;
+ if (back) back = MEMNEXT(back);
+ backok = NULL;
+ while (back) {
+ if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break;
+ backok = back;
+ if (back->prev) back = MEMNEXT(back->prev);
+ else back = NULL;
+ }
+
+ if (forw != back) return ("MORE THAN 1 MEMORYBLOCK CORRUPT");
+
+ if (forw == NULL && back == NULL) {
+ /* no wrong headers found then but in search of memblock */
+
+ forw = membase->first;
+ if (forw) forw = MEMNEXT(forw);
+ forwok = NULL;
+ while (forw) {
+ if (forw == memh) break;
+ if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break;
+ forwok = forw;
+ if (forw->next) forw = MEMNEXT(forw->next);
+ else forw = NULL;
+ }
+ if (forw == NULL) return NULL;
+
+ back = (MemHead *) membase->last;
+ if (back) back = MEMNEXT(back);
+ backok = NULL;
+ while (back) {
+ if (back == memh) break;
+ if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break;
+ backok = back;
+ if (back->prev) back = MEMNEXT(back->prev);
+ else back = NULL;
+ }
+ }
+
+ if (forwok) name = forwok->nextname;
+ else name = "No name found";
+
+ if (forw == memh) {
+ /* to be sure but this block is removed from the list */
+ if (forwok) {
+ if (backok) {
+ forwok->next = (MemHead *)&backok->next;
+ backok->prev = (MemHead *)&forwok->next;
+ forwok->nextname = backok->name;
+ }
+ else {
+ forwok->next = NULL;
+ membase->last = (struct localLink *) &forwok->next;
+ }
+ }
+ else {
+ if (backok) {
+ backok->prev = NULL;
+ membase->first = &backok->next;
+ }
+ else {
+ membase->first = membase->last = NULL;
+ }
+ }
+ }
+ else {
+ MemorY_ErroR(name, "Additional error in header");
+ return("Additional error in header");
+ }
+
+ return(name);
+}
+
+size_t MEM_guarded_get_peak_memory(void)
+{
+ size_t _peak_mem;
+
+ mem_lock_thread();
+ _peak_mem = peak_mem;
+ mem_unlock_thread();
+
+ return _peak_mem;
+}
+
+void MEM_guarded_reset_peak_memory(void)
+{
+ mem_lock_thread();
+ peak_mem = 0;
+ mem_unlock_thread();
+}
+
+uintptr_t MEM_guarded_get_memory_in_use(void)
+{
+ uintptr_t _mem_in_use;
+
+ mem_lock_thread();
+ _mem_in_use = mem_in_use;
+ mem_unlock_thread();
+
+ return _mem_in_use;
+}
+
+uintptr_t MEM_guarded_get_mapped_memory_in_use(void)
+{
+ uintptr_t _mmap_in_use;
+
+ mem_lock_thread();
+ _mmap_in_use = mmap_in_use;
+ mem_unlock_thread();
+
+ return _mmap_in_use;
+}
+
+unsigned int MEM_guarded_get_memory_blocks_in_use(void)
+{
+ unsigned int _totblock;
+
+ mem_lock_thread();
+ _totblock = totblock;
+ mem_unlock_thread();
+
+ return _totblock;
+}
+
+#ifndef NDEBUG
+const char *MEM_guarded_name_ptr(void *vmemh)
+{
+ if (vmemh) {
+ MemHead *memh = vmemh;
+ memh--;
+ return memh->name;
+ }
+ else {
+ return "MEM_guarded_name_ptr(NULL)";
+ }
+}
+#endif /* NDEBUG */
diff --git a/intern/guardedalloc/intern/mallocn_intern.h b/intern/guardedalloc/intern/mallocn_intern.h
new file mode 100644
index 00000000000..db45b59b884
--- /dev/null
+++ b/intern/guardedalloc/intern/mallocn_intern.h
@@ -0,0 +1,132 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file guardedalloc/intern/mallocn_intern.h
+ * \ingroup MEM
+ */
+
+#ifndef __MALLOCN_INTERN_H__
+#define __MALLOCN_INTERN_H__
+
+/* mmap exception */
+#if defined(WIN32)
+# include "mmap_win.h"
+#else
+# include <sys/mman.h>
+#endif
+
+#if defined(_MSC_VER)
+# define __func__ __FUNCTION__
+#endif
+
+#ifdef __GNUC__
+# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
+#else
+# define UNUSED(x) UNUSED_ ## x
+#endif
+
+#undef HAVE_MALLOC_STATS
+
+#if defined(__linux__)
+# include <malloc.h>
+# define HAVE_MALLOC_STATS
+#elif defined(__FreeBSD__)
+# include <malloc_np.h>
+#elif defined(__APPLE__)
+# include <malloc/malloc.h>
+# define malloc_usable_size malloc_size
+#elif defined(WIN32)
+# include <malloc.h>
+# define malloc_usable_size _msize
+#else
+# error "We don't know how to use malloc_usable_size on your platform"
+#endif
+
+/* Blame Microsoft for LLP64 and no inttypes.h, quick workaround needed: */
+#if defined(WIN64)
+# define SIZET_FORMAT "%I64u"
+# define SIZET_ARG(a) ((unsigned long long)(a))
+#else
+# define SIZET_FORMAT "%lu"
+# define SIZET_ARG(a) ((unsigned long)(a))
+#endif
+
+#define SIZET_ALIGN_4(len) ((len + 3) & ~(size_t)3)
+
+/* Prototypes for counted allocator functions */
+size_t MEM_lockfree_allocN_len(const void *vmemh) ATTR_WARN_UNUSED_RESULT;
+void MEM_lockfree_freeN(void *vmemh);
+void *MEM_lockfree_dupallocN(const void *vmemh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+void *MEM_lockfree_reallocN_id(void *vmemh, size_t len, const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(2);
+void *MEM_lockfree_recallocN_id(void *vmemh, size_t len, const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(2);
+void *MEM_lockfree_callocN(size_t len, const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
+void *MEM_lockfree_mallocN(size_t len, const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
+void *MEM_lockfree_mapallocN(size_t len, const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
+void MEM_lockfree_printmemlist_pydict(void);
+void MEM_lockfree_printmemlist(void);
+void MEM_lockfree_callbackmemlist(void (*func)(void *));
+void MEM_lockfree_printmemlist_stats(void);
+void MEM_lockfree_set_error_callback(void (*func)(const char *));
+bool MEM_lockfree_check_memory_integrity(void);
+void MEM_lockfree_set_lock_callback(void (*lock)(void), void (*unlock)(void));
+void MEM_lockfree_set_memory_debug(void);
+uintptr_t MEM_lockfree_get_memory_in_use(void);
+uintptr_t MEM_lockfree_get_mapped_memory_in_use(void);
+unsigned int MEM_lockfree_get_memory_blocks_in_use(void);
+void MEM_lockfree_reset_peak_memory(void);
+uintptr_t MEM_lockfree_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
+#ifndef NDEBUG
+const char *MEM_lockfree_name_ptr(void *vmemh);
+#endif
+
+/* Prototypes for fully guarded allocator functions */
+size_t MEM_guarded_allocN_len(const void *vmemh) ATTR_WARN_UNUSED_RESULT;
+void MEM_guarded_freeN(void *vmemh);
+void *MEM_guarded_dupallocN(const void *vmemh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+void *MEM_guarded_reallocN_id(void *vmemh, size_t len, const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(2);
+void *MEM_guarded_recallocN_id(void *vmemh, size_t len, const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(2);
+void *MEM_guarded_callocN(size_t len, const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
+void *MEM_guarded_mallocN(size_t len, const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
+void *MEM_guarded_mapallocN(size_t len, const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
+void MEM_guarded_printmemlist_pydict(void);
+void MEM_guarded_printmemlist(void);
+void MEM_guarded_callbackmemlist(void (*func)(void *));
+void MEM_guarded_printmemlist_stats(void);
+void MEM_guarded_set_error_callback(void (*func)(const char *));
+bool MEM_guarded_check_memory_integrity(void);
+void MEM_guarded_set_lock_callback(void (*lock)(void), void (*unlock)(void));
+void MEM_guarded_set_memory_debug(void);
+uintptr_t MEM_guarded_get_memory_in_use(void);
+uintptr_t MEM_guarded_get_mapped_memory_in_use(void);
+unsigned int MEM_guarded_get_memory_blocks_in_use(void);
+void MEM_guarded_reset_peak_memory(void);
+uintptr_t MEM_guarded_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
+#ifndef NDEBUG
+const char *MEM_guarded_name_ptr(void *vmemh);
+#endif
+
+#endif /* __MALLOCN_INTERN_H__ */
diff --git a/intern/guardedalloc/intern/mallocn_lockfree_impl.c b/intern/guardedalloc/intern/mallocn_lockfree_impl.c
new file mode 100644
index 00000000000..35caebcc5e8
--- /dev/null
+++ b/intern/guardedalloc/intern/mallocn_lockfree_impl.c
@@ -0,0 +1,376 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel
+ * Campbell Barton
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file guardedalloc/intern/mallocn.c
+ * \ingroup MEM
+ *
+ * Memory allocation which keeps track on allocated memory counters
+ */
+
+#include <stdlib.h>
+#include <string.h> /* memcpy */
+#include <stdarg.h>
+#include <sys/types.h>
+
+#include "MEM_guardedalloc.h"
+
+/* to ensure strict conversions */
+#include "../../source/blender/blenlib/BLI_strict_flags.h"
+
+#include "atomic_ops.h"
+#include "mallocn_intern.h"
+
+typedef struct MemHead {
+ /* Length of allocated memory block. */
+ size_t len;
+} MemHead;
+
+static unsigned int totblock = 0;
+static size_t mem_in_use = 0, mmap_in_use = 0, peak_mem = 0;
+static bool malloc_debug_memset = false;
+
+static void (*error_callback)(const char *) = NULL;
+static void (*thread_lock_callback)(void) = NULL;
+static void (*thread_unlock_callback)(void) = NULL;
+
+#define MEMHEAD_FROM_PTR(ptr) (((MemHead*) vmemh) - 1)
+#define PTR_FROM_MEMHEAD(memhead) (memhead + 1)
+
+#ifdef __GNUC__
+__attribute__ ((format(printf, 1, 2)))
+#endif
+static void print_error(const char *str, ...)
+{
+ char buf[512];
+ va_list ap;
+
+ va_start(ap, str);
+ vsnprintf(buf, sizeof(buf), str, ap);
+ va_end(ap);
+ buf[sizeof(buf) - 1] = '\0';
+
+ if (error_callback) {
+ error_callback(buf);
+ }
+}
+
+#if defined(WIN32)
+static void mem_lock_thread(void)
+{
+ if (thread_lock_callback)
+ thread_lock_callback();
+}
+
+static void mem_unlock_thread(void)
+{
+ if (thread_unlock_callback)
+ thread_unlock_callback();
+}
+#endif
+
+size_t MEM_lockfree_allocN_len(const void *vmemh)
+{
+ if (vmemh) {
+ return MEMHEAD_FROM_PTR(vmemh)->len & ~((size_t) 1);
+ }
+ else {
+ return 0;
+ }
+}
+
+void MEM_lockfree_freeN(void *vmemh)
+{
+ MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
+ size_t len = MEM_lockfree_allocN_len(vmemh);
+
+ atomic_sub_u(&totblock, 1);
+ atomic_sub_z(&mem_in_use, len);
+
+ if (memh->len & (size_t) 1) {
+ atomic_sub_z(&mmap_in_use, len);
+#if defined(WIN32)
+ /* our windows mmap implementation is not thread safe */
+ mem_lock_thread();
+#endif
+ if (munmap(memh, memh->len + sizeof(MemHead)))
+ printf("Couldn't unmap memory\n");
+#if defined(WIN32)
+ mem_unlock_thread();
+#endif
+ }
+ else {
+ if (malloc_debug_memset && len) {
+ memset(memh + 1, 255, len);
+ }
+ free(memh);
+ }
+}
+
+void *MEM_lockfree_dupallocN(const void *vmemh)
+{
+ void *newp = NULL;
+ if (vmemh) {
+ const size_t prev_size = MEM_allocN_len(vmemh);
+ newp = MEM_lockfree_mallocN(prev_size, "dupli_malloc");
+ memcpy(newp, vmemh, prev_size);
+ }
+ return newp;
+}
+
+void *MEM_lockfree_reallocN_id(void *vmemh, size_t len, const char *str)
+{
+ void *newp = NULL;
+
+ if (vmemh) {
+ size_t old_len = MEM_allocN_len(vmemh);
+
+ newp = MEM_lockfree_mallocN(len, "realloc");
+ if (newp) {
+ if (len < old_len) {
+ /* shrink */
+ memcpy(newp, vmemh, len);
+ }
+ else {
+ /* grow (or remain same size) */
+ memcpy(newp, vmemh, old_len);
+ }
+ }
+
+ MEM_lockfree_freeN(vmemh);
+ }
+ else {
+ newp = MEM_lockfree_mallocN(len, str);
+ }
+
+ return newp;
+}
+
+void *MEM_lockfree_recallocN_id(void *vmemh, size_t len, const char *str)
+{
+ void *newp = NULL;
+
+ if (vmemh) {
+ size_t old_len = MEM_allocN_len(vmemh);
+
+ newp = MEM_lockfree_mallocN(len, "recalloc");
+ if (newp) {
+ if (len < old_len) {
+ /* shrink */
+ memcpy(newp, vmemh, len);
+ }
+ else {
+ memcpy(newp, vmemh, old_len);
+
+ if (len > old_len) {
+ /* grow */
+ /* zero new bytes */
+ memset(((char *)newp) + old_len, 0, len - old_len);
+ }
+ }
+ }
+
+ MEM_lockfree_freeN(vmemh);
+ }
+ else {
+ newp = MEM_lockfree_callocN(len, str);
+ }
+
+ return newp;
+}
+
+void *MEM_lockfree_callocN(size_t len, const char *str)
+{
+ MemHead *memh;
+
+ len = SIZET_ALIGN_4(len);
+
+ memh = (MemHead *)calloc(1, len + sizeof(MemHead));
+
+ if (memh) {
+ memh->len = len;
+ atomic_add_u(&totblock, 1);
+ atomic_add_z(&mem_in_use, len);
+
+ /* TODO(sergey): Not strictly speaking thread-safe. */
+ peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem;
+
+ return PTR_FROM_MEMHEAD(memh);
+ }
+ print_error("Calloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
+ SIZET_ARG(len), str, (unsigned int) mem_in_use);
+ return NULL;
+}
+
+void *MEM_lockfree_mallocN(size_t len, const char *str)
+{
+ MemHead *memh;
+
+ len = SIZET_ALIGN_4(len);
+
+ memh = (MemHead *)malloc(len + sizeof(MemHead));
+
+ if (memh) {
+ if (malloc_debug_memset && len) {
+ memset(memh + 1, 255, len);
+ }
+
+ memh->len = len;
+ atomic_add_u(&totblock, 1);
+ atomic_add_z(&mem_in_use, len);
+
+ /* TODO(sergey): Not strictly speaking thread-safe. */
+ peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem;
+
+ return PTR_FROM_MEMHEAD(memh);
+ }
+ print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
+ SIZET_ARG(len), str, (unsigned int) mem_in_use);
+ return NULL;
+}
+
+void *MEM_lockfree_mapallocN(size_t len, const char *str)
+{
+ MemHead *memh;
+
+ len = SIZET_ALIGN_4(len);
+
+#if defined(WIN32)
+ /* our windows mmap implementation is not thread safe */
+ mem_lock_thread();
+#endif
+ memh = mmap(NULL, len + sizeof(MemHead),
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+#if defined(WIN32)
+ mem_unlock_thread();
+#endif
+
+ if (memh != (MemHead *)-1) {
+ memh->len = len | (size_t) 1;
+ atomic_add_u(&totblock, 1);
+ atomic_add_z(&mem_in_use, len);
+ atomic_add_z(&mmap_in_use, len);
+
+ /* TODO(sergey): Not strictly speaking thread-safe. */
+ peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem;
+ peak_mem = mmap_in_use > peak_mem ? mmap_in_use : peak_mem;
+
+ return PTR_FROM_MEMHEAD(memh);
+ }
+ print_error("Mapalloc returns null, fallback to regular malloc: "
+ "len=" SIZET_FORMAT " in %s, total %u\n",
+ SIZET_ARG(len), str, (unsigned int) mmap_in_use);
+ return MEM_lockfree_callocN(len, str);
+}
+
+void MEM_lockfree_printmemlist_pydict(void)
+{
+}
+
+void MEM_lockfree_printmemlist(void)
+{
+}
+
+/* unused */
+void MEM_lockfree_callbackmemlist(void (*func)(void *))
+{
+ (void) func; /* Ignored. */
+}
+
+void MEM_lockfree_printmemlist_stats(void)
+{
+ printf("\ntotal memory len: %.3f MB\n",
+ (double)mem_in_use / (double)(1024 * 1024));
+ printf("peak memory len: %.3f MB\n",
+ (double)peak_mem / (double)(1024 * 1024));
+ printf("\nFor more detailed per-block statistics run Blender with memory debugging command line argument.\n");
+
+#ifdef HAVE_MALLOC_STATS
+ printf("System Statistics:\n");
+ malloc_stats();
+#endif
+}
+
+void MEM_lockfree_set_error_callback(void (*func)(const char *))
+{
+ error_callback = func;
+}
+
+bool MEM_lockfree_check_memory_integrity(void)
+{
+ return true;
+}
+
+void MEM_lockfree_set_lock_callback(void (*lock)(void), void (*unlock)(void))
+{
+ thread_lock_callback = lock;
+ thread_unlock_callback = unlock;
+}
+
+void MEM_lockfree_set_memory_debug(void)
+{
+ malloc_debug_memset = true;
+}
+
+uintptr_t MEM_lockfree_get_memory_in_use(void)
+{
+ return mem_in_use;
+}
+
+uintptr_t MEM_lockfree_get_mapped_memory_in_use(void)
+{
+ return mmap_in_use;
+}
+
+unsigned int MEM_lockfree_get_memory_blocks_in_use(void)
+{
+ return totblock;
+}
+
+/* dummy */
+void MEM_lockfree_reset_peak_memory(void)
+{
+ peak_mem = 0;
+}
+
+uintptr_t MEM_lockfree_get_peak_memory(void)
+{
+ return peak_mem;
+}
+
+#ifndef NDEBUG
+const char *MEM_lockfree_name_ptr(void *vmemh)
+{
+ if (vmemh) {
+ return "unknown block name ptr";
+ }
+ else {
+ return "MEM_lockfree_name_ptr(NULL)";
+ }
+}
+#endif /* NDEBUG */
diff --git a/intern/guardedalloc/mmap_win.h b/intern/guardedalloc/mmap_win.h
index 0f88a8e3ba8..a1959fed9f9 100644
--- a/intern/guardedalloc/mmap_win.h
+++ b/intern/guardedalloc/mmap_win.h
@@ -51,6 +51,8 @@
/* needed for uintptr_t, exception, dont use BLI anywhere else in MEM_* */
#include "../../source/blender/blenlib/BLI_sys_types.h"
+#include <sys/types.h>
+
void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset);
intptr_t munmap(void *ptr, size_t size);
diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt
index 30a74baa646..3a139dc64cf 100644
--- a/intern/opencolorio/CMakeLists.txt
+++ b/intern/opencolorio/CMakeLists.txt
@@ -62,6 +62,8 @@ if(WITH_OPENCOLORIO)
${BOOST_INCLUDE_DIR}
)
endif()
+
+ data_to_c_simple(gpu_shader_display_transform.glsl SRC)
endif()
diff --git a/intern/opencolorio/SConscript b/intern/opencolorio/SConscript
index 7f050f25cae..70aa9000719 100644
--- a/intern/opencolorio/SConscript
+++ b/intern/opencolorio/SConscript
@@ -39,6 +39,13 @@ if env['WITH_BF_OCIO']:
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
incs += ' ' + env['BF_BOOST_INC']
+
+ # generated data files
+ import os
+ sources.extend((
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_display_transform.glsl.c"),
+ ))
+
else:
sources.remove('ocio_impl.cc')
sources.remove('ocio_impl_glsl.cc')
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc
index 36dac689287..ca999eab569 100644
--- a/intern/opencolorio/fallback_impl.cc
+++ b/intern/opencolorio/fallback_impl.cc
@@ -418,7 +418,8 @@ bool FallbackImpl::supportGLSLDraw(void)
return false;
}
-bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/, OCIO_ConstProcessorRcPtr * /*processor*/, bool /*predivide*/)
+bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/, OCIO_ConstProcessorRcPtr * /*processor*/,
+ OCIO_CurveMappingSettings * /*curve_mapping_settings*/, bool /*predivide*/)
{
return false;
}
diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl
new file mode 100644
index 00000000000..6ba3fa55e8f
--- /dev/null
+++ b/intern/opencolorio/gpu_shader_display_transform.glsl
@@ -0,0 +1,123 @@
+uniform sampler2D image_texture;
+uniform sampler3D lut3d_texture;
+uniform bool predivide;
+
+#ifdef USE_CURVE_MAPPING
+/* Curve mapping parameters
+ *
+ * See documentation for OCIO_CurveMappingSettings to get fields descriptions.
+ * (this ones pretyt much copies stuff from C structure.)
+ */
+uniform sampler1D curve_mapping_texture;
+uniform int curve_mapping_lut_size;
+uniform ivec4 use_curve_mapping_extend_extrapolate;
+uniform vec4 curve_mapping_mintable;
+uniform vec4 curve_mapping_range;
+uniform vec4 curve_mapping_ext_in_x;
+uniform vec4 curve_mapping_ext_in_y;
+uniform vec4 curve_mapping_ext_out_x;
+uniform vec4 curve_mapping_ext_out_y;
+uniform vec4 curve_mapping_first_x;
+uniform vec4 curve_mapping_first_y;
+uniform vec4 curve_mapping_last_x;
+uniform vec4 curve_mapping_last_y;
+uniform vec3 curve_mapping_black;
+uniform vec3 curve_mapping_bwmul;
+
+float read_curve_mapping(int table, int index)
+{
+ /* TODO(sergey): Without -1 here image is getting darken after applying unite curve.
+ * But is it actually correct to subtract 1 here?
+ */
+ float texture_index = float(index) / float(curve_mapping_lut_size - 1);
+ return texture1D(curve_mapping_texture, texture_index) [table];
+}
+
+float curvemap_calc_extend(int table, float x, vec2 first, vec2 last)
+{
+ if (x <= first[0]) {
+ if (use_curve_mapping_extend_extrapolate[table] == 0) {
+ /* no extrapolate */
+ return first[1];
+ }
+ else {
+ if (curve_mapping_ext_in_x[table] == 0.0)
+ return first[1] + curve_mapping_ext_in_y[table] * 10000.0;
+ else
+ return first[1] + curve_mapping_ext_in_y[table] * (x - first[0]) / curve_mapping_ext_in_x[table];
+ }
+ }
+ else if (x >= last[0]) {
+ if (use_curve_mapping_extend_extrapolate[table] == 0) {
+ /* no extrapolate */
+ return last[1];
+ }
+ else {
+ if (curve_mapping_ext_out_x[table] == 0.0)
+ return last[1] - curve_mapping_ext_out_y[table] * 10000.0;
+ else
+ return last[1] + curve_mapping_ext_out_y[table] * (x - last[0]) / curve_mapping_ext_out_x[table];
+ }
+ }
+ return 0.0;
+}
+
+float curvemap_evaluateF(int table, float value)
+{
+ float mintable_ = curve_mapping_mintable[table];
+ float range = curve_mapping_range[table];
+ float mintable = 0.0;
+ int CM_TABLE = curve_mapping_lut_size - 1;
+
+ float fi;
+ int i;
+
+ /* index in table */
+ fi = (value - mintable) * range;
+ i = int(fi);
+
+ /* fi is table float index and should check against table range i.e. [0.0 CM_TABLE] */
+ if (fi < 0.0 || fi > float(CM_TABLE)) {
+ return curvemap_calc_extend(table, value,
+ vec2(curve_mapping_first_x[table], curve_mapping_first_y[table]),
+ vec2(curve_mapping_last_x[table], curve_mapping_last_y[table]));
+ }
+ else {
+ if (i < 0) return read_curve_mapping(table, 0);
+ if (i >= CM_TABLE) return read_curve_mapping(table, CM_TABLE);
+
+ fi = fi - float(i);
+ return (1.0 - fi) * read_curve_mapping(table, i) + fi * read_curve_mapping(table, i + 1);
+ }
+}
+
+vec4 curvemapping_evaluate_premulRGBF(vec4 col)
+{
+ vec4 result = col;
+ result[0] = curvemap_evaluateF(0, (col[0] - curve_mapping_black[0]) * curve_mapping_bwmul[0]);
+ result[1] = curvemap_evaluateF(1, (col[1] - curve_mapping_black[1]) * curve_mapping_bwmul[1]);
+ result[2] = curvemap_evaluateF(2, (col[2] - curve_mapping_black[2]) * curve_mapping_bwmul[2]);
+ result[3] = col[3];
+ return result;
+}
+#endif
+
+void main()
+{
+ vec4 col = texture2D(image_texture, gl_TexCoord[0].st);
+#ifdef USE_CURVE_MAPPING
+ col = curvemapping_evaluate_premulRGBF(col);
+#endif
+ if (predivide && col[3] > 0.0 && col[3] < 1.0) {
+ float inv_alpha = 1.0 / col[3];
+ col[0] *= inv_alpha;
+ col[1] *= inv_alpha;
+ col[2] *= inv_alpha;
+ }
+
+ /* NOTE: This is true we only do de-premul here and NO premul
+ * and the reason is simple -- opengl is always configured
+ * for straight alpha at this moment
+ */
+ gl_FragColor = OCIODisplay(col, lut3d_texture);
+}
diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc
index 1656ad9cbc0..30668dff245 100644
--- a/intern/opencolorio/ocio_capi.cc
+++ b/intern/opencolorio/ocio_capi.cc
@@ -323,9 +323,10 @@ int OCIO_supportGLSLDraw(void)
return (int) impl->supportGLSLDraw();
}
-int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide)
+int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide)
{
- return (int) impl->setupGLSLDraw(state_r, processor, (bool) predivide);
+ return (int) impl->setupGLSLDraw(state_r, processor, curve_mapping_settings, predivide);
}
void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state)
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
index 0846b8ff7b3..5532ade1f3a 100644
--- a/intern/opencolorio/ocio_capi.h
+++ b/intern/opencolorio/ocio_capi.h
@@ -54,6 +54,62 @@ OCIO_DECLARE_HANDLE(OCIO_ExponentTransformRcPtr);
OCIO_DECLARE_HANDLE(OCIO_MatrixTransformRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstLookRcPtr);
+/* This structure is used to pass curve mapping settings from
+ * blender's DNA structure stored in view transform settings
+ * to a generic OpenColorIO C-API.
+ */
+typedef struct OCIO_CurveMappingSettings {
+ /* This is a LUT which contain values for all 4 curve mapping tables
+ * (combined, R, G and B).
+ *
+ * Element I for table T is stored at I * 4 + T element of this LUT.
+ *
+ * This array is usually returned by curvemapping_table_RGBA().
+ */
+ float *lut;
+
+ /* Size of single curve mapping table, 1/4 size of lut array. */
+ int lut_size;
+
+ /* Extend extrapolation flags for all the tables.
+ * if use_extend_extrapolate[T] != 0 means extrapolation for
+ * table T is needed.
+ */
+ int use_extend_extrapolate[4];
+
+ /* Minimal X value of the curve mapping tables. */
+ float mintable[4];
+
+ /* Per curve mapping table range. */
+ float range[4];
+
+ /* Lower extension value, stored as per-component arrays. */
+ float ext_in_x[4], ext_in_y[4];
+
+ /* Higher extension value, stored as per-component arrays. */
+ float ext_out_x[4], ext_out_y[4];
+
+ /* First points of the tables, both X and Y values.
+ * Needed for easier and faster access when extrapolating.
+ */
+ float first_x[4], first_y[4];
+
+ /* Last points of the tables, both X and Y values.
+ * Needed for easier and faster access when extrapolating.
+ */
+ float last_x[4], last_y[4];
+
+ /* Premultiplication settings: black level and scale to match
+ * with white level.
+ */
+ float black[3], bwmul[3];
+
+ /* Cache id of the original curve mapping, used to detect when
+ * upload of new settings to GPU is needed.
+ */
+ size_t cache_id;
+} OCIO_CurveMappingSettings;
+
void OCIO_init(void);
void OCIO_exit(void);
@@ -132,7 +188,8 @@ void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt);
void OCIO_matrixTransformScale(float *m44, float *offset4, const float *scale4);
int OCIO_supportGLSLDraw(void);
-int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide);
+int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state);
diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc
index dff25f238a7..2cffe1a89ef 100644
--- a/intern/opencolorio/ocio_impl.cc
+++ b/intern/opencolorio/ocio_impl.cc
@@ -55,9 +55,6 @@ using namespace OCIO_NAMESPACE;
# define __func__ __FUNCTION__
#endif
-#define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type()
-#define MEM_DELETE(what, type) if (what) { ((type*)(what))->~type(); MEM_freeN(what); } (void)0
-
static void OCIO_reportError(const char *err)
{
std::cerr << "OpenColorIO Error: " << err << std::endl;
@@ -72,7 +69,7 @@ static void OCIO_reportException(Exception &exception)
OCIO_ConstConfigRcPtr *OCIOImpl::getCurrentConfig(void)
{
- ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
+ ConstConfigRcPtr *config = OBJECT_GUARDED_NEW(ConstConfigRcPtr);
try {
*config = GetCurrentConfig();
@@ -84,7 +81,7 @@ OCIO_ConstConfigRcPtr *OCIOImpl::getCurrentConfig(void)
OCIO_reportException(exception);
}
- MEM_DELETE(config, ConstConfigRcPtr);
+ OBJECT_GUARDED_DELETE(config, ConstConfigRcPtr);
return NULL;
}
@@ -101,7 +98,7 @@ void OCIOImpl::setCurrentConfig(const OCIO_ConstConfigRcPtr *config)
OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromEnv(void)
{
- ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
+ ConstConfigRcPtr *config = OBJECT_GUARDED_NEW(ConstConfigRcPtr);
try {
*config = Config::CreateFromEnv();
@@ -113,7 +110,7 @@ OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromEnv(void)
OCIO_reportException(exception);
}
- MEM_DELETE(config, ConstConfigRcPtr);
+ OBJECT_GUARDED_DELETE(config, ConstConfigRcPtr);
return NULL;
}
@@ -121,7 +118,7 @@ OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromEnv(void)
OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromFile(const char *filename)
{
- ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
+ ConstConfigRcPtr *config = OBJECT_GUARDED_NEW(ConstConfigRcPtr);
try {
*config = Config::CreateFromFile(filename);
@@ -133,14 +130,14 @@ OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromFile(const char *filename)
OCIO_reportException(exception);
}
- MEM_DELETE(config, ConstConfigRcPtr);
+ OBJECT_GUARDED_DELETE(config, ConstConfigRcPtr);
return NULL;
}
void OCIOImpl::configRelease(OCIO_ConstConfigRcPtr *config)
{
- MEM_DELETE((ConstConfigRcPtr *) config, ConstConfigRcPtr);
+ OBJECT_GUARDED_DELETE((ConstConfigRcPtr *) config, ConstConfigRcPtr);
}
int OCIOImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config)
@@ -169,7 +166,7 @@ const char *OCIOImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *conf
OCIO_ConstColorSpaceRcPtr *OCIOImpl::configGetColorSpace(OCIO_ConstConfigRcPtr *config, const char *name)
{
- ConstColorSpaceRcPtr *cs = MEM_NEW(ConstColorSpaceRcPtr);
+ ConstColorSpaceRcPtr *cs = OBJECT_GUARDED_NEW(ConstColorSpaceRcPtr);
try {
*cs = (*(ConstConfigRcPtr *) config)->getColorSpace(name);
@@ -181,7 +178,7 @@ OCIO_ConstColorSpaceRcPtr *OCIOImpl::configGetColorSpace(OCIO_ConstConfigRcPtr *
OCIO_reportException(exception);
}
- MEM_DELETE(cs, ConstColorSpaceRcPtr);
+ OBJECT_GUARDED_DELETE(cs, ConstColorSpaceRcPtr);
return NULL;
}
@@ -308,7 +305,7 @@ const char *OCIOImpl::configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, in
OCIO_ConstLookRcPtr *OCIOImpl::configGetLook(OCIO_ConstConfigRcPtr *config, const char *name)
{
- ConstLookRcPtr *look = MEM_NEW(ConstLookRcPtr);
+ ConstLookRcPtr *look = OBJECT_GUARDED_NEW(ConstLookRcPtr);
try {
*look = (*(ConstConfigRcPtr *) config)->getLook(name);
@@ -320,7 +317,7 @@ OCIO_ConstLookRcPtr *OCIOImpl::configGetLook(OCIO_ConstConfigRcPtr *config, cons
OCIO_reportException(exception);
}
- MEM_DELETE(look, ConstLookRcPtr);
+ OBJECT_GUARDED_DELETE(look, ConstLookRcPtr);
return NULL;
}
@@ -332,7 +329,7 @@ const char *OCIOImpl::lookGetProcessSpace(OCIO_ConstLookRcPtr *look)
void OCIOImpl::lookRelease(OCIO_ConstLookRcPtr *look)
{
- MEM_DELETE((ConstLookRcPtr *) look, ConstLookRcPtr);
+ OBJECT_GUARDED_DELETE((ConstLookRcPtr *) look, ConstLookRcPtr);
}
int OCIOImpl::colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs_)
@@ -367,12 +364,12 @@ int OCIOImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs)
void OCIOImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
{
- MEM_DELETE((ConstColorSpaceRcPtr *) cs, ConstColorSpaceRcPtr);
+ OBJECT_GUARDED_DELETE((ConstColorSpaceRcPtr *) cs, ConstColorSpaceRcPtr);
}
OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName)
{
- ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
+ ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
try {
*p = (*(ConstConfigRcPtr *) config)->getProcessor(srcName, dstName);
@@ -384,14 +381,14 @@ OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfig
OCIO_reportException(exception);
}
- MEM_DELETE(p, ConstProcessorRcPtr);
+ OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr);
return 0;
}
OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessor(OCIO_ConstConfigRcPtr *config, OCIO_ConstTransformRcPtr *transform)
{
- ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
+ ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
try {
*p = (*(ConstConfigRcPtr *) config)->getProcessor(*(ConstTransformRcPtr *) transform);
@@ -403,7 +400,7 @@ OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessor(OCIO_ConstConfigRcPtr *co
OCIO_reportException(exception);
}
- MEM_DELETE(p, ConstProcessorRcPtr);
+ OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr);
return NULL;
}
@@ -482,7 +479,7 @@ void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor,
void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *p)
{
- MEM_DELETE(p, ConstProcessorRcPtr);
+ OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr);
}
const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
@@ -502,7 +499,7 @@ const char *OCIOImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs)
OCIO_DisplayTransformRcPtr *OCIOImpl::createDisplayTransform(void)
{
- DisplayTransformRcPtr *dt = MEM_NEW(DisplayTransformRcPtr);
+ DisplayTransformRcPtr *dt = OBJECT_GUARDED_NEW(DisplayTransformRcPtr);
*dt = DisplayTransform::Create();
@@ -546,7 +543,7 @@ void OCIOImpl::displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPt
void OCIOImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *dt)
{
- MEM_DELETE((DisplayTransformRcPtr *) dt, DisplayTransformRcPtr);
+ OBJECT_GUARDED_DELETE((DisplayTransformRcPtr *) dt, DisplayTransformRcPtr);
}
OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels,
@@ -567,12 +564,12 @@ OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data, long wid
void OCIOImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id)
{
- MEM_DELETE((PackedImageDesc *) id, PackedImageDesc);
+ OBJECT_GUARDED_DELETE((PackedImageDesc *) id, PackedImageDesc);
}
OCIO_ExponentTransformRcPtr *OCIOImpl::createExponentTransform(void)
{
- ExponentTransformRcPtr *et = MEM_NEW(ExponentTransformRcPtr);
+ ExponentTransformRcPtr *et = OBJECT_GUARDED_NEW(ExponentTransformRcPtr);
*et = ExponentTransform::Create();
@@ -586,12 +583,12 @@ void OCIOImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const
void OCIOImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr *et)
{
- MEM_DELETE((ExponentTransformRcPtr *) et, ExponentTransformRcPtr);
+ OBJECT_GUARDED_DELETE((ExponentTransformRcPtr *) et, ExponentTransformRcPtr);
}
OCIO_MatrixTransformRcPtr *OCIOImpl::createMatrixTransform(void)
{
- MatrixTransformRcPtr *mt = MEM_NEW(MatrixTransformRcPtr);
+ MatrixTransformRcPtr *mt = OBJECT_GUARDED_NEW(MatrixTransformRcPtr);
*mt = MatrixTransform::Create();
@@ -605,7 +602,7 @@ void OCIOImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, const floa
void OCIOImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt)
{
- MEM_DELETE((MatrixTransformRcPtr *) mt, MatrixTransformRcPtr);
+ OBJECT_GUARDED_DELETE((MatrixTransformRcPtr *) mt, MatrixTransformRcPtr);
}
void OCIOImpl::matrixTransformScale(float *m44, float *offset4, const float *scale4f)
diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h
index 48d18fa78ea..8b666e8ae14 100644
--- a/intern/opencolorio/ocio_impl.h
+++ b/intern/opencolorio/ocio_impl.h
@@ -106,7 +106,8 @@ public:
virtual void matrixTransformScale(float * m44, float * offset4, const float * scale4) = 0;
virtual bool supportGLSLDraw(void) = 0;
- virtual bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide) = 0;
+ virtual bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide) = 0;
virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0;
virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0;
};
@@ -189,7 +190,8 @@ public:
void matrixTransformScale(float *m44, float *offset4, const float *scale4);
bool supportGLSLDraw(void);
- bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide);
+ bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
};
@@ -273,7 +275,8 @@ public:
void matrixTransformScale(float * m44, float * offset4, const float * scale4);
bool supportGLSLDraw(void);
- bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide);
+ bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
};
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index 1a3132fa4b3..2af3befc8a9 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -48,6 +48,8 @@ using namespace OCIO_NAMESPACE;
static const int LUT3D_EDGE_SIZE = 64;
+extern "C" char datatoc_gpu_shader_display_transform_glsl[];
+
/* **** OpenGL drawing routines using GLSL for color space transform ***** */
typedef struct OCIO_GLSLDrawState {
@@ -60,42 +62,24 @@ typedef struct OCIO_GLSLDrawState {
float *lut3d; /* 3D LUT table */
+ bool curve_mapping_used;
+ bool curve_mapping_texture_allocated;
+ bool curve_mapping_texture_valid;
+ GLuint curve_mapping_texture;
+ size_t curve_mapping_cache_id;
+
/* Cache */
std::string lut3dcacheid;
std::string shadercacheid;
/* GLSL stuff */
- GLuint fragShader;
+ GLuint ocio_shader;
GLuint program;
/* Previous OpenGL state. */
GLint last_texture, last_texture_unit;
} OCIO_GLSLDrawState;
-/* Hardcoded to do alpha predivide before color space conversion */
-/* NOTE: This is true we only do de-premul here and NO premul
- * and the reason is simple -- opengl is always configured
- * for straight alpha at this moment
- */
-static const char *g_fragShaderText = ""
-"\n"
-"uniform sampler2D tex1;\n"
-"uniform sampler3D tex2;\n"
-"uniform bool predivide;\n"
-"\n"
-"void main()\n"
-"{\n"
-" vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n"
-" if (predivide && col[3] > 0.0 && col[3] < 1.0) {\n"
-" float inv_alpha = 1.0 / col[3];\n"
-" col[0] *= inv_alpha;\n"
-" col[1] *= inv_alpha;\n"
-" col[2] *= inv_alpha;\n"
-" }\n"
-" gl_FragColor = OCIODisplay(col, tex2);\n"
-"\n"
-"}\n";
-
static GLuint compileShaderText(GLenum shaderType, const char *text)
{
GLuint shader;
@@ -117,15 +101,14 @@ static GLuint compileShaderText(GLenum shaderType, const char *text)
return shader;
}
-static GLuint linkShaders(GLuint fragShader)
+static GLuint linkShaders(GLuint ocio_shader)
{
- if (!fragShader)
+ if (!ocio_shader)
return 0;
GLuint program = glCreateProgram();
- if (fragShader)
- glAttachShader(program, fragShader);
+ glAttachShader(program, ocio_shader);
glLinkProgram(program);
@@ -197,6 +180,37 @@ static bool ensureLUT3DAllocated(OCIO_GLSLDrawState *state)
return state->lut3d_texture_valid;
}
+static bool ensureCurveMappingAllocated(OCIO_GLSLDrawState *state, OCIO_CurveMappingSettings *curve_mapping_settings)
+{
+ if (state->curve_mapping_texture_allocated)
+ return state->curve_mapping_texture_valid;
+
+ glGenTextures(1, &state->curve_mapping_texture);
+
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_1D, state->curve_mapping_texture);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
+ /* clean glError buffer */
+ while (glGetError() != GL_NO_ERROR) {}
+
+ glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16F_ARB, curve_mapping_settings->lut_size,
+ 0, GL_RGBA, GL_FLOAT, curve_mapping_settings->lut);
+
+ state->curve_mapping_texture_allocated = true;
+
+ /* GL_RGB16F_ARB could be not supported at some drivers
+ * in this case we could not use GLSL display
+ */
+ state->curve_mapping_texture_valid = glGetError() == GL_NO_ERROR;
+
+ return state->curve_mapping_texture_valid;
+}
+
/* Detect if we can support GLSL drawing */
bool OCIOImpl::supportGLSLDraw()
{
@@ -214,9 +228,11 @@ bool OCIOImpl::supportGLSLDraw()
* When all drawing is finished, finishGLSLDraw shall be called to
* restore OpenGL context to it's pre-GLSL draw state.
*/
-bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide)
+bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide)
{
ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor;
+ bool use_curve_mapping = curve_mapping_settings != NULL;
/* Create state if needed. */
OCIO_GLSLDrawState *state;
@@ -234,12 +250,36 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
return false;
}
+ if (use_curve_mapping) {
+ if (!ensureCurveMappingAllocated(state, curve_mapping_settings)) {
+ glActiveTexture(state->last_texture_unit);
+ glBindTexture(GL_TEXTURE_2D, state->last_texture);
+
+ return false;
+ }
+ }
+ else {
+ if (state->curve_mapping_texture_allocated) {
+ glDeleteTextures(1, &state->curve_mapping_texture);
+ state->curve_mapping_texture_allocated = false;
+ }
+ }
+
/* Step 1: Create a GPU Shader Description */
GpuShaderDesc shaderDesc;
shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_0);
shaderDesc.setFunctionName("OCIODisplay");
shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
+ if (use_curve_mapping) {
+ if (state->curve_mapping_cache_id != curve_mapping_settings->cache_id) {
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_1D, state->curve_mapping_texture);
+ glTexSubImage1D(GL_TEXTURE_1D, 0, 0, curve_mapping_settings->lut_size,
+ GL_RGBA, GL_FLOAT, curve_mapping_settings->lut);
+ }
+ }
+
/* Step 2: Compute the 3D LUT */
std::string lut3dCacheID = ocio_processor->getGpuLut3DCacheID(shaderDesc);
if (lut3dCacheID != state->lut3dcacheid) {
@@ -255,37 +295,73 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
/* Step 3: Compute the Shader */
std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc);
- if (state->program == 0 || shaderCacheID != state->shadercacheid) {
+ if (state->program == 0 ||
+ shaderCacheID != state->shadercacheid ||
+ use_curve_mapping != state->curve_mapping_used)
+ {
state->shadercacheid = shaderCacheID;
+ if (state->program) {
+ glDeleteProgram(state->program);
+ }
+
+ if (state->ocio_shader) {
+ glDeleteShader(state->ocio_shader);
+ }
+
std::ostringstream os;
- os << ocio_processor->getGpuShaderText(shaderDesc) << "\n";
- os << g_fragShaderText;
- if (state->fragShader)
- glDeleteShader(state->fragShader);
+ if (use_curve_mapping) {
+ os << "#define USE_CURVE_MAPPING\n";
+ }
- state->fragShader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
+ os << ocio_processor->getGpuShaderText(shaderDesc) << "\n";
+ os << datatoc_gpu_shader_display_transform_glsl;
- if (state->fragShader) {
- if (state->program)
- glDeleteProgram(state->program);
+ state->ocio_shader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
- state->program = linkShaders(state->fragShader);
+ if (state->ocio_shader) {
+ state->program = linkShaders(state->ocio_shader);
}
+
+ state->curve_mapping_used = use_curve_mapping;
}
if (state->program) {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
+ if (use_curve_mapping) {
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_1D, state->curve_mapping_texture);
+ }
+
glActiveTexture(GL_TEXTURE0);
glUseProgram(state->program);
- glUniform1i(glGetUniformLocation(state->program, "tex1"), 0);
- glUniform1i(glGetUniformLocation(state->program, "tex2"), 1);
+
+ glUniform1i(glGetUniformLocation(state->program, "image_texture"), 0);
+ glUniform1i(glGetUniformLocation(state->program, "lut3d_texture"), 1);
glUniform1i(glGetUniformLocation(state->program, "predivide"), predivide);
+ if (use_curve_mapping) {
+ glUniform1i(glGetUniformLocation(state->program, "curve_mapping_texture"), 2);
+ glUniform1i(glGetUniformLocation(state->program, "curve_mapping_lut_size"), curve_mapping_settings->lut_size);
+ glUniform4iv(glGetUniformLocation(state->program, "use_curve_mapping_extend_extrapolate"), 1, curve_mapping_settings->use_extend_extrapolate);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_mintable"), 1, curve_mapping_settings->mintable);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_range"), 1, curve_mapping_settings->range);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_ext_in_x"), 1, curve_mapping_settings->ext_in_x);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_ext_in_y"), 1, curve_mapping_settings->ext_in_y);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_ext_out_x"), 1, curve_mapping_settings->ext_out_x);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_ext_out_y"), 1, curve_mapping_settings->ext_out_y);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_first_x"), 1, curve_mapping_settings->first_x);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_first_y"), 1, curve_mapping_settings->first_y);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_last_x"), 1, curve_mapping_settings->last_x);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_last_y"), 1, curve_mapping_settings->last_y);
+ glUniform3fv(glGetUniformLocation(state->program, "curve_mapping_black"), 1, curve_mapping_settings->black);
+ glUniform3fv(glGetUniformLocation(state->program, "curve_mapping_bwmul"), 1, curve_mapping_settings->bwmul);
+ }
+
return true;
}
else {
@@ -316,8 +392,8 @@ void OCIOImpl::freeGLState(struct OCIO_GLSLDrawState *state)
if (state->program)
glDeleteProgram(state->program);
- if (state->fragShader)
- glDeleteShader(state->fragShader);
+ if (state->ocio_shader)
+ glDeleteShader(state->ocio_shader);
state->lut3dcacheid.~string();
state->shadercacheid.~string();
diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png
index 9551fad2fac..4ee82bcbb62 100644
--- a/release/datafiles/splash.png
+++ b/release/datafiles/splash.png
Binary files differ
diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py
index e6ccb419059..da1a52e560d 100644
--- a/release/scripts/modules/bpy/path.py
+++ b/release/scripts/modules/bpy/path.py
@@ -163,6 +163,7 @@ def display_name(name):
"""
# string replacements
name = name.replace("_colon_", ":")
+ name = name.replace("_plus_", "+")
name = name.replace("_", " ")
diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py
index a4fd2c996cb..60b11884e30 100644
--- a/release/scripts/modules/rna_info.py
+++ b/release/scripts/modules/rna_info.py
@@ -648,7 +648,8 @@ def BuildRNAInfo():
for prop in func.return_values:
prop.build()
- if 1:
+ # there are too many invalid defaults, unless we intend to fix, leave this off
+ if 0:
for rna_info in InfoStructRNA.global_lookup.values():
for prop in rna_info.properties:
# ERROR CHECK
diff --git a/release/scripts/modules/rna_keymap_ui.py b/release/scripts/modules/rna_keymap_ui.py
index 727e9935bcc..60590158fbd 100644
--- a/release/scripts/modules/rna_keymap_ui.py
+++ b/release/scripts/modules/rna_keymap_ui.py
@@ -74,15 +74,14 @@ def draw_km(display_keymaps, kc, km, children, layout, level):
row.prop(km, "show_expanded_children", text="", emboss=False)
row.label(text=km.name, text_ctxt=i18n_contexts.id_windowmanager)
- row.label()
- row.label()
+ subrow = row.row()
+ subrow.alignment = 'RIGHT'
- if km.is_modal:
- row.label(text="", icon='LINKED')
if km.is_user_modified:
- row.operator("wm.keymap_restore", text="Restore")
- else:
- row.label()
+ subrow.operator("wm.keymap_restore", text="Restore")
+ if km.is_modal:
+ subrow.label(text="", icon='LINKED')
+ del subrow
if km.show_expanded_children:
if children:
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index c22b2546309..21fd757c4e5 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -655,8 +655,10 @@ kmi = km.keymap_items.new('mesh.duplicate_move', 'D', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True)
kmi.properties.name = 'INFO_MT_mesh_add'
kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'MIDDLEMOUSE', 'CLICK', ctrl=True)
-kmi = km.keymap_items.new('mesh.delete', 'BACK_SPACE', 'PRESS')
-kmi = km.keymap_items.new('mesh.delete', 'DEL', 'PRESS')
+kmi = km.keymap_items.new('wm.call_menu', 'BACK_SPACE', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_edit_mesh_delete'
+kmi = km.keymap_items.new('wm.call_menu', 'DEL', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_edit_mesh_delete'
kmi = km.keymap_items.new('mesh.knife_tool', 'LEFTMOUSE', 'PRESS', key_modifier='K')
kmi = km.keymap_items.new('object.vertex_parent_set', 'P', 'PRESS')
kmi = km.keymap_items.new('wm.call_menu', 'RIGHTMOUSE', 'PRESS', ctrl=True)
diff --git a/release/scripts/presets/operator/wm.collada_export/second_life_rigged.py b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py
index 717e044ccd6..7825a4d0f32 100644
--- a/release/scripts/presets/operator/wm.collada_export/second_life_rigged.py
+++ b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py
@@ -15,4 +15,4 @@ op.use_texture_copies = True
op.triangulate = True
op.use_object_instantiation = False
op.sort_by_name = True
-op.second_life = True
+op.open_sim = True
diff --git a/release/scripts/presets/operator/wm.collada_export/second_life_static.py b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py
index 9518fe5fb35..9e2efcaa727 100644
--- a/release/scripts/presets/operator/wm.collada_export/second_life_static.py
+++ b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py
@@ -15,4 +15,4 @@ op.use_texture_copies = True
op.triangulate = True
op.use_object_instantiation = False
op.sort_by_name = True
-op.second_life = False
+op.open_sim = False
diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py
index 9b629c3f976..77978c71ed9 100644
--- a/release/scripts/startup/bl_operators/node.py
+++ b/release/scripts/startup/bl_operators/node.py
@@ -113,8 +113,11 @@ class NodeAddOperator():
# Default execute simply adds a node
def execute(self, context):
- self.create_node(context)
- return {'FINISHED'}
+ if self.properties.is_property_set("type"):
+ self.create_node(context)
+ return {'FINISHED'}
+ else:
+ return {'CANCELLED'}
# Default invoke stores the mouse position to place the node correctly
# and optionally invokes the transform operator
diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
index f8f4b8d35e6..6f54c051c0b 100644
--- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py
+++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
@@ -556,8 +556,6 @@ def lightmap_uvpack(meshes,
print("finished all %.2f " % (time.time() - t))
- # Window.RedrawAll()
-
def unwrap(operator, context, **kwargs):
@@ -590,7 +588,7 @@ from bpy.props import BoolProperty, FloatProperty, IntProperty
class LightMapPack(Operator):
- """Follow UVs from active quads along continuous face loops"""
+ """Pack each faces UV's into the UV bounds"""
bl_idname = "uv.lightmap_pack"
bl_label = "Lightmap Pack"
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 909842d3c2b..5a249159d86 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -498,7 +498,7 @@ class WM_OT_context_menu_enum(Operator):
class WM_OT_context_set_id(Operator):
- """Toggle a context value"""
+ """Set a context value to an ID data-block"""
bl_idname = "wm.context_set_id"
bl_label = "Set Library ID"
bl_options = {'UNDO', 'INTERNAL'}
@@ -903,8 +903,9 @@ class WM_OT_doc_view(Operator):
return {'FINISHED'}
+'''
class WM_OT_doc_edit(Operator):
- """Load online reference docs"""
+ """Edit online reference docs"""
bl_idname = "wm.doc_edit"
bl_label = "Edit Documentation"
@@ -972,6 +973,7 @@ class WM_OT_doc_edit(Operator):
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self, width=600)
+'''
rna_path = StringProperty(
@@ -1893,7 +1895,7 @@ class WM_OT_addon_install(Operator):
class WM_OT_addon_remove(Operator):
- "Disable an addon"
+ "Delete the addon from the file system"
bl_idname = "wm.addon_remove"
bl_label = "Remove Addon"
@@ -1935,6 +1937,8 @@ class WM_OT_addon_remove(Operator):
else:
os.remove(path)
+ addon_utils.modules_refresh()
+
context.area.tag_redraw()
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py
index 18dd8f591e8..a96441a26e5 100644
--- a/release/scripts/startup/bl_ui/properties_freestyle.py
+++ b/release/scripts/startup/bl_ui/properties_freestyle.py
@@ -530,6 +530,8 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
linestyle = lineset.linestyle
layout.template_ID(lineset, "linestyle", new="scene.freestyle_linestyle_new")
+ if linestyle is None:
+ return
row = layout.row(align=True)
row.prop(linestyle, "panel", expand=True)
if linestyle.panel == 'STROKES':
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index aa4d671e938..45f3471ad35 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -222,6 +222,11 @@ class MASK_PT_display():
layout.prop(space_data, "mask_draw_type", text="")
layout.prop(space_data, "show_mask_smooth")
+ layout.prop(space_data, "show_mask_overlay")
+ row = layout.row()
+ row.active = space_data.show_mask_overlay
+ row.prop(space_data, "mask_overlay_mode", text="")
+
class MASK_PT_tools():
# subclasses must define...
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index eff538971c0..bb0b137da0a 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -518,7 +518,7 @@ class MATERIAL_PT_sss(MaterialButtonsPanel, Panel):
layout.active = (sss.use) and (not mat.use_shadeless)
row = layout.row().split()
- sub = row.row(align=True).split(percentage=0.75)
+ sub = row.row(align=True).split(align=True, percentage=0.75)
sub.menu("MATERIAL_MT_sss_presets", text=bpy.types.MATERIAL_MT_sss_presets.bl_label)
sub.operator("material.sss_preset_add", text="", icon='ZOOMIN')
sub.operator("material.sss_preset_add", text="", icon='ZOOMOUT').remove_active = True
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 5995b765ae6..e27d80bc8c3 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -134,13 +134,12 @@ def brush_mask_texture_settings(layout, brush):
layout.operator("brush.stencil_fit_image_aspect").mask = True
layout.operator("brush.stencil_reset_transform").mask = True
- if brush.mask_texture:
- col = layout.column()
- col.label(text="Angle:")
- col.active = brush.brush_capabilities.has_texture_angle
- col.prop(mask_tex_slot, "angle", text="")
-
- # scale and offset
- split = layout.split()
- split.prop(mask_tex_slot, "offset")
- split.prop(mask_tex_slot, "scale")
+ col = layout.column()
+ col.label(text="Angle:")
+ col.active = brush.brush_capabilities.has_texture_angle
+ col.prop(mask_tex_slot, "angle", text="")
+
+ # scale and offset
+ split = layout.split()
+ split.prop(mask_tex_slot, "offset")
+ split.prop(mask_tex_slot, "scale")
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index e11f179e2cb..288f95ca4b0 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -501,7 +501,7 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
layout.prop(rd, "bake_type")
multires_bake = False
- if rd.bake_type in ['NORMALS', 'DISPLACEMENT', 'AO']:
+ if rd.bake_type in ['NORMALS', 'DISPLACEMENT', 'DERIVATIVE', 'AO']:
layout.prop(rd, "use_bake_multires")
multires_bake = rd.use_bake_multires
@@ -542,11 +542,20 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
if rd.bake_type == 'DISPLACEMENT':
col = split.column()
col.prop(rd, "use_bake_lores_mesh")
+
if rd.bake_type == 'AO':
col = split.column()
col.prop(rd, "bake_bias")
col.prop(rd, "bake_samples")
+ if rd.bake_type == 'DERIVATIVE':
+ row = layout.row()
+ row.prop(rd, "use_bake_user_scale", text="")
+
+ sub = row.column()
+ sub.active = rd.use_bake_user_scale
+ sub.prop(rd, "bake_user_scale", text="User Scale")
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 398d1596216..17ed7b44cf1 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -390,7 +390,7 @@ class IMAGE_HT_header(Header):
if show_maskedit:
sub.menu("MASK_MT_mask")
- layout.template_ID(sima, "image", new="image.new")
+ layout.template_ID(sima, "image", new="image.new", open="image.open")
if not show_render:
layout.prop(sima, "use_image_pin", text="")
@@ -715,8 +715,8 @@ class IMAGE_PT_paint(Panel, ImagePaintPanel):
col.prop(brush, "clone_alpha", text="Alpha")
-class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
- bl_label = "Texture"
+class IMAGE_PT_tools_brush_overlay(BrushButtonsPanel, Panel):
+ bl_label = "Overlay"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
@@ -725,17 +725,24 @@ class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
toolsettings = context.tool_settings.image_paint
brush = toolsettings.brush
tex_slot = brush.texture_slot
+ tex_slot_mask = brush.mask_texture_slot
col = layout.column()
- col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
+
+ col.label(text="Curve:")
- brush_texture_settings(col, brush, 0)
+ row = col.row(align=True)
+ if brush.use_cursor_overlay:
+ row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
+ else:
+ row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
- # use_texture_overlay and texture_overlay_alpha
- col = layout.column(align=True)
- col.active = brush.brush_capabilities.has_overlay
- col.label(text="Overlay:")
+ sub = row.row(align=True)
+ sub.prop(brush, "cursor_overlay_alpha", text="Alpha")
+ sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
+ col.active = brush.brush_capabilities.has_overlay
+ col.label(text="Texture:")
row = col.row(align=True)
if tex_slot.map_mode != 'STENCIL':
if brush.use_primary_overlay:
@@ -747,6 +754,36 @@ class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
sub.prop(brush, "texture_overlay_alpha", text="Alpha")
sub.prop(brush, "use_primary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
+ col.label(text="Mask Texture:")
+
+ row = col.row(align=True)
+ if tex_slot_mask.map_mode != 'STENCIL':
+ if brush.use_secondary_overlay:
+ row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
+ else:
+ row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
+
+ sub = row.row(align=True)
+ sub.prop(brush, "mask_overlay_alpha", text="Alpha")
+ sub.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
+
+
+class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
+ bl_label = "Texture"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ toolsettings = context.tool_settings.image_paint
+ brush = toolsettings.brush
+ tex_slot = brush.texture_slot
+
+ col = layout.column()
+ col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
+
+ brush_texture_settings(col, brush, 0)
+
class IMAGE_PT_tools_mask_texture(BrushButtonsPanel, Panel):
bl_label = "Texture Mask"
@@ -764,21 +801,6 @@ class IMAGE_PT_tools_mask_texture(BrushButtonsPanel, Panel):
brush_mask_texture_settings(col, brush)
- col = layout.column(align=True)
- col.active = brush.brush_capabilities.has_overlay
- col.label(text="Overlay:")
-
- row = col.row(align=True)
- if tex_slot_alpha.map_mode != 'STENCIL':
- if brush.use_secondary_overlay:
- row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
- else:
- row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
-
- sub = row.row(align=True)
- sub.prop(brush, "mask_overlay_alpha", text="Alpha")
- sub.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
-
class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, Panel):
bl_label = "Tool"
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 843bafabdec..1721eacd8ac 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -407,13 +407,13 @@ class NODE_UL_interface_sockets(bpy.types.UIList):
row = layout.row(align=True)
# inputs get icon on the left
- if socket.in_out == 'IN':
+ if not socket.is_output:
row.template_node_socket(color)
row.label(text=socket.name, icon_value=icon)
# outputs get icon on the right
- if socket.in_out == 'OUT':
+ if socket.is_output:
row.template_node_socket(color)
elif self.layout_type in {'GRID'}:
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 7137a5097ee..ea88d35b4e9 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -685,10 +685,15 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
layout.prop(strip, "pan")
col = layout.column(align=True)
- col.label(text="Trim Duration:")
+ col.label(text="Trim Duration (hard):")
col.prop(strip, "animation_offset_start", text="Start")
col.prop(strip, "animation_offset_end", text="End")
+ col = layout.column(align=True)
+ col.label(text="Trim Duration (soft):")
+ col.prop(strip, "frame_offset_start", text="Start")
+ col.prop(strip, "frame_offset_end", text="End")
+
class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
bl_label = "Scene"
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index d01df810307..0bb31f51c1b 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -673,19 +673,6 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
col.prop(brush, "use_persistent")
col.operator("sculpt.set_persistent_base")
- col = layout.column(align=True)
- col.label(text="Overlay:")
-
- row = col.row(align=True)
- if brush.use_cursor_overlay:
- row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
- else:
- row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
-
- sub = row.row(align=True)
- sub.prop(brush, "cursor_overlay_alpha", text="Alpha")
- sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
-
# Texture Paint Mode #
elif context.image_paint_object and brush:
@@ -709,19 +696,6 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
col.active = (brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'})
col.prop(brush, "use_alpha")
- col = layout.column(align=True)
- col.label(text="Overlay:")
-
- row = col.row(align=True)
- if brush.use_cursor_overlay:
- row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
- else:
- row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
-
- sub = row.row(align=True)
- sub.prop(brush, "cursor_overlay_alpha", text="Alpha")
- sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
-
# Weight Paint Mode #
elif context.weight_paint_object and brush:
@@ -765,18 +739,71 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
col.prop(brush, "vertex_tool", text="Blend")
- col = layout.column(align=True)
- col.label(text="Overlay:")
+class VIEW3D_PT_tools_brush_overlay(Panel, View3DPaintPanel):
+ bl_label = "Overlay"
+ bl_options = {'DEFAULT_CLOSED'}
+ @classmethod
+ def poll(cls, context):
+ settings = cls.paint_settings(context)
+ return (settings and
+ settings.brush and
+ (context.sculpt_object or
+ context.vertex_paint_object or
+ context.weight_paint_object or
+ context.image_paint_object))
+
+
+ def draw(self, context):
+ layout = self.layout
+
+ settings = self.paint_settings(context)
+ brush = settings.brush
+ tex_slot = brush.texture_slot
+ tex_slot_mask = brush.mask_texture_slot
+
+ col = layout.column()
+
+ col.label(text="Curve:")
+
+ row = col.row(align=True)
+ if brush.use_cursor_overlay:
+ row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
+ else:
+ row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
+
+ sub = row.row(align=True)
+ sub.prop(brush, "cursor_overlay_alpha", text="Alpha")
+ sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
+
+ col.active = brush.brush_capabilities.has_overlay
+
+ if context.image_paint_object or context.sculpt_object or context.vertex_paint_object:
+ col.label(text="Texture:")
row = col.row(align=True)
- if brush.use_cursor_overlay:
- row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
- else:
- row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
+ if tex_slot.map_mode != 'STENCIL':
+ if brush.use_primary_overlay:
+ row.prop(brush, "use_primary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
+ else:
+ row.prop(brush, "use_primary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
+
+ sub = row.row(align=True)
+ sub.prop(brush, "texture_overlay_alpha", text="Alpha")
+ sub.prop(brush, "use_primary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
+
+ if context.image_paint_object:
+ col.label(text="Mask Texture:")
+
+ row = col.row(align=True)
+ if tex_slot_mask.map_mode != 'STENCIL':
+ if brush.use_secondary_overlay:
+ row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
+ else:
+ row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
sub = row.row(align=True)
- sub.prop(brush, "cursor_overlay_alpha", text="Alpha")
- sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
+ sub.prop(brush, "mask_overlay_alpha", text="Alpha")
+ sub.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
@@ -802,22 +829,6 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
brush_texture_settings(col, brush, context.sculpt_object)
- # use_texture_overlay and texture_overlay_alpha
- col = layout.column(align=True)
- col.active = brush.brush_capabilities.has_overlay
- col.label(text="Overlay:")
-
- row = col.row(align=True)
- if tex_slot.map_mode != 'STENCIL':
- if brush.use_primary_overlay:
- row.prop(brush, "use_primary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
- else:
- row.prop(brush, "use_primary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
-
- sub = row.row(align=True)
- sub.prop(brush, "texture_overlay_alpha", text="Alpha")
- sub.prop(brush, "use_primary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
-
class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel):
bl_context = "imagepaint"
@@ -841,21 +852,6 @@ class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel):
brush_mask_texture_settings(col, brush)
- col = layout.column(align=True)
- col.active = brush.brush_capabilities.has_overlay
- col.label(text="Overlay:")
-
- row = col.row(align=True)
- if tex_slot_alpha.map_mode != 'STENCIL':
- if brush.use_secondary_overlay:
- row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
- else:
- row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
-
- sub = row.row(align=True)
- sub.prop(brush, "mask_overlay_alpha", text="Alpha")
- sub.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
-
class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
bl_label = "Stroke"
diff --git a/release/scripts/templates_py/custom_nodes.py b/release/scripts/templates_py/custom_nodes.py
index 5f002f37161..975ae1881f2 100644
--- a/release/scripts/templates_py/custom_nodes.py
+++ b/release/scripts/templates_py/custom_nodes.py
@@ -40,7 +40,7 @@ class MyCustomSocket(NodeSocket):
# Optional function for drawing the socket input value
def draw(self, context, layout, node, text):
- if self.is_linked:
+ if self.is_output or self.is_linked:
layout.label(text)
else:
layout.prop(self, "myEnumProperty", text=text)
diff --git a/release/scripts/templates_py/ui_list.py b/release/scripts/templates_py/ui_list.py
index 61ad0ae0435..92e1b29d2ae 100644
--- a/release/scripts/templates_py/ui_list.py
+++ b/release/scripts/templates_py/ui_list.py
@@ -1,7 +1,7 @@
import bpy
-class MESH_UL_mylist(UIList):
+class MESH_UL_mylist(bpy.types.UIList):
# Constants (flags)
# Be careful not to shadow FILTER_ITEM (i.e. UIList().bitflag_filter_item)!
# E.g. VGROUP_EMPTY = 1 << 0
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 7e327028a01..0d309523daf 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -117,6 +117,10 @@ if(WITH_IMAGE_OPENEXR)
add_subdirectory(imbuf/intern/openexr)
endif()
+if(WITH_OPENIMAGEIO)
+ add_subdirectory(imbuf/intern/oiio)
+endif()
+
if(WITH_IMAGE_DDS)
add_subdirectory(imbuf/intern/dds)
endif()
diff --git a/source/blender/SConscript b/source/blender/SConscript
index 66d54961131..de052f24c33 100644
--- a/source/blender/SConscript
+++ b/source/blender/SConscript
@@ -49,6 +49,9 @@ makesrna = SConscript('makesrna/SConscript')
if env['WITH_BF_PYTHON']:
SConscript(['python/SConscript'])
+if env['WITH_BF_OIIO']:
+ SConscript (['imbuf/intern/oiio/SConscript'])
+
if env['WITH_BF_DDS']:
SConscript (['imbuf/intern/dds/SConscript'])
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index d485632955d..698098d28c3 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -188,6 +188,10 @@ struct bPoseChannel *BKE_pose_channel_active(struct Object *ob);
*/
struct bPoseChannel *BKE_pose_channel_verify(struct bPose *pose, const char *name);
+#ifndef NDEBUG
+bool BKE_pose_channels_is_valid(const struct bPose *pose);
+#endif
+
/* Copy the data from the action-pose (src) into the pose */
void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index dd150ba6a63..f0f6b5a2319 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -112,6 +112,9 @@ void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, st
/* Fix all the paths for the entire database... */
void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const char *oldName, const char *newName);
+/* Fix the path after removing elements that are not ID (e.g., node) */
+void BKE_animdata_fix_paths_remove(struct ID *id, const char *path);
+
/* -------------------------------------- */
/* Move animation data from src to destination if it's paths are based on basepaths */
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index f434bcf3cad..5b32e7229d5 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -41,15 +41,15 @@ extern "C" {
/* these lines are grep'd, watch out for our not-so-awesome regex
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
-#define BLENDER_VERSION 268
-#define BLENDER_SUBVERSION 5
+#define BLENDER_VERSION 269
+#define BLENDER_SUBVERSION 1
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 262
#define BLENDER_MINSUBVERSION 0
/* used by packaging tools */
/* can be left blank, otherwise a,b,c... etc with no quotes */
-#define BLENDER_VERSION_CHAR a
+#define BLENDER_VERSION_CHAR
/* alpha/beta/rc/release, docs use this */
#define BLENDER_VERSION_CYCLE alpha
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index ac114a62de6..07116979eab 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -155,6 +155,7 @@ void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt);
void BKE_nurb_handles_calc(struct Nurb *nu);
void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag);
-void BKE_nurb_handles_test(struct Nurb *nu);
+void BKE_nurb_bezt_handle_test(struct BezTriple *bezt, const bool use_handle);
+void BKE_nurb_handles_test(struct Nurb *nu, const bool use_handles);
#endif /* __BKE_CURVE_H__ */
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index a43a243106d..435cad17e57 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -78,8 +78,12 @@ void defvert_flip_merged(struct MDeformVert *dvert, const int *flip_map, const i
void defvert_normalize(struct MDeformVert *dvert);
void defvert_normalize_subset(struct MDeformVert *dvert,
const bool *vgroup_subset, const int vgroup_tot);
-void defvert_normalize_lock_single(struct MDeformVert *dvert, const int def_nr_lock);
-void defvert_normalize_lock_map(struct MDeformVert *dvert, const bool *lock_flags, const int defbase_tot);
+void defvert_normalize_lock_single(struct MDeformVert *dvert,
+ const bool *vgroup_subset, const int vgroup_tot,
+ const int def_nr_lock);
+void defvert_normalize_lock_map(struct MDeformVert *dvert,
+ const bool *vgroup_subset, const int vgroup_tot,
+ const bool *lock_flags, const int defbase_tot);
/* utility function, note that MAX_VGROUP_NAME chars is the maximum string length since its only
* used with defgroups currently */
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 64a6811bf51..c31dd745911 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -229,12 +229,13 @@ short calc_fcurve_bounds(struct FCurve *fcu, float *xmin, float *xmax, float *ym
short fcurve_are_keyframes_usable(struct FCurve *fcu);
/* Can keyframes be added to F-Curve? */
-short fcurve_is_keyframable(struct FCurve *fcu);
+bool fcurve_is_keyframable(struct FCurve *fcu);
+bool BKE_fcurve_is_protected(struct FCurve *fcu);
/* -------- Curve Sanity -------- */
void calchandles_fcurve(struct FCurve *fcu);
-void testhandles_fcurve(struct FCurve *fcu, const short use_handle);
+void testhandles_fcurve(struct FCurve *fcu, const bool use_handle);
void sort_time_fcurve(struct FCurve *fcu);
short test_time_fcurve(struct FCurve *fcu);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 9e80a93fd63..a3d1eb74211 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -169,9 +169,9 @@ void BKE_mesh_calc_normals_tessface(
struct MFace *mfaces, int numFaces,
float (*faceNors_r)[3]);
void BKE_mesh_normals_loop_split(
- struct MVert *mverts, int numVerts, struct MEdge *medges, int numEdges,
- struct MLoop *mloops, float (*r_loopnors)[3], int numLoops,
- struct MPoly *mpolys, float (*polynors)[3], int numPolys, float split_angle);
+ struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges,
+ struct MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
+ struct MPoly *mpolys, float (*polynors)[3], const int numPolys, float split_angle);
void BKE_mesh_calc_poly_normal(
struct MPoly *mpoly, struct MLoop *loopstart,
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 7f19a867093..7cc8c7290f7 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -131,8 +131,6 @@ typedef struct bNodeSocketType {
int type, subtype;
} bNodeSocketType;
-typedef void (*NodeSocketDrawFunction)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr);
-
typedef void *(*NodeInitExecFunction)(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key);
typedef void (*NodeFreeExecFunction)(struct bNode *node, void *nodedata);
typedef void (*NodeExecFunction)(void *data, int thread, struct bNode *, struct bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out);
@@ -162,24 +160,19 @@ typedef struct bNodeType {
char storagename[64]; /* struct name for DNA */
- /// Main draw function for the node.
- void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
+ /* Main draw function for the node */
+ void (*draw_nodetype)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
- /// Updates the node geometry attributes according to internal state before actual drawing.
- void (*drawupdatefunc)(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
- /// Draw the option buttons on the node.
- void (*uifunc)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
- /// Additional parameters in the side panel.
- void (*uifuncbut)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
- /// Additional drawing on backdrop.
- void (*uibackdropfunc)(struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y);
-
- /// Draw a node socket. Default draws the input value button.
- /* XXX deprecated, only used for the OutputFile node,
- * should be removed at some point.
- */
- NodeSocketDrawFunction drawinputfunc;
- NodeSocketDrawFunction drawoutputfunc;
+ /* Updates the node geometry attributes according to internal state before actual drawing */
+ void (*draw_nodetype_prepare)(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
+
+ /* Draw the option buttons on the node */
+ void (*draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
+ /* Additional parameters in the side panel */
+ void (*draw_buttons_ex)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
+
+ /* Additional drawing on backdrop */
+ void (*draw_backdrop)(struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y);
/// Optional custom label function for the node header.
const char *(*labelfunc)(struct bNode *);
diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h
index 653f2a42675..ab8b8b29915 100644
--- a/source/blender/blenkernel/BKE_subsurf.h
+++ b/source/blender/blenkernel/BKE_subsurf.h
@@ -72,11 +72,11 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
void subsurf_calculate_limit_positions(struct Mesh *me, float (*positions_r)[3]);
/* get gridsize from 'level', level must be greater than zero */
-int ccg_gridsize(int level);
+int BKE_ccg_gridsize(int level);
/* x/y grid coordinates at 'low_level' can be multiplied by the result
* of this function to convert to grid coordinates at 'high_level' */
-int ccg_factor(int low_level, int high_level);
+int BKE_ccg_factor(int low_level, int high_level);
void subsurf_copy_grid_hidden(struct DerivedMesh *dm,
const struct MPoly *mpoly,
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 3c3ac61a3cb..07dbc1d6065 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -101,6 +101,9 @@ if env['WITH_BF_SDL']:
incs += ' ' + env['BF_SDL_INC']
defs.append('WITH_SDL')
+if env['WITH_BF_OIIO']:
+ defs.append('WITH_OPENIMAGEIO')
+
if env['WITH_BF_OPENEXR']:
defs.append('WITH_OPENEXR')
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index d4454a95a2d..ffb92788d4d 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -248,7 +248,7 @@ static CCGAllocatorIFC *_getStandardAllocatorIFC(void)
/***/
-int ccg_gridsize(int level)
+BLI_INLINE int ccg_gridsize(int level)
{
BLI_assert(level > 0);
BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
@@ -256,7 +256,12 @@ int ccg_gridsize(int level)
return (1 << (level - 1)) + 1;
}
-int ccg_factor(int low_level, int high_level)
+int BKE_ccg_gridsize(int level)
+{
+ return ccg_gridsize(level);
+}
+
+int BKE_ccg_factor(int low_level, int high_level)
{
BLI_assert(low_level > 0 && high_level > 0);
BLI_assert(low_level <= high_level);
@@ -264,7 +269,7 @@ int ccg_factor(int low_level, int high_level)
return 1 << (high_level - low_level);
}
-static int ccg_edgesize(int level)
+BLI_INLINE int ccg_edgesize(int level)
{
BLI_assert(level > 0);
BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
@@ -272,7 +277,7 @@ static int ccg_edgesize(int level)
return 1 + (1 << level);
}
-static int ccg_spacing(int high_level, int low_level)
+BLI_INLINE int ccg_spacing(int high_level, int low_level)
{
BLI_assert(high_level > 0 && low_level > 0);
BLI_assert(high_level >= low_level);
@@ -281,7 +286,7 @@ static int ccg_spacing(int high_level, int low_level)
return 1 << (high_level - low_level);
}
-static int ccg_edgebase(int level)
+BLI_INLINE int ccg_edgebase(int level)
{
BLI_assert(level > 0);
BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
@@ -742,7 +747,7 @@ BLI_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int le
byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
return (float *) &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing) + normalDataOffset];
}
-static int _face_getVertIndex(CCGFace *f, CCGVert *v)
+BLI_INLINE int _face_getVertIndex(CCGFace *f, CCGVert *v)
{
int i;
for (i = 0; i < f->numVerts; i++)
@@ -750,7 +755,7 @@ static int _face_getVertIndex(CCGFace *f, CCGVert *v)
return i;
return -1;
}
-static int _face_getEdgeIndex(CCGFace *f, CCGEdge *e)
+BLI_INLINE int _face_getEdgeIndex(CCGFace *f, CCGEdge *e)
{
int i;
for (i = 0; i < f->numVerts; i++)
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 644fefad3b0..b0644da4598 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -489,6 +489,22 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name)
return chan;
}
+#ifndef NDEBUG
+bool BKE_pose_channels_is_valid(const bPose *pose)
+{
+ if (pose->chanhash) {
+ bPoseChannel *pchan;
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (BLI_ghash_lookup(pose->chanhash, pchan->name) != pchan) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+#endif
/* Find the active posechannel for an object (we can't just use pose, as layer info is in armature) */
bPoseChannel *BKE_pose_channel_active(Object *ob)
{
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 5c3f67d8959..225be335c6d 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -530,7 +530,7 @@ void calc_curvepath(Object *ob, ListBase *nurbs)
path->len = nu->resolu * SEGMENTSU(nu);
}
- dist = (float *)MEM_mallocN((tot + 1) * 4, "calcpathdist");
+ dist = (float *)MEM_mallocN(sizeof(float) * (tot + 1), "calcpathdist");
/* all lengths in *dist */
bevp = bevpfirst = (BevPoint *)(bl + 1);
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 8e697ad4ef3..74578266c63 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -42,6 +42,7 @@
#include "BLI_blenlib.h"
#include "BLI_alloca.h"
#include "BLI_dynstr.h"
+#include "BLI_listbase.h"
#include "BLF_translation.h"
@@ -759,6 +760,76 @@ void BKE_animdata_fix_paths_rename(ID *owner_id, AnimData *adt, ID *ref_id, cons
MEM_freeN(newN);
}
+/* *************************** */
+/* remove of individual paths */
+
+/* Check RNA-Paths for a list of F-Curves */
+static void fcurves_path_remove_fix(const char *prefix, ListBase *curves)
+{
+ FCurve *fcu, *fcn;
+ if (!prefix) return;
+
+ /* we need to check every curve... */
+ for (fcu = curves->first; fcu; fcu = fcn) {
+ fcn = fcu->next;
+
+ if (fcu->rna_path) {
+ if (STRPREFIX(fcu->rna_path, prefix)) {
+ BLI_remlink(curves, fcu);
+ free_fcurve(fcu);
+ }
+ }
+ }
+}
+
+/* Check RNA-Paths for a list of F-Curves */
+static void nlastrips_path_remove_fix(const char *prefix, ListBase *strips)
+{
+ NlaStrip *strip;
+
+ /* recursively check strips, fixing only actions... */
+ for (strip = strips->first; strip; strip = strip->next) {
+
+ /* fix strip's action */
+ if (strip->act)
+ fcurves_path_remove_fix(prefix, &strip->act->curves);
+
+ /* check sub-strips (if metas) */
+ nlastrips_path_remove_fix(prefix, &strip->strips);
+ }
+}
+
+void BKE_animdata_fix_paths_remove(ID *id, const char *prefix)
+{
+ /* Only some ID-blocks have this info for now, so we cast the
+ * types that do to be of type IdAdtTemplate
+ */
+ NlaTrack *nlt;
+
+ if (id_type_can_have_animdata(id)) {
+ IdAdtTemplate *iat = (IdAdtTemplate *)id;
+ AnimData *adt = iat->adt;
+
+ /* check if there's any AnimData to start with */
+ if (adt) {
+
+ /* free fcurves */
+ if (adt->action)
+ fcurves_path_remove_fix(prefix, &adt->action->curves);
+
+ if (adt->tmpact)
+ fcurves_path_remove_fix(prefix, &adt->tmpact->curves);
+
+ /* free drivers - stored as a list of F-Curves */
+ fcurves_path_remove_fix(prefix, &adt->drivers);
+
+ /* NLA Data - Animation Data for Strips */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next)
+ nlastrips_path_remove_fix(prefix, &nlt->strips);
+ }
+ }
+}
+
/* Whole Database Ops -------------------------------------------- */
/* apply the given callback function on all data in main database */
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 5b66b8b4cd4..370dbc62ef8 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -355,7 +355,7 @@ float nearest_point_in_tri_surface(const float v0[3], const float v1[3], const f
/*
- * BVH from meshs callbacks
+ * BVH from meshes callbacks
*/
/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 7f94f365925..578fa5d348d 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -972,9 +972,6 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM
if (ibuf->rect_float)
cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
- /* persistent draw */
- hist->flag |= HISTO_FLAG_SAMPLELINE; /* keep drawing the flag after */
-
for (i = 0; i < 256; i++) {
x = (int)(0.5f + x1 + (float)i * (x2 - x1) / 255.0f);
y = (int)(0.5f + y1 + (float)i * (y2 - y1) / 255.0f);
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 02b35794d28..e255732d3fb 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -3102,46 +3102,67 @@ void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt)
}
}
-void BKE_nurb_handles_test(Nurb *nu)
-{
- /* use when something has changed with handles.
- * it treats all BezTriples with the following rules:
- * PHASE 1: do types have to be altered?
- * Auto handles: become aligned when selection status is NOT(000 || 111)
- * Vector handles: become 'nothing' when (one half selected AND other not)
- * PHASE 2: recalculate handles
- */
- BezTriple *bezt;
- short flag, a;
+/**
+ * Use when something has changed handle positions.
+ *
+ * The caller needs to recalculate handles.
+ */
+void BKE_nurb_bezt_handle_test(BezTriple *bezt, const bool use_handle)
+{
+ short flag = 0;
- if (nu->type != CU_BEZIER) return;
+#define SEL_F1 (1 << 0)
+#define SEL_F2 (1 << 1)
+#define SEL_F3 (1 << 2)
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- flag = 0;
- if (bezt->f1 & SELECT)
- flag++;
- if (bezt->f2 & SELECT)
- flag += 2;
- if (bezt->f3 & SELECT)
- flag += 4;
+ if (use_handle) {
+ if (bezt->f1 & SELECT) flag |= SEL_F1;
+ if (bezt->f2 & SELECT) flag |= SEL_F2;
+ if (bezt->f3 & SELECT) flag |= SEL_F3;
+ }
+ else {
+ flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
+ }
- if (!(flag == 0 || flag == 7) ) {
- if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) { /* auto */
- bezt->h1 = HD_ALIGN;
- }
- if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { /* auto */
- bezt->h2 = HD_ALIGN;
- }
+ /* check for partial selection */
+ if (!ELEM(flag, 0, SEL_F1 | SEL_F2 | SEL_F3)) {
+ if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) {
+ bezt->h1 = HD_ALIGN;
+ }
+ if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) {
+ bezt->h2 = HD_ALIGN;
+ }
- if (bezt->h1 == HD_VECT) { /* vector */
- if (flag < 4) bezt->h1 = 0;
+ if (bezt->h1 == HD_VECT) {
+ if ((!(flag & SEL_F1)) != (!(flag & SEL_F2))) {
+ bezt->h1 = HD_FREE;
}
- if (bezt->h2 == HD_VECT) { /* vector */
- if (flag > 3) bezt->h2 = 0;
+ }
+ if (bezt->h2 == HD_VECT) {
+ if ((!(flag & SEL_F3)) != (!(flag & SEL_F2))) {
+ bezt->h2 = HD_FREE;
}
}
+ }
+
+#undef SEL_F1
+#undef SEL_F2
+#undef SEL_F3
+
+}
+
+void BKE_nurb_handles_test(Nurb *nu, const bool use_handle)
+{
+ BezTriple *bezt;
+ short a;
+
+ if (nu->type != CU_BEZIER)
+ return;
+
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ BKE_nurb_bezt_handle_test(bezt, use_handle);
bezt++;
}
@@ -3151,9 +3172,11 @@ void BKE_nurb_handles_test(Nurb *nu)
void BKE_nurb_handles_autocalc(Nurb *nu, int flag)
{
/* checks handle coordinates and calculates type */
+ const float eps = 0.0001f;
+ const float eps_sq = eps * eps;
BezTriple *bezt2, *bezt1, *bezt0;
- int i, align, leftsmall, rightsmall;
+ int i;
if (nu == NULL || nu->bezt == NULL)
return;
@@ -3164,54 +3187,54 @@ void BKE_nurb_handles_autocalc(Nurb *nu, int flag)
i = nu->pntsu;
while (i--) {
- align = leftsmall = rightsmall = 0;
+ bool align = false, leftsmall = false, rightsmall = false;
/* left handle: */
if (flag == 0 || (bezt1->f1 & flag) ) {
- bezt1->h1 = 0;
+ bezt1->h1 = HD_FREE;
/* distance too short: vectorhandle */
- if (len_v3v3(bezt1->vec[1], bezt0->vec[1]) < 0.0001f) {
+ if (len_squared_v3v3(bezt1->vec[1], bezt0->vec[1]) < eps_sq) {
bezt1->h1 = HD_VECT;
- leftsmall = 1;
+ leftsmall = true;
}
else {
/* aligned handle? */
- if (dist_to_line_v2(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < 0.0001f) {
- align = 1;
+ if (dist_to_line_v2(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < eps) {
+ align = true;
bezt1->h1 = HD_ALIGN;
}
/* or vector handle? */
- if (dist_to_line_v2(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < 0.0001f)
+ if (dist_to_line_v2(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < eps)
bezt1->h1 = HD_VECT;
}
}
/* right handle: */
if (flag == 0 || (bezt1->f3 & flag) ) {
- bezt1->h2 = 0;
+ bezt1->h2 = HD_FREE;
/* distance too short: vectorhandle */
- if (len_v3v3(bezt1->vec[1], bezt2->vec[1]) < 0.0001f) {
+ if (len_squared_v3v3(bezt1->vec[1], bezt2->vec[1]) < eps_sq) {
bezt1->h2 = HD_VECT;
- rightsmall = 1;
+ rightsmall = true;
}
else {
/* aligned handle? */
if (align) bezt1->h2 = HD_ALIGN;
/* or vector handle? */
- if (dist_to_line_v2(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < 0.0001f)
+ if (dist_to_line_v2(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < eps)
bezt1->h2 = HD_VECT;
}
}
if (leftsmall && bezt1->h2 == HD_ALIGN)
- bezt1->h2 = 0;
+ bezt1->h2 = HD_FREE;
if (rightsmall && bezt1->h1 == HD_ALIGN)
- bezt1->h1 = 0;
+ bezt1->h1 = HD_FREE;
/* undesired combination: */
if (bezt1->h1 == HD_ALIGN && bezt1->h2 == HD_VECT)
- bezt1->h1 = 0;
+ bezt1->h1 = HD_FREE;
if (bezt1->h2 == HD_ALIGN && bezt1->h1 == HD_VECT)
- bezt1->h2 = 0;
+ bezt1->h2 = HD_FREE;
bezt0 = bezt1;
bezt1 = bezt2;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 1521ec8467e..8a74f4719d5 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -1463,8 +1463,7 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, const cha
for (i = 0; i < data->totlayer; ++i)
if (data->layers[i].type == type)
- if ((!name && !data->layers[i].name) ||
- (strcmp(data->layers[i].name, name) == 0))
+ if (strcmp(data->layers[i].name, name) == 0)
return i;
return -1;
@@ -1970,10 +1969,10 @@ static void CustomData_copy_data_layer(const CustomData *source, CustomData *des
dest_offset = dest_index * typeInfo->size;
if (!src_data || !dest_data) {
- if (src_data != NULL && dest_data != NULL) {
+ if (!(src_data == NULL && dest_data == NULL)) {
printf("%s: warning null data for %s type (%p --> %p), skipping\n",
- __func__, layerType_getName(source->layers[src_i].type),
- (void *)src_data, (void *)dest_data);
+ __func__, layerType_getName(source->layers[src_i].type),
+ (void *)src_data, (void *)dest_data);
}
return;
}
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 882085aa5db..a183872552d 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -217,24 +217,35 @@ void defvert_remap(MDeformVert *dvert, int *map, const int map_len)
void defvert_normalize_subset(MDeformVert *dvert,
const bool *vgroup_subset, const int vgroup_tot)
{
- MDeformWeight *dw;
- unsigned int i;
- float tot_weight = 0.0f;
-
- for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if (dvert->totweight == 0) {
+ /* nothing */
+ }
+ else if (dvert->totweight == 1) {
+ MDeformWeight *dw = dvert->dw;
if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
- tot_weight += dw->weight;
+ dw->weight = 1.0f;
}
}
+ else {
+ MDeformWeight *dw;
+ unsigned int i;
+ float tot_weight = 0.0f;
- if (tot_weight > 0.0f) {
- float scalar = 1.0f / tot_weight;
for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
- dw->weight *= scalar;
-
- /* in case of division errors with very low weights */
- CLAMP(dw->weight, 0.0f, 1.0f);
+ tot_weight += dw->weight;
+ }
+ }
+
+ if (tot_weight > 0.0f) {
+ float scalar = 1.0f / tot_weight;
+ for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+ if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
+ dw->weight *= scalar;
+
+ /* in case of division errors with very low weights */
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
}
}
}
@@ -242,7 +253,7 @@ void defvert_normalize_subset(MDeformVert *dvert,
void defvert_normalize(MDeformVert *dvert)
{
- if (dvert->totweight <= 0) {
+ if (dvert->totweight == 0) {
/* nothing */
}
else if (dvert->totweight == 1) {
@@ -269,14 +280,20 @@ void defvert_normalize(MDeformVert *dvert)
}
}
-void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock)
+/* Same as defvert_normalize() if the locked vgroup is not a member of the subset */
+void defvert_normalize_lock_single(MDeformVert *dvert,
+ const bool *vgroup_subset, const int vgroup_tot,
+ const int def_nr_lock)
{
- if (dvert->totweight <= 0) {
+ if (dvert->totweight == 0) {
/* nothing */
}
else if (dvert->totweight == 1) {
- if (def_nr_lock != 0) {
- dvert->dw[0].weight = 1.0f;
+ MDeformWeight *dw = dvert->dw;
+ if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
+ if (def_nr_lock != 0) {
+ dw->weight = 1.0f;
+ }
}
}
else {
@@ -287,13 +304,15 @@ void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock)
float lock_iweight = 1.0f;
for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw->def_nr != def_nr_lock) {
- tot_weight += dw->weight;
- }
- else {
- dw_lock = dw;
- lock_iweight = (1.0f - dw_lock->weight);
- CLAMP(lock_iweight, 0.0f, 1.0f);
+ if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
+ if (dw->def_nr != def_nr_lock) {
+ tot_weight += dw->weight;
+ }
+ else {
+ dw_lock = dw;
+ lock_iweight = (1.0f - dw_lock->weight);
+ CLAMP(lock_iweight, 0.0f, 1.0f);
+ }
}
}
@@ -302,25 +321,33 @@ void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock)
float scalar = (1.0f / tot_weight) * lock_iweight;
for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if (dw != dw_lock) {
- dw->weight *= scalar;
+ if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
+ if (dw != dw_lock) {
+ dw->weight *= scalar;
- /* in case of division errors with very low weights */
- CLAMP(dw->weight, 0.0f, 1.0f);
+ /* in case of division errors with very low weights */
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
}
}
}
}
}
-void defvert_normalize_lock_map(MDeformVert *dvert, const bool *lock_flags, const int defbase_tot)
+/* Same as defvert_normalize() if no locked vgroup is a member of the subset */
+void defvert_normalize_lock_map(MDeformVert *dvert,
+ const bool *vgroup_subset, const int vgroup_tot,
+ const bool *lock_flags, const int defbase_tot)
{
- if (dvert->totweight <= 0) {
+ if (dvert->totweight == 0) {
/* nothing */
}
else if (dvert->totweight == 1) {
- if (LIKELY(defbase_tot >= 1) && lock_flags[0]) {
- dvert->dw[0].weight = 1.0f;
+ MDeformWeight *dw = dvert->dw;
+ if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
+ if (LIKELY(defbase_tot >= 1) && lock_flags[0]) {
+ dw->weight = 1.0f;
+ }
}
}
else {
@@ -330,12 +357,14 @@ void defvert_normalize_lock_map(MDeformVert *dvert, const bool *lock_flags, cons
float lock_iweight = 0.0f;
for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) {
- tot_weight += dw->weight;
- }
- else {
- /* invert after */
- lock_iweight += dw->weight;
+ if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
+ if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) {
+ tot_weight += dw->weight;
+ }
+ else {
+ /* invert after */
+ lock_iweight += dw->weight;
+ }
}
}
@@ -346,11 +375,13 @@ void defvert_normalize_lock_map(MDeformVert *dvert, const bool *lock_flags, cons
float scalar = (1.0f / tot_weight) * lock_iweight;
for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
- if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) {
- dw->weight *= scalar;
+ if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
+ if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) {
+ dw->weight *= scalar;
- /* in case of division errors with very low weights */
- CLAMP(dw->weight, 0.0f, 1.0f);
+ /* in case of division errors with very low weights */
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
}
}
}
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 580172bcccd..fe9a96d60cf 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -98,12 +98,13 @@
#endif
/* precalculated gaussian factors for 5x super sampling */
-static float gaussianFactors[5] = {0.996849f,
- 0.596145f,
- 0.596145f,
- 0.596145f,
- 0.524141f};
-static float gaussianTotal = 3.309425f;
+static const float gaussianFactors[5] = {
+ 0.996849f,
+ 0.596145f,
+ 0.596145f,
+ 0.596145f,
+ 0.524141f};
+static const float gaussianTotal = 3.309425f;
/* UV Image neighboring pixel table x and y list */
static int neighX[8] = {1, 1, 0, -1, -1, -1, 0, 1};
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 791c47cc551..dbdf30ea63d 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -688,21 +688,27 @@ short fcurve_are_keyframes_usable(FCurve *fcu)
return 1;
}
+bool BKE_fcurve_is_protected(FCurve *fcu)
+{
+ return ((fcu->flag & FCURVE_PROTECTED) ||
+ ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)));
+}
+
/* Can keyframes be added to F-Curve?
* Keyframes can only be added if they are already visible
*/
-short fcurve_is_keyframable(FCurve *fcu)
+bool fcurve_is_keyframable(FCurve *fcu)
{
/* F-Curve's keyframes must be "usable" (i.e. visible + have an effect on final result) */
if (fcurve_are_keyframes_usable(fcu) == 0)
- return 0;
+ return false;
/* F-Curve must currently be editable too */
- if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) )
- return 0;
+ if (BKE_fcurve_is_protected(fcu))
+ return false;
/* F-Curve is keyframable */
- return 1;
+ return true;
}
/* ***************************** Keyframe Column Tools ********************************* */
@@ -841,14 +847,7 @@ void calchandles_fcurve(FCurve *fcu)
}
}
-/* Use when F-Curve with handles has changed
- * It treats all BezTriples with the following rules:
- * - PHASE 1: do types have to be altered?
- * -> Auto handles: become aligned when selection status is NOT(000 || 111)
- * -> Vector handles: become 'nothing' when (one half selected AND other not)
- * - PHASE 2: recalculate handles
- */
-void testhandles_fcurve(FCurve *fcu, const short use_handle)
+void testhandles_fcurve(FCurve *fcu, const bool use_handle)
{
BezTriple *bezt;
unsigned int a;
@@ -856,45 +855,10 @@ void testhandles_fcurve(FCurve *fcu, const short use_handle)
/* only beztriples have handles (bpoints don't though) */
if (ELEM(NULL, fcu, fcu->bezt))
return;
-
+
/* loop over beztriples */
for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) {
- short flag = 0;
-
- /* flag is initialized as selection status
- * of beztriple control-points (labelled 0, 1, 2)
- */
- if (bezt->f2 & SELECT) flag |= (1 << 1); // == 2
- if (use_handle == FALSE) {
- if (flag & 2) {
- flag |= (1 << 0) | (1 << 2);
- }
- }
- else {
- if (bezt->f1 & SELECT) flag |= (1 << 0); // == 1
- if (bezt->f3 & SELECT) flag |= (1 << 2); // == 4
- }
-
- /* one or two handles selected only */
- if (ELEM(flag, 0, 7) == 0) {
- /* auto handles become aligned */
- if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM))
- bezt->h1 = HD_ALIGN;
- if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM))
- bezt->h2 = HD_ALIGN;
-
- /* vector handles become 'free' when only one half selected */
- if (bezt->h1 == HD_VECT) {
- /* only left half (1 or 2 or 1+2) */
- if (flag < 4)
- bezt->h1 = 0;
- }
- if (bezt->h2 == HD_VECT) {
- /* only right half (4 or 2+4) */
- if (flag > 3)
- bezt->h2 = 0;
- }
- }
+ BKE_nurb_bezt_handle_test(bezt, use_handle);
}
/* recalculate handles */
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index 1f106ff90a7..d87c93310c8 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -107,7 +107,8 @@ void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *con
static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset)
{
new_lineset->linestyle = lineset->linestyle;
- new_lineset->linestyle->id.us++;
+ if (new_lineset->linestyle)
+ new_lineset->linestyle->id.us++;
new_lineset->flags = lineset->flags;
new_lineset->selection = lineset->selection;
new_lineset->qi = lineset->qi;
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 2e32c18b264..6f275e4ec75 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -56,7 +56,13 @@ static char idp_size_table[] = {
sizeof(double)
};
-/* ------------Property Array Type ----------- */
+
+/* -------------------------------------------------------------------- */
+/* Array Functions */
+
+/** \name IDP Array API
+ * \{ */
+
#define GETPROP(prop, i) (((IDProperty *)(prop)->data.pointer) + (i))
/* --------- property array type -------------*/
@@ -78,9 +84,12 @@ IDProperty *IDP_NewIDPArray(const char *name)
IDProperty *IDP_CopyIDPArray(IDProperty *array)
{
/* don't use MEM_dupallocN because this may be part of an array */
- IDProperty *narray = MEM_mallocN(sizeof(IDProperty), "IDP_CopyIDPArray"), *tmp;
+ IDProperty *narray, *tmp;
int i;
+ BLI_assert(array->type == IDP_IDPARRAY);
+
+ narray = MEM_mallocN(sizeof(IDProperty), __func__);
*narray = *array;
narray->data.pointer = MEM_dupallocN(array->data.pointer);
@@ -103,6 +112,8 @@ void IDP_FreeIDPArray(IDProperty *prop)
{
int i;
+ BLI_assert(prop->type == IDP_IDPARRAY);
+
for (i = 0; i < prop->len; i++)
IDP_FreeProperty(GETPROP(prop, i));
@@ -113,7 +124,11 @@ void IDP_FreeIDPArray(IDProperty *prop)
/*shallow copies item*/
void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
{
- IDProperty *old = GETPROP(prop, index);
+ IDProperty *old;
+
+ BLI_assert(prop->type == IDP_IDPARRAY);
+
+ old = GETPROP(prop, index);
if (index >= prop->len || index < 0) return;
if (item != old) IDP_FreeProperty(old);
@@ -122,11 +137,15 @@ void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
IDProperty *IDP_GetIndexArray(IDProperty *prop, int index)
{
+ BLI_assert(prop->type == IDP_IDPARRAY);
+
return GETPROP(prop, index);
}
void IDP_AppendArray(IDProperty *prop, IDProperty *item)
{
+ BLI_assert(prop->type == IDP_IDPARRAY);
+
IDP_ResizeIDPArray(prop, prop->len + 1);
IDP_SetIndexArray(prop, prop->len - 1, item);
}
@@ -135,6 +154,8 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
{
int newsize;
+ BLI_assert(prop->type == IDP_IDPARRAY);
+
/* first check if the array buffer size has room */
/* if newlen is 200 items less then totallen, reallocate anyway */
if (newlen <= prop->totallen) {
@@ -286,8 +307,14 @@ static IDProperty *IDP_CopyArray(IDProperty *prop)
return newp;
}
+/** \} */
+
-/* ---------- String Type ------------ */
+/* -------------------------------------------------------------------- */
+/* String Functions */
+
+/** \name IDProperty String API
+ * \{ */
/**
*
@@ -327,9 +354,13 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
static IDProperty *IDP_CopyString(IDProperty *prop)
{
- IDProperty *newp = idp_generic_copy(prop);
+ IDProperty *newp;
+
+ BLI_assert(prop->type == IDP_STRING);
+ newp = idp_generic_copy(prop);
- if (prop->data.pointer) newp->data.pointer = MEM_dupallocN(prop->data.pointer);
+ if (prop->data.pointer)
+ newp->data.pointer = MEM_dupallocN(prop->data.pointer);
newp->len = prop->len;
newp->subtype = prop->subtype;
newp->totallen = prop->totallen;
@@ -340,8 +371,10 @@ static IDProperty *IDP_CopyString(IDProperty *prop)
void IDP_AssignString(IDProperty *prop, const char *st, int maxlen)
{
- int stlen = strlen(st);
+ int stlen;
+ BLI_assert(prop->type == IDP_STRING);
+ stlen = strlen(st);
if (maxlen > 0 && maxlen < stlen)
stlen = maxlen;
@@ -360,6 +393,8 @@ void IDP_ConcatStringC(IDProperty *prop, const char *st)
{
int newlen;
+ BLI_assert(prop->type == IDP_STRING);
+
newlen = prop->len + strlen(st);
/* we have to remember that prop->len includes the null byte for strings.
* so there's no need to add +1 to the resize function.*/
@@ -371,6 +406,8 @@ void IDP_ConcatString(IDProperty *str1, IDProperty *append)
{
int newlen;
+ BLI_assert(append->type == IDP_STRING);
+
/* since ->len for strings includes the NULL byte, we have to subtract one or
* we'll get an extra null byte after each concatenation operation.*/
newlen = str1->len + append->len - 1;
@@ -380,13 +417,19 @@ void IDP_ConcatString(IDProperty *str1, IDProperty *append)
void IDP_FreeString(IDProperty *prop)
{
+ BLI_assert(prop->type == IDP_STRING);
+
if (prop->data.pointer)
MEM_freeN(prop->data.pointer);
}
+/** \} */
-/*-------- ID Type, not in use yet -------*/
+/* -------------------------------------------------------------------- */
+/* ID Type (not in use yet) */
+/** \name IDProperty ID API (unused)
+ * \{ */
void IDP_LinkID(IDProperty *prop, ID *id)
{
if (prop->data.pointer) ((ID *)prop->data.pointer)->us--;
@@ -398,15 +441,26 @@ void IDP_UnlinkID(IDProperty *prop)
{
((ID *)prop->data.pointer)->us--;
}
+/** \} */
+
-/*-------- Group Functions -------*/
+/* -------------------------------------------------------------------- */
+/* Group Functions */
-/*checks if a property with the same name as prop exists, and if so replaces it.*/
+/** \name IDProperty Group API
+ * \{ */
+
+/**
+ * Checks if a property with the same name as prop exists, and if so replaces it.
+ */
static IDProperty *IDP_CopyGroup(IDProperty *prop)
{
- IDProperty *newp = idp_generic_copy(prop), *link;
- newp->len = prop->len;
+ IDProperty *newp, *link;
+ BLI_assert(prop->type == IDP_GROUP);
+ newp = idp_generic_copy(prop);
+ newp->len = prop->len;
+
for (link = prop->data.group.first; link; link = link->next) {
BLI_addtail(&newp->data.group, IDP_CopyProperty(link));
}
@@ -419,6 +473,10 @@ static IDProperty *IDP_CopyGroup(IDProperty *prop)
void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src)
{
IDProperty *other, *prop;
+
+ BLI_assert(dest->type == IDP_GROUP);
+ BLI_assert(src->type == IDP_GROUP);
+
for (prop = src->data.group.first; prop; prop = prop->next) {
other = BLI_findstring(&dest->data.group, prop->name, offsetof(IDProperty, name));
if (other && prop->type == other->type) {
@@ -454,6 +512,10 @@ void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src)
void IDP_ReplaceGroupInGroup(IDProperty *dest, IDProperty *src)
{
IDProperty *loop, *prop;
+
+ BLI_assert(dest->type == IDP_GROUP);
+ BLI_assert(src->type == IDP_GROUP);
+
for (prop = src->data.group.first; prop; prop = prop->next) {
for (loop = dest->data.group.first; loop; loop = loop->next) {
if (STREQ(loop->name, prop->name)) {
@@ -484,6 +546,9 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, IDProperty *src)
void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop)
{
IDProperty *loop;
+
+ BLI_assert(group->type == IDP_GROUP);
+
if ((loop = IDP_GetPropertyFromGroup(group, prop->name))) {
BLI_insertlinkafter(&group->data.group, loop, prop);
@@ -497,13 +562,16 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop)
}
}
-/*
+/**
* If a property is missing in \a dest, add it.
*/
void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite)
{
IDProperty *prop;
+ BLI_assert(dest->type == IDP_GROUP);
+ BLI_assert(src->type == IDP_GROUP);
+
if (do_overwrite) {
for (prop = src->data.group.first; prop; prop = prop->next) {
IDProperty *copy = IDP_CopyProperty(prop);
@@ -538,6 +606,8 @@ void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite)
*/
int IDP_AddToGroup(IDProperty *group, IDProperty *prop)
{
+ BLI_assert(group->type == IDP_GROUP);
+
if (IDP_GetPropertyFromGroup(group, prop->name) == NULL) {
group->len++;
BLI_addtail(&group->data.group, prop);
@@ -553,6 +623,8 @@ int IDP_AddToGroup(IDProperty *group, IDProperty *prop)
*/
int IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew)
{
+ BLI_assert(group->type == IDP_GROUP);
+
if (IDP_GetPropertyFromGroup(group, pnew->name) == NULL) {
group->len++;
BLI_insertlinkafter(&group->data.group, previous, pnew);
@@ -571,12 +643,16 @@ int IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew)
*/
void IDP_RemFromGroup(IDProperty *group, IDProperty *prop)
{
+ BLI_assert(group->type == IDP_GROUP);
+
group->len--;
BLI_remlink(&group->data.group, prop);
}
IDProperty *IDP_GetPropertyFromGroup(IDProperty *prop, const char *name)
{
+ BLI_assert(prop->type == IDP_GROUP);
+
return (IDProperty *)BLI_findstring(&prop->data.group, name, offsetof(IDProperty, name));
}
/** same as above but ensure type match */
@@ -599,7 +675,10 @@ typedef struct IDPIter {
*/
void *IDP_GetGroupIterator(IDProperty *prop)
{
- IDPIter *iter = MEM_callocN(sizeof(IDPIter), "IDPIter");
+ IDPIter *iter;
+
+ BLI_assert(prop->type == IDP_GROUP);
+ iter = MEM_mallocN(sizeof(IDPIter), "IDPIter");
iter->next = prop->data.group.first;
iter->parent = prop;
return (void *) iter;
@@ -640,14 +719,21 @@ void IDP_FreeIterBeforeEnd(void *vself)
static void IDP_FreeGroup(IDProperty *prop)
{
IDProperty *loop;
+
+ BLI_assert(prop->type == IDP_GROUP);
for (loop = prop->data.group.first; loop; loop = loop->next) {
IDP_FreeProperty(loop);
}
BLI_freelistN(&prop->data.group);
}
+/** \} */
-/*-------- Main Functions --------*/
+/* -------------------------------------------------------------------- */
+/* Main Functions */
+
+/** \name IDProperty Main API
+ * \{ */
IDProperty *IDP_CopyProperty(IDProperty *prop)
{
switch (prop->type) {
@@ -909,3 +995,5 @@ void IDP_UnlinkProperty(IDProperty *prop)
break;
}
}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 2bf6304b04b..01b41eb22cd 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1250,6 +1250,12 @@ static int do_add_image_extension(char *string, const char imtype, const ImageFo
}
}
#endif
+#ifdef WITH_OPENIMAGEIO
+ else if (imtype == R_IMF_IMTYPE_PSD) {
+ if (!BLI_testextensie(string, ".psd"))
+ extension = ".psd";
+ }
+#endif
#ifdef WITH_OPENEXR
else if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
if (!BLI_testextensie(string, ".exr"))
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index dd747ba4e46..9b8d34e651d 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -1411,7 +1411,7 @@ bool new_id(ListBase *lb, ID *id, const char *tname)
/* This was in 2.43 and previous releases
* however all data in blender should be sorted, not just duplicate names
- * sorting should not hurt, but noting just incause it alters the way other
+ * sorting should not hurt, but noting just incase it alters the way other
* functions work, so sort every time */
#if 0
if (result)
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 874e60936d1..a43bf41058c 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -409,7 +409,7 @@ static void layer_bucket_init_dummy(MaskRasterLayer *layer)
static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size)
{
- MemArena *arena = BLI_memarena_new(1 << 16, __func__);
+ MemArena *arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), __func__);
const float bucket_dim_x = BLI_rctf_size_x(&layer->bounds);
const float bucket_dim_y = BLI_rctf_size_y(&layer->bounds);
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 090d41aba73..a77f768835a 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -645,7 +645,7 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int
}
cdlp = &pdata->layers[poly_index];
cdlu = &ldata->layers[loop_index];
- cdlf = do_tessface ? &fdata->layers[face_index] : NULL;
+ cdlf = fdata && do_tessface ? &fdata->layers[face_index] : NULL;
BLI_strncpy(cdlp->name, new_name, sizeof(cdlp->name));
CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers);
@@ -662,8 +662,10 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int
CustomData_set_layer_unique_name(ldata, cdlu - ldata->layers);
break;
case 2:
- BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name));
- CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers);
+ if (cdlf) {
+ BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name));
+ CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers);
+ }
break;
}
}
@@ -673,48 +675,61 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int
bool BKE_mesh_uv_cdlayer_rename(Mesh *me, const char *old_name, const char *new_name, bool do_tessface)
{
- CustomData *pdata = &me->pdata, *ldata = &me->ldata, *fdata = &me->fdata;
- const int pidx_start = CustomData_get_layer_index(pdata, CD_MTEXPOLY);
- const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV);
- const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1;
- int pidx, lidx, fidx;
-
- do_tessface = (do_tessface && fdata->totlayer && !me->edit_btmesh);
- pidx = CustomData_get_named_layer(pdata, CD_MTEXPOLY, old_name);
- lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name);
- fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1;
-
- /* None of those cases should happen, in theory!
- * Note this assume we have the same number of mtexpoly, mloopuv and mtface layers!
- */
- if (pidx == -1) {
- if (lidx == -1) {
- if (fidx == -1) {
- /* No layer found with this name! */
- return false;
- }
- else {
- lidx = lidx_start + (fidx - fidx_start);
- }
- }
- pidx = pidx_start + (lidx - lidx_start);
+ CustomData *pdata, *ldata, *fdata;
+ if (me->edit_btmesh) {
+ pdata = &me->edit_btmesh->bm->pdata;
+ ldata = &me->edit_btmesh->bm->ldata;
+ /* No tessellated data in BMesh! */
+ fdata = NULL;
+ do_tessface = false;
}
else {
- if (lidx == -1) {
- lidx = lidx_start + (pidx - pidx_start);
+ pdata = &me->pdata;
+ ldata = &me->ldata;
+ fdata = &me->fdata;
+ do_tessface = (do_tessface && fdata->totlayer);
+ }
+
+ {
+ const int pidx_start = CustomData_get_layer_index(pdata, CD_MTEXPOLY);
+ const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV);
+ const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1;
+ int pidx = CustomData_get_named_layer(pdata, CD_MTEXPOLY, old_name);
+ int lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name);
+ int fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1;
+
+ /* None of those cases should happen, in theory!
+ * Note this assume we have the same number of mtexpoly, mloopuv and mtface layers!
+ */
+ if (pidx == -1) {
+ if (lidx == -1) {
+ if (fidx == -1) {
+ /* No layer found with this name! */
+ return false;
+ }
+ else {
+ lidx = lidx_start + (fidx - fidx_start);
+ }
+ }
+ pidx = pidx_start + (lidx - lidx_start);
}
- if (fidx == -1 && do_tessface) {
- fidx = fidx_start + (pidx - pidx_start);
+ else {
+ if (lidx == -1) {
+ lidx = lidx_start + (pidx - pidx_start);
+ }
+ if (fidx == -1 && do_tessface) {
+ fidx = fidx_start + (pidx - pidx_start);
+ }
}
- }
#if 0
- /* For now, we do not consider mismatch in indices (i.e. same name leading to (relative) different indices). */
- else if ((pidx - pidx_start) != (lidx - lidx_start)) {
- lidx = lidx_start + (pidx - pidx_start);
- }
+ /* For now, we do not consider mismatch in indices (i.e. same name leading to (relative) different indices). */
+ else if ((pidx - pidx_start) != (lidx - lidx_start)) {
+ lidx = lidx_start + (pidx - pidx_start);
+ }
#endif
- return BKE_mesh_uv_cdlayer_rename_index(me, pidx, lidx, fidx, new_name, do_tessface);
+ return BKE_mesh_uv_cdlayer_rename_index(me, pidx, lidx, fidx, new_name, do_tessface);
+ }
}
void BKE_mesh_boundbox_calc(Mesh *me, float r_loc[3], float r_size[3])
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 07dfae2f28a..47b8e053bf7 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -318,9 +318,9 @@ void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces,
* Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
* Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges).
*/
-void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *medges, int numEdges,
- MLoop *mloops, float (*r_loopnors)[3], int numLoops,
- MPoly *mpolys, float (*polynors)[3], int numPolys, float split_angle)
+void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdge *medges, const int numEdges,
+ MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
+ MPoly *mpolys, float (*polynors)[3], const int numPolys, float split_angle)
{
#define INDEX_UNSET INT_MIN
#define INDEX_INVALID -1
@@ -333,7 +333,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med
* sharp edge: < 0 (INDEX_INVALID || INDEX_UNSET),
* unset: INDEX_UNSET
* Note that currently we only have two values for second loop of sharp edges. However, if needed, we can
- * store the negated value of loop index instead of INDEX_INVALID to retrieve th real value later in code).
+ * store the negated value of loop index instead of INDEX_INVALID to retrieve the real value later in code).
* Note also that lose edges always have both values set to 0!
*/
int (*edge_to_loops)[2] = MEM_callocN(sizeof(int[2]) * (size_t)numEdges, __func__);
@@ -377,7 +377,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med
/* Check whether current edge might be smooth or sharp */
if ((e2l[0] | e2l[1]) == 0) {
- /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INT_MIN to tag it as unset). */
+ /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */
e2l[0] = ml_curr_index;
e2l[1] = INDEX_UNSET;
}
@@ -397,7 +397,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med
}
}
else if (!IS_EDGE_SHARP(e2l)) {
- /* More that two loops using this edge, tag as sharp if not yet done. */
+ /* More than two loops using this edge, tag as sharp if not yet done. */
e2l[1] = INDEX_INVALID;
}
/* Else, edge is already 'disqualified' (i.e. sharp)! */
@@ -448,6 +448,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med
* it should not be a common case in real-life meshes anyway).
*/
const unsigned int mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
+ const MVert *mv_pivot = &mverts[mv_pivot_index];
const int *e2lfan_curr;
float vec_curr[3], vec_prev[3];
MLoop *mlfan_curr, *mlfan_next;
@@ -464,11 +465,10 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med
/* Only need to compute previous edge's vector once, then we can just reuse old current one! */
{
- const MEdge *me_prev = &medges[ml_prev->e];
- const MVert *mv_1 = &mverts[mv_pivot_index];
+ const MEdge *me_prev = &medges[ml_curr->e]; /* ml_curr would be mlfan_prev if we needed that one */
const MVert *mv_2 = (me_prev->v1 == mv_pivot_index) ? &mverts[me_prev->v2] : &mverts[me_prev->v1];
- sub_v3_v3v3(vec_prev, mv_2->co, mv_1->co);
+ sub_v3_v3v3(vec_prev, mv_2->co, mv_pivot->co);
normalize_v3(vec_prev);
}
@@ -479,12 +479,11 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med
* given the fact that this code should not be called that much in real-life meshes...
*/
{
- const MEdge *me_curr = &medges[ml_curr->e];
- const MVert *mv_1 = &mverts[mv_pivot_index];
+ const MEdge *me_curr = &medges[mlfan_curr->e];
const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] :
&mverts[me_curr->v1];
- sub_v3_v3v3(vec_curr, mv_2->co, mv_1->co);
+ sub_v3_v3v3(vec_curr, mv_2->co, mv_pivot->co);
normalize_v3(vec_curr);
}
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index bf4a63c52a8..d9630a7343d 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -62,7 +62,6 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
-#include "BLI_mempool.h"
#include "BLI_threads.h"
#include "BKE_animsys.h"
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 4519a116946..0cdcf4e7298 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -114,8 +114,8 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden,
BLI_bitmap *prev_hidden)
{
BLI_bitmap *subd;
- int hi_gridsize = ccg_gridsize(hi_level);
- int lo_gridsize = ccg_gridsize(lo_level);
+ int hi_gridsize = BKE_ccg_gridsize(hi_level);
+ int lo_gridsize = BKE_ccg_gridsize(lo_level);
int yh, xh, xl, yl, xo, yo, hi_ndx;
int offset, factor;
@@ -127,7 +127,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden,
subd = BLI_BITMAP_NEW(hi_gridsize * hi_gridsize, "MDisps.hidden upsample");
- factor = ccg_factor(lo_level, hi_level);
+ factor = BKE_ccg_factor(lo_level, hi_level);
offset = 1 << (hi_level - lo_level - 1);
/* low-res blocks */
@@ -173,12 +173,12 @@ static BLI_bitmap *multires_mdisps_downsample_hidden(BLI_bitmap *old_hidden,
int new_level)
{
BLI_bitmap *new_hidden;
- int new_gridsize = ccg_gridsize(new_level);
- int old_gridsize = ccg_gridsize(old_level);
+ int new_gridsize = BKE_ccg_gridsize(new_level);
+ int old_gridsize = BKE_ccg_gridsize(old_level);
int x, y, factor, old_value;
BLI_assert(new_level <= old_level);
- factor = ccg_factor(new_level, old_level);
+ factor = BKE_ccg_factor(new_level, old_level);
new_hidden = BLI_BITMAP_NEW(new_gridsize * new_gridsize,
"downsample hidden");
@@ -246,7 +246,7 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level)
{
MDisps *mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS,
CD_CALLOC, NULL, me->totloop);
- int gridsize = ccg_gridsize(level);
+ int gridsize = BKE_ccg_gridsize(level);
int gridarea = gridsize * gridsize;
int i, j, k;
@@ -594,7 +594,7 @@ static void multires_copy_dm_grid(CCGElem *gridA, CCGElem *gridB, CCGKey *keyA,
static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level)
{
if (level < gpm->level) {
- int gridsize = ccg_gridsize(level);
+ int gridsize = BKE_ccg_gridsize(level);
float *data = MEM_callocN(sizeof(float) * gridsize * gridsize,
"multires_grid_paint_mask_downsample");
int x, y;
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 2305c0696af..c0df306a3fa 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1107,7 +1107,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
* copying for internal use (threads for eg), where you wont want it to modify the
* scene data.
*/
-static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern, const short copy_previews)
+static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_id_user, bool do_make_extern, bool copy_previews)
{
bNodeTree *newtree;
bNode *node /*, *nnode */ /* UNUSED */, *last;
@@ -1116,13 +1116,17 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use
if (ntree == NULL) return NULL;
- /* is ntree part of library? */
- for (newtree = G.main->nodetree.first; newtree; newtree = newtree->id.next)
- if (newtree == ntree) break;
- if (newtree) {
- newtree = BKE_libblock_copy(&ntree->id);
+ if (bmain) {
+ /* is ntree part of library? */
+ if (BLI_findindex(&bmain->nodetree, ntree) != -1)
+ newtree = BKE_libblock_copy(&ntree->id);
+ else
+ newtree = NULL;
}
- else {
+ else
+ newtree = NULL;
+
+ if (newtree == NULL) {
newtree = MEM_dupallocN(ntree);
newtree->id.lib = NULL; /* same as owning datablock id.lib */
BKE_libblock_copy_data(&newtree->id, &ntree->id, true); /* copy animdata and ID props */
@@ -1208,7 +1212,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use
bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const short do_id_user)
{
- return ntreeCopyTree_internal(ntree, do_id_user, TRUE, TRUE);
+ return ntreeCopyTree_internal(ntree, G.main, do_id_user, TRUE, TRUE);
}
bNodeTree *ntreeCopyTree(bNodeTree *ntree)
{
@@ -1590,6 +1594,8 @@ static void node_unlink_attached(bNodeTree *ntree, bNode *parent)
void nodeFreeNode(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock, *nextsock;
+ char propname_esc[MAX_IDPROP_NAME * 2];
+ char prefix[MAX_IDPROP_NAME * 2];
/* extra free callback */
if (node->typeinfo && node->typeinfo->freefunc_api) {
@@ -1609,6 +1615,11 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
BLI_remlink(&ntree->nodes, node);
+ BLI_strescape(propname_esc, node->name, sizeof(propname_esc));
+ BLI_snprintf(prefix, sizeof(prefix), "nodes[\"%s\"]", propname_esc);
+
+ BKE_animdata_fix_paths_remove((ID *)ntree, prefix);
+
if (ntree->typeinfo && ntree->typeinfo->free_node_cache)
ntree->typeinfo->free_node_cache(ntree, node);
@@ -1657,6 +1668,22 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *so
MEM_freeN(sock->default_value);
}
+static void free_localized_node_groups(bNodeTree *ntree)
+{
+ bNode *node;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP && node->id) {
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+ if (BLI_findindex(&G.main->nodetree, ngroup) == -1) {
+ /* ntree is not in library, i.e. localized node group: free it */
+ ntreeFreeTree_ex(ngroup, false);
+ MEM_freeN(ngroup);
+ }
+ }
+ }
+}
+
/* do not free ntree itself here, BKE_libblock_free calls this function too */
void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
{
@@ -1683,6 +1710,9 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
}
}
+ /* XXX not nice, but needed to free localized node groups properly */
+ free_localized_node_groups(ntree);
+
/* unregister associated RNA types */
ntreeInterfaceTypeFree(ntree);
@@ -1932,8 +1962,14 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
/* Make full copy.
* Note: previews are not copied here.
*/
- ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE, FALSE);
-
+ ltree = ntreeCopyTree_internal(ntree, NULL, FALSE, FALSE, FALSE);
+
+ for (node = ltree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP && node->id) {
+ node->id = (ID *)ntreeLocalize((bNodeTree *)node->id);
+ }
+ }
+
if (adt) {
AnimData *ladt = BKE_animdata_from_id(&ltree->id);
@@ -1978,7 +2014,7 @@ void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree)
/* we have to assume the editor already changed completely */
void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree)
{
- if (localtree && ntree) {
+ if (ntree && localtree) {
if (ntree->typeinfo->local_merge)
ntree->typeinfo->local_merge(localtree, ntree);
@@ -2285,7 +2321,7 @@ bNode *nodeGetActive(bNodeTree *ntree)
static bNode *node_get_active_id_recursive(bNodeInstanceKey active_key, bNodeInstanceKey parent_key, bNodeTree *ntree, short idtype)
{
- if (parent_key.value == active_key.value) {
+ if (parent_key.value == active_key.value || active_key.value == 0) {
bNode *node;
for (node = ntree->nodes.first; node; node = node->next)
if (node->id && GS(node->id->name) == idtype)
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 5d0216affca..8c2475369de 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -643,7 +643,9 @@ void BKE_object_unlink(Object *ob)
for (lineset = (FreestyleLineSet *)srl->freestyleConfig.linesets.first;
lineset; lineset = lineset->next)
{
- BKE_unlink_linestyle_target_object(lineset->linestyle, ob);
+ if (lineset->linestyle) {
+ BKE_unlink_linestyle_target_object(lineset->linestyle, ob);
+ }
}
}
}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index b47a493581e..6bdfb22dc1a 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -359,8 +359,8 @@ int paint_is_bmesh_face_hidden(BMFace *f)
float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level,
unsigned x, unsigned y)
{
- int factor = ccg_factor(level, gpm->level);
- int gridsize = ccg_gridsize(gpm->level);
+ int factor = BKE_ccg_factor(level, gpm->level);
+ int gridsize = BKE_ccg_gridsize(gpm->level);
return gpm->data[(y * factor) * gridsize + (x * factor)];
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 216bc94a058..24cf98d957d 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -1729,7 +1729,7 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_
return 0;
if (dm->deformedOnly || index_dmcache == DMCACHE_ISCHILD) {
- /* for meshes that are either only defined or for child particles, the
+ /* for meshes that are either only deformed or for child particles, the
* index and fw do not require any mapping, so we can directly use it */
if (from == PART_FROM_VERT) {
if (index >= dm->getNumVerts(dm))
@@ -1817,8 +1817,8 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
copy_v3_v3(orco, orcodata[mapindex]);
if (ornor) {
- dm->getVertNo(dm, mapindex, nor);
- normalize_v3(nor);
+ dm->getVertNo(dm, mapindex, ornor);
+ normalize_v3(ornor);
}
if (utan && vtan) {
@@ -1843,7 +1843,7 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
if (nor)
copy_v3_v3(nor, tmpnor);
- normalize_v3(tmpnor);
+ normalize_v3(tmpnor); /* XXX Why not normalize tmpnor before copying it into nor??? -- mont29 */
mul_v3_fl(tmpnor, -foffset);
add_v3_v3(vec, tmpnor);
}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index c83d760797b..0a7c6d901af 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -438,10 +438,6 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
if (new_node) {
pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v);
}
- else {
- BLI_gset_remove(f_node->bm_unique_verts, v, NULL);
- BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL);
- }
}
else {
/* Remove from other verts */
@@ -516,10 +512,10 @@ static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
return ((len_squared_v3v3(q->center, c) <= q->radius_squared));
}
-/* Return true if the vertex mask is less than 0.5, false otherwise */
-static bool check_mask_half(EdgeQueueContext *eq_ctx, BMVert *v)
+/* Return true if the vertex mask is less than 1.0, false otherwise */
+static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v)
{
- return (BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 0.5f);
+ return (BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 1.0f);
}
static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e,
@@ -527,11 +523,13 @@ static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e,
{
BMVert **pair;
- /* Don't let topology update affect masked vertices. Unlike with
- * displacements, can't do 50% topology update, so instead set
- * (arbitrary) cutoff: if both vertices' masks are less than 50%,
- * topology update can happen. */
- if (check_mask_half(eq_ctx, e->v1) && check_mask_half(eq_ctx, e->v2)) {
+ /* Don't let topology update affect fully masked vertices. This used to
+ * have a 50% mask cutoff, with the reasoning that you can't do a 50%
+ * topology update. But this gives an ugly border in the mesh. The mask
+ * should already make the brush move the vertices only 50%, which means
+ * that topology updates will also happen less frequent, that should be
+ * enough. */
+ if (check_mask(eq_ctx, e->v1) || check_mask(eq_ctx, e->v2)) {
pair = BLI_mempool_alloc(eq_ctx->pool);
pair[0] = e->v1;
pair[1] = e->v2;
@@ -678,6 +676,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh,
BMVert *v_new;
float mid[3];
int i, node_index;
+ const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK);
/* Get all faces adjacent to the edge */
pbvh_bmesh_edge_loops(edge_loops, e);
@@ -689,6 +688,15 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh,
e->v1));
v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1);
+ /* update paint mask */
+ if (cd_vert_mask_offset != -1) {
+ float mask_v1 = BM_ELEM_CD_GET_FLOAT(e->v1, cd_vert_mask_offset);
+ float mask_v2 = BM_ELEM_CD_GET_FLOAT(e->v2, cd_vert_mask_offset);
+ float mask_v_new = 0.5f * (mask_v1 + mask_v2);
+
+ BM_ELEM_CD_SET_FLOAT(v_new, cd_vert_mask_offset, mask_v_new);
+ }
+
/* For each face, add two new triangles and delete the original */
for (i = 0; i < edge_loops->count; i++) {
BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i);
@@ -1112,7 +1120,7 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
if (mode & PBVH_Collapse) {
EdgeQueue q;
- BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2,
+ BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]),
128, 128, 0);
EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset};
@@ -1125,7 +1133,7 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
if (mode & PBVH_Subdivide) {
EdgeQueue q;
- BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2,
+ BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]),
128, 128, 0);
EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset};
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index b89cb6b7b82..41e43c00457 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -493,23 +493,10 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->r.border.ymax = 1.0f;
sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct");
- sce->toolsettings->cornertype = 1;
- sce->toolsettings->degr = 90;
- sce->toolsettings->step = 9;
- sce->toolsettings->turn = 1;
- sce->toolsettings->extr_offs = 1;
sce->toolsettings->doublimit = 0.001;
- sce->toolsettings->segments = 32;
- sce->toolsettings->rings = 32;
- sce->toolsettings->vertices = 32;
- sce->toolsettings->uvcalc_radius = 1.0f;
- sce->toolsettings->uvcalc_cubesize = 1.0f;
- sce->toolsettings->uvcalc_mapdir = 1;
- sce->toolsettings->uvcalc_mapalign = 1;
sce->toolsettings->uvcalc_margin = 0.001f;
sce->toolsettings->unwrapper = 1;
sce->toolsettings->select_thresh = 0.01f;
- sce->toolsettings->jointrilimit = 0.8f;
sce->toolsettings->selectmode = SCE_SELECT_VERTEX;
sce->toolsettings->uv_selectmode = UV_SELECT_VERTEX;
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 43845638754..dd7e847feaf 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -632,7 +632,7 @@ static void seq_update_sound_bounds_recursive_rec(Scene *scene, Sequence *metase
endofs = seq->start + seq->len - end;
sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs,
- seq->start + seq->len - endofs, startofs);
+ seq->start + seq->len - endofs, startofs + seq->anim_startofs);
}
}
}
@@ -664,8 +664,9 @@ void BKE_sequence_calc_disp(Scene *scene, Sequence *seq)
if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
BKE_sequencer_update_sound_bounds(scene, seq);
}
- else if (seq->type == SEQ_TYPE_META)
+ else if (seq->type == SEQ_TYPE_META) {
seq_update_sound_bounds_recursive(scene, seq);
+ }
}
void BKE_sequence_calc(Scene *scene, Sequence *seq)
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 9bc7f4b9e2b..5c9c564998e 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -506,7 +506,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
DerivedMesh *ss_mesh = NULL;
ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
- /* remove loop dependencies on derived meshs (TODO should this be done elsewhere?) */
+ /* remove loop dependencies on derived meshes (TODO should this be done elsewhere?) */
if (smd->target == ob) smd->target = NULL;
if (smd->auxTarget == ob) smd->auxTarget = NULL;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 2461ec85bb4..9a38a5f87b8 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -170,7 +170,7 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
if (useArena) {
CCGAllocatorIFC allocatorIFC;
- CCGAllocatorHDL allocator = BLI_memarena_new((1 << 16), "subsurf arena");
+ CCGAllocatorHDL allocator = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "subsurf arena");
allocatorIFC.alloc = arena_alloc;
allocatorIFC.realloc = arena_realloc;
@@ -1064,8 +1064,8 @@ void subsurf_copy_grid_hidden(DerivedMesh *dm, const MPoly *mpoly,
for (j = 0; j < mpoly[i].totloop; j++) {
const MDisps *md = &mdisps[mpoly[i].loopstart + j];
- int hidden_gridsize = ccg_gridsize(md->level);
- int factor = ccg_factor(level, md->level);
+ int hidden_gridsize = BKE_ccg_gridsize(md->level);
+ int factor = BKE_ccg_factor(level, md->level);
if (!md->hidden)
continue;
@@ -1107,8 +1107,8 @@ void subsurf_copy_grid_paint_mask(DerivedMesh *dm, const MPoly *mpoly,
if (!gpm->data)
continue;
- factor = ccg_factor(level, gpm->level);
- gpm_gridsize = ccg_gridsize(gpm->level);
+ factor = BKE_ccg_factor(level, gpm->level);
+ gpm_gridsize = BKE_ccg_gridsize(gpm->level);
for (y = 0; y < gridSize; y++) {
for (x = 0; x < gridSize; x++) {
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index d98a6cbe0cc..22b0fe7bc24 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -123,12 +123,12 @@ void init_tex_mapping(TexMapping *texmap)
if (ELEM(texmap->type, TEXMAP_TYPE_TEXTURE, TEXMAP_TYPE_NORMAL)) {
/* keep matrix invertible */
- if(fabsf(size[0]) < 1e-5f)
- size[0] = signf(size[0])*1e-5f;
- if(fabsf(size[1]) < 1e-5f)
- size[1] = signf(size[1])*1e-5f;
- if(fabsf(size[2]) < 1e-5f)
- size[2] = signf(size[2])*1e-5f;
+ if (fabsf(size[0]) < 1e-5f)
+ size[0] = signf(size[0]) * 1e-5f;
+ if (fabsf(size[1]) < 1e-5f)
+ size[1] = signf(size[1]) * 1e-5f;
+ if (fabsf(size[2]) < 1e-5f)
+ size[2] = signf(size[2]) * 1e-5f;
}
size_to_mat4(smat, texmap->size);
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index fd92ec9f462..b8711f6e5f6 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -3340,7 +3340,7 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac
break;
}
- libmv_homography2DFromCorrespondencesLinear(x1, x2, num_correspondences, H_double, 1e-8);
+ libmv_homography2DFromCorrespondencesEuc(x1, x2, num_correspondences, H_double);
mat3f_from_mat3d(H, H_double);
@@ -3444,7 +3444,7 @@ void BKE_tracking_homography_between_two_quads(/*const*/ float reference_corners
float_corners_to_double(reference_corners, x1);
float_corners_to_double(corners, x2);
- libmv_homography2DFromCorrespondencesLinear(x1, x2, 4, H_double, 1e-8);
+ libmv_homography2DFromCorrespondencesEuc(x1, x2, 4, H_double);
mat3f_from_mat3d(H, H_double);
}
diff --git a/source/blender/blenlib/BLI_bitmap.h b/source/blender/blenlib/BLI_bitmap.h
index bcdc97cdaa7..cf10fe53a5d 100644
--- a/source/blender/blenlib/BLI_bitmap.h
+++ b/source/blender/blenlib/BLI_bitmap.h
@@ -60,6 +60,9 @@ typedef unsigned int BLI_bitmap;
((_bitmap)[(_index) >> BLI_BITMAP_POWER] & \
(1u << ((_index) & BLI_BITMAP_MASK)))
+#define BLI_BITMAP_GET_BOOL(_bitmap, _index) \
+ (BLI_BITMAP_GET(_bitmap, _index) != 0)
+
/* set the value of a single bit at '_index' */
#define BLI_BITMAP_SET(_bitmap, _index) \
((_bitmap)[(_index) >> BLI_BITMAP_POWER] |= \
diff --git a/source/blender/blenlib/BLI_boxpack2d.h b/source/blender/blenlib/BLI_boxpack2d.h
index 8316987dfcd..b02e3423f88 100644
--- a/source/blender/blenlib/BLI_boxpack2d.h
+++ b/source/blender/blenlib/BLI_boxpack2d.h
@@ -39,14 +39,15 @@ typedef struct BoxPack {
float y;
float w;
float h;
- int index;
/* Verts this box uses
* (BL,TR,TL,BR) / 0,1,2,3 */
struct BoxVert *v[4];
+
+ int index;
} BoxPack;
-void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *tot_height);
+void BLI_box_pack_2d(BoxPack *boxarray, const unsigned int len, float *tot_width, float *tot_height);
#endif
diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h
index ca050883018..c9fb00ecdf5 100644
--- a/source/blender/blenlib/BLI_linklist_stack.h
+++ b/source/blender/blenlib/BLI_linklist_stack.h
@@ -151,8 +151,6 @@
(void)&(_##var##_type); \
} (void)0
-#include "BLI_alloca.h"
-
/** \} */
#endif /* __BLI_LINKLIST_STACK_H__ */
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index d3f6c7ef14b..f815716148b 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -155,8 +155,8 @@ bool isect_ray_tri_epsilon_v3(const float p1[3], const float d[3],
const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float epsilon);
/* point in polygon */
-bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr);
-bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr);
+bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr, const bool use_holes);
+bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr, const bool use_holes);
int isect_point_quad_v2(const float p[2], const float a[2], const float b[2], const float c[2], const float d[2]);
@@ -188,7 +188,10 @@ bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4]);
bool clip_segment_v3_plane_n(float p1[3], float p2[3], float plane_array[][4], const int plane_tot);
void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int, void *), void *userData);
-
+void fill_poly_v2i_n(
+ const int xmin, const int ymin, const int xmax, const int ymax,
+ const int polyXY[][2], const int polyCorners,
+ void (*callback)(int, int, void *), void *userData);
/****************************** Interpolation ********************************/
/* tri or quad, d can be NULL */
diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h
index 9ff4883c89c..737324ebc16 100644
--- a/source/blender/blenlib/BLI_memarena.h
+++ b/source/blender/blenlib/BLI_memarena.h
@@ -47,7 +47,7 @@ extern "C" {
* enough to not cause much internal fragmentation,
* small enough not to waste resources
*/
-#define BLI_MEMARENA_STD_BUFSIZE (1 << 14)
+#define BLI_MEMARENA_STD_BUFSIZE MEM_SIZE_OPTIMAL(1 << 14)
struct MemArena;
typedef struct MemArena MemArena;
diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h
index 88650719712..3fab77f2cb2 100644
--- a/source/blender/blenlib/BLI_mempool.h
+++ b/source/blender/blenlib/BLI_mempool.h
@@ -67,6 +67,10 @@ void **BLI_mempool_as_tableN(BLI_mempool *pool, const char *allocstr) ATTR_
void BLI_mempool_as_array(BLI_mempool *pool, void *data) ATTR_NONNULL(1, 2);
void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
+#ifdef DEBUG
+void BLI_mempool_set_memory_debug(void);
+#endif
+
/** iteration stuff. note: this may easy to produce bugs with **/
/* private structure */
typedef struct BLI_mempool_iter {
diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h
index e7d2130e473..52f5decb4f4 100644
--- a/source/blender/blenlib/BLI_scanfill.h
+++ b/source/blender/blenlib/BLI_scanfill.h
@@ -51,7 +51,7 @@ typedef struct ScanFillContext {
struct MemArena *arena;
} ScanFillContext;
-#define BLI_SCANFILL_ARENA_SIZE 16384
+#define BLI_SCANFILL_ARENA_SIZE MEM_SIZE_OPTIMAL(1 << 14)
typedef struct ScanFillVert {
struct ScanFillVert *next, *prev;
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
new file mode 100644
index 00000000000..f57d42858c7
--- /dev/null
+++ b/source/blender/blenlib/BLI_task.h
@@ -0,0 +1,108 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_TASK_H__
+#define __BLI_TASK_H__
+
+/** \file BLI_task.h
+ * \ingroup bli
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
+/* Task Scheduler
+ *
+ * Central scheduler that holds running threads ready to execute tasks. A single
+ * queue holds the task from all pools.
+ *
+ * Init/exit must be called before/after any task pools are created/freed, and
+ * must be called from the main threads. All other scheduler and pool functions
+ * are thread-safe. */
+
+typedef struct TaskScheduler TaskScheduler;
+
+enum {
+ TASK_SCHEDULER_AUTO_THREADS = 0,
+ TASK_SCHEDULER_SINGLE_THREAD = 1
+};
+
+TaskScheduler *BLI_task_scheduler_create(int num_threads);
+void BLI_task_scheduler_free(TaskScheduler *scheduler);
+
+int BLI_task_scheduler_num_threads(TaskScheduler *scheduler);
+
+/* Task Pool
+ *
+ * Pool of tasks that will be executed by the central TaskScheduler. For each
+ * pool, we can wait for all tasks to be done, or cancel them before they are
+ * done.
+ *
+ * Running tasks may spawn new tasks.
+ *
+ * Pools may be nested, i.e. a thread running a task can create another task
+ * pool with smaller tasks. When other threads are busy they will continue
+ * working on their own tasks, if not they will join in, no new threads will
+ * be launched.
+ */
+
+typedef enum TaskPriority {
+ TASK_PRIORITY_LOW,
+ TASK_PRIORITY_HIGH
+} TaskPriority;
+
+typedef struct TaskPool TaskPool;
+typedef void (*TaskRunFunction)(TaskPool *pool, void *taskdata, int threadid);
+
+TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata);
+void BLI_task_pool_free(TaskPool *pool);
+
+void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run,
+ void *taskdata, bool free_taskdata, TaskPriority priority);
+
+/* work and wait until all tasks are done */
+void BLI_task_pool_work_and_wait(TaskPool *pool);
+/* cancel all tasks, keep worker threads running */
+void BLI_task_pool_cancel(TaskPool *pool);
+/* stop all worker threads */
+void BLI_task_pool_stop(TaskPool *pool);
+
+/* for worker threads, test if cancelled */
+bool BLI_task_pool_cancelled(TaskPool *pool);
+
+/* optional userdata pointer to pass along to run function */
+void *BLI_task_pool_userdata(TaskPool *pool);
+
+/* optional mutex to use from run function */
+ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool);
+
+/* number of tasks done, for stats, don't use this to make decisions */
+size_t BLI_task_pool_tasks_done(TaskPool *pool);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h
index 38ad0827246..7a3ee1dd0f4 100644
--- a/source/blender/blenlib/BLI_threads.h
+++ b/source/blender/blenlib/BLI_threads.h
@@ -45,6 +45,7 @@ extern "C" {
#define BLENDER_MAX_THREADS 64
struct ListBase;
+struct TaskScheduler;
/* Threading API */
@@ -52,6 +53,8 @@ struct ListBase;
void BLI_threadapi_init(void);
void BLI_threadapi_exit(void);
+struct TaskScheduler *BLI_task_scheduler_get(void);
+
void BLI_init_threads(struct ListBase *threadbase, void *(*do_thread)(void *), int tot);
int BLI_available_threads(struct ListBase *threadbase);
int BLI_available_thread_index(struct ListBase *threadbase);
@@ -101,6 +104,7 @@ ThreadMutex *BLI_mutex_alloc(void);
void BLI_mutex_free(ThreadMutex *mutex);
void BLI_mutex_lock(ThreadMutex *mutex);
+bool BLI_mutex_trylock(ThreadMutex *mutex);
void BLI_mutex_unlock(ThreadMutex *mutex);
/* Spin Lock */
@@ -144,27 +148,15 @@ void BLI_ticket_mutex_free(TicketMutex *ticket);
void BLI_ticket_mutex_lock(TicketMutex *ticket);
void BLI_ticket_mutex_unlock(TicketMutex *ticket);
-/* ThreadedWorker
- *
- * A simple tool for dispatching work to a limited number of threads
- * in a transparent fashion from the caller's perspective. */
-
-struct ThreadedWorker;
-
-/* Create a new worker supporting tot parallel threads.
- * When new work in inserted and all threads are busy, sleep(sleep_time) before checking again
- */
-struct ThreadedWorker *BLI_create_worker(void *(*do_thread)(void *), int tot, int sleep_time);
-
-/* join all working threads */
-void BLI_end_worker(struct ThreadedWorker *worker);
-
-/* also ends all working threads */
-void BLI_destroy_worker(struct ThreadedWorker *worker);
+/* Condition */
+
+typedef pthread_cond_t ThreadCondition;
-/* Spawns a new work thread if possible, sleeps until one is available otherwise
- * NOTE: inserting work is NOT thread safe, so make sure it is only done from one thread */
-void BLI_insert_work(struct ThreadedWorker *worker, void *param);
+void BLI_condition_init(ThreadCondition *cond);
+void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex);
+void BLI_condition_notify_one(ThreadCondition *cond);
+void BLI_condition_notify_all(ThreadCondition *cond);
+void BLI_condition_end(ThreadCondition *cond);
/* ThreadWorkQueue
*
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 31125fd3153..d855d45760a 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -94,6 +94,7 @@ set(SRC
intern/string.c
intern/string_cursor_utf8.c
intern/string_utf8.c
+ intern/task.c
intern/threads.c
intern/time.c
intern/uvproject.c
@@ -160,6 +161,7 @@ set(SRC
BLI_string_cursor_utf8.h
BLI_string_utf8.h
BLI_sys_types.h
+ BLI_task.h
BLI_threads.h
BLI_utildefines.h
BLI_uvproject.h
@@ -178,6 +180,10 @@ if(WITH_BINRELOC)
add_definitions(-DWITH_BINRELOC)
endif()
+if(WITH_MEM_VALGRIND)
+ add_definitions(-DWITH_MEM_VALGRIND)
+endif()
+
if(WIN32)
list(APPEND INC
../../../intern/utfconv
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
index 45bdeeedcf9..206a8041c4a 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -127,7 +127,7 @@ Heap *BLI_heap_new_ex(unsigned int tot_reserve)
/* ensure we have at least one so we can keep doubling it */
heap->bufsize = MAX2(1, tot_reserve);
heap->tree = (HeapNode **)MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree");
- heap->arena = BLI_memarena_new(1 << 16, "heap arena");
+ heap->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "heap arena");
return heap;
}
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 80483fbfa38..7c1cdd593c3 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -117,7 +117,7 @@ typedef struct BVHRayCastData {
* Notes: You can choose the tree type --> binary, quad, octree, choose below
*/
-static float KDOP_AXES[13][3] = {
+static const float KDOP_AXES[13][3] = {
{1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0},
{1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0},
{0, 1.0, -1.0}
diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c
index 747c2f0c2b7..4a6712201a9 100644
--- a/source/blender/blenlib/intern/BLI_memarena.c
+++ b/source/blender/blenlib/intern/BLI_memarena.c
@@ -38,6 +38,10 @@
#include "BLI_linklist.h"
#include "BLI_strict_flags.h"
+#ifdef WITH_MEM_VALGRIND
+# include "valgrind/memcheck.h"
+#endif
+
struct MemArena {
unsigned char *curbuf;
int bufsize, cursize;
@@ -56,6 +60,10 @@ MemArena *BLI_memarena_new(const int bufsize, const char *name)
ma->align = 8;
ma->name = name;
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_CREATE_MEMPOOL(ma, 0, false);
+#endif
+
return ma;
}
@@ -78,6 +86,11 @@ void BLI_memarena_use_align(struct MemArena *ma, const int align)
void BLI_memarena_free(MemArena *ma)
{
BLI_linklist_freeN(ma->bufs);
+
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_DESTROY_MEMPOOL(ma);
+#endif
+
MEM_freeN(ma);
}
@@ -122,6 +135,10 @@ void *BLI_memarena_alloc(MemArena *ma, int size)
ma->curbuf += size;
ma->cursize -= size;
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_MEMPOOL_ALLOC(ma, ptr, size);
+#endif
+
return ptr;
}
@@ -152,4 +169,10 @@ void BLI_memarena_clear(MemArena *ma)
memset(ma->curbuf, 0, (size_t)curbuf_used);
}
}
+
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_DESTROY_MEMPOOL(ma);
+ VALGRIND_CREATE_MEMPOOL(ma, 0, false);
+#endif
+
}
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index febf09745fb..261e53f0f55 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -45,6 +45,9 @@
#include "BLI_strict_flags.h" /* keep last */
+#ifdef WITH_MEM_VALGRIND
+# include "valgrind/memcheck.h"
+#endif
/* note: copied from BLO_blend_defs.h, don't use here because we're in BLI */
#ifdef __BIG_ENDIAN__
@@ -63,6 +66,10 @@
/* when undefined, merge the allocs for BLI_mempool_chunk and its data */
// #define USE_DATA_PTR
+#ifndef NDEBUG
+static bool mempool_debug_memset = false;
+#endif
+
/**
* A free element from #BLI_mempool_chunk. Data is cast to this type and stored in
* #BLI_mempool.free as a single linked list, each item #BLI_mempool.esize large.
@@ -275,6 +282,10 @@ BLI_mempool *BLI_mempool_create(unsigned int esize, unsigned int totelem,
lasttail = mempool_chunk_add(pool, mpchunk, lasttail);
}
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_CREATE_MEMPOOL(pool, 0, false);
+#endif
+
return pool;
}
@@ -297,6 +308,11 @@ void *BLI_mempool_alloc(BLI_mempool *pool)
}
pool->free = pool->free->next;
+
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_MEMPOOL_ALLOC(pool, retval, pool->esize);
+#endif
+
return retval;
}
@@ -330,6 +346,11 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr)
BLI_assert(!"Attempt to free data which is not in pool.\n");
}
}
+
+ /* enable for debugging */
+ if (UNLIKELY(mempool_debug_memset)) {
+ memset(addr, 255, pool->esize);
+ }
#endif
if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
@@ -345,8 +366,12 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr)
pool->totused--;
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_MEMPOOL_FREE(pool, addr);
+#endif
+
/* nothing is in use; free all the chunks except the first */
- if (pool->totused == 0) {
+ if (UNLIKELY(pool->totused == 0)) {
BLI_freenode *curnode = NULL;
char *tmpaddr = NULL;
unsigned int i;
@@ -359,6 +384,10 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr)
pool->totalloc = pool->pchunk;
#endif
+ /* temp alloc so valgrind doesn't complain when setting free'd blocks 'next' */
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_MEMPOOL_ALLOC(pool, CHUNK_DATA(first), pool->csize);
+#endif
pool->free = CHUNK_DATA(first); /* start of the list */
for (tmpaddr = CHUNK_DATA(first), i = 0; i < pool->pchunk; i++) {
curnode = ((BLI_freenode *)tmpaddr);
@@ -366,6 +395,10 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr)
curnode->next = (BLI_freenode *)tmpaddr;
}
curnode->next = NULL; /* terminate the list */
+
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_MEMPOOL_FREE(pool, CHUNK_DATA(first));
+#endif
}
}
@@ -537,6 +570,11 @@ void BLI_mempool_clear_ex(BLI_mempool *pool, const int totelem_reserve)
ListBase chunks_temp;
BLI_freenode *lasttail = NULL;
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_DESTROY_MEMPOOL(pool);
+ VALGRIND_CREATE_MEMPOOL(pool, 0, false);
+#endif
+
if (totelem_reserve == -1) {
maxchunks = pool->maxchunks;
}
@@ -582,6 +620,10 @@ void BLI_mempool_destroy(BLI_mempool *pool)
{
mempool_chunk_free_all(&pool->chunks, pool->flag);
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_DESTROY_MEMPOOL(pool);
+#endif
+
if (pool->flag & BLI_MEMPOOL_SYSMALLOC) {
free(pool);
}
@@ -589,3 +631,10 @@ void BLI_mempool_destroy(BLI_mempool *pool)
MEM_freeN(pool);
}
}
+
+#ifndef NDEBUG
+void BLI_mempool_set_memory_debug(void)
+{
+ mempool_debug_memset = true;
+}
+#endif
diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c
index 8707be46196..4b51aefbd87 100644
--- a/source/blender/blenlib/intern/boxpack2d.c
+++ b/source/blender/blenlib/intern/boxpack2d.c
@@ -31,14 +31,19 @@
#include "BLI_boxpack2d.h" /* own include */
+#ifdef __GNUC__
+# pragma GCC diagnostic error "-Wpadded"
+#endif
+
/* BoxPacker for backing 2D rectangles into a square
*
* The defined Below are for internal use only */
-
typedef struct BoxVert {
float x;
float y;
- short free;
+
+ int free; /* could be a char */
+ unsigned int index;
struct BoxPack *trb; /* top right box */
struct BoxPack *blb; /* bottom left box */
@@ -48,8 +53,6 @@ typedef struct BoxVert {
/* Store last intersecting boxes here
* speedup intersection testing */
struct BoxPack *isect_cache[4];
-
- int index;
} BoxVert;
/* free vert flags */
@@ -156,13 +159,15 @@ static int vertex_sort(const void *p1, const void *p2)
* len - the number of boxes in the array.
* tot_width and tot_height are set so you can normalize the data.
* */
-void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *tot_height)
+void BLI_box_pack_2d(BoxPack *boxarray, const unsigned int len, float *tot_width, float *tot_height)
{
- BoxVert *vert; /* the current vert */
- int box_index, verts_pack_len, i, j, k, isect;
- int quad_flags[4] = {BLF, TRF, TLF, BRF}; /* use for looping */
+ const int quad_flags[4] = {BLF, TRF, TLF, BRF}; /* use for looping */
+ unsigned int box_index, verts_pack_len, i, j, k;
+ unsigned int *vertex_pack_indices; /* an array of indices used for sorting verts */
+ bool isect;
+
BoxPack *box, *box_test; /*current box and another for intersection tests*/
- int *vertex_pack_indices; /*an array of indices used for sorting verts*/
+ BoxVert *vert; /* the current vert */
if (!len) {
*tot_width = 0.0f;
@@ -184,7 +189,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *
vert->isect_cache[2] = vert->isect_cache[3] = NULL;
vert->free = CORNERFLAGS & ~TRF;
vert->trb = box;
- vert->index = i; i++;
+ vert->index = i++;
box->v[BL] = vert; vert++;
vert->trb = vert->brb = vert->tlb =
@@ -192,7 +197,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *
vert->isect_cache[2] = vert->isect_cache[3] = NULL;
vert->free = CORNERFLAGS & ~BLF;
vert->blb = box;
- vert->index = i; i++;
+ vert->index = i++;
box->v[TR] = vert; vert++;
vert->trb = vert->blb = vert->tlb =
@@ -200,7 +205,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *
vert->isect_cache[2] = vert->isect_cache[3] = NULL;
vert->free = CORNERFLAGS & ~BRF;
vert->brb = box;
- vert->index = i; i++;
+ vert->index = i++;
box->v[TL] = vert; vert++;
vert->trb = vert->blb = vert->brb =
@@ -208,7 +213,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *
vert->isect_cache[2] = vert->isect_cache[3] = NULL;
vert->free = CORNERFLAGS & ~TLF;
vert->tlb = box;
- vert->index = i; i++;
+ vert->index = i++;
box->v[BR] = vert; vert++;
}
vert = NULL;
@@ -247,7 +252,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *
/* Pack the box in with the others */
/* sort the verts */
- isect = 1;
+ isect = true;
for (i = 0; i < verts_pack_len && isect; i++) {
vert = vertarray + vertex_pack_indices[i];
@@ -283,7 +288,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *
/* Now we need to check that the box intersects
* with any other boxes
* Assume no intersection... */
- isect = 0;
+ isect = false;
if ( /* Constrain boxes to positive X/Y values */
BOXLEFT(box) < 0.0f || BOXBOTTOM(box) < 0.0f ||
@@ -296,7 +301,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *
* isect_cache that can store a pointer to a
* box for each quadrant
* big speedup */
- isect = 1;
+ isect = true;
}
else {
/* do a full search for colliding box
@@ -307,7 +312,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *
/* Store the last intersecting here as cache
* for faster checking next time around */
vert->isect_cache[j] = box_test;
- isect = 1;
+ isect = true;
break;
}
}
@@ -320,7 +325,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *
(*tot_height) = max_ff(BOXTOP(box), (*tot_height));
/* Place the box */
- vert->free &= (short)~quad_flags[j];
+ vert->free &= ~quad_flags[j];
switch (j) {
case TR:
diff --git a/source/blender/blenlib/intern/lasso.c b/source/blender/blenlib/intern/lasso.c
index 8e22d6f1182..e89f7fd795b 100644
--- a/source/blender/blenlib/intern/lasso.c
+++ b/source/blender/blenlib/intern/lasso.c
@@ -63,7 +63,7 @@ bool BLI_lasso_is_point_inside(const int mcords[][2], const unsigned int moves,
}
else {
int pt[2] = {sx, sy};
- return isect_point_poly_v2_int(pt, mcords, moves);
+ return isect_point_poly_v2_int(pt, mcords, moves, true);
}
}
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 65cfac86021..0d15eede9ea 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -712,7 +712,8 @@ int isect_line_sphere_v2(const float l1[2], const float l2[2],
}
/* point in polygon (keep float and int versions in sync) */
-bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr)
+bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr,
+ const bool use_holes)
{
/* we do the angle rule, define that all added angles should be about zero or (2 * PI) */
float angletot = 0.0;
@@ -749,9 +750,18 @@ bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsign
p1 = p2;
}
- return (fabsf(angletot) > 4.0f);
+ angletot = fabsf(angletot);
+ if (use_holes) {
+ const int nested = floorf((angletot / (float)(M_PI * 2.0)) + 0.00001f);
+ angletot -= nested * (float)(M_PI * 2.0);
+ return (angletot > 4.0f) != (nested % 2);
+ }
+ else {
+ return (angletot > 4.0f);
+ }
}
-bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr)
+bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr,
+ const bool use_holes)
{
/* we do the angle rule, define that all added angles should be about zero or (2 * PI) */
float angletot = 0.0;
@@ -788,7 +798,15 @@ bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsign
p1 = p2;
}
- return (fabsf(angletot) > 4.0f);
+ angletot = fabsf(angletot);
+ if (use_holes) {
+ const int nested = floorf((angletot / (float)(M_PI * 2.0)) + 0.00001f);
+ angletot -= nested * (float)(M_PI * 2.0);
+ return (angletot > 4.0f) != (nested % 2);
+ }
+ else {
+ return (angletot > 4.0f);
+ }
}
/* point in tri */
@@ -1979,6 +1997,59 @@ void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int
}
}
+void fill_poly_v2i_n(
+ const int xmin, const int ymin, const int xmax, const int ymax,
+ const int verts[][2], const int nr,
+ void (*callback)(int, int, void *), void *userData)
+{
+ /* originally by Darel Rex Finley, 2007 */
+
+ int nodes, pixel_y, i, j, swap;
+ int *node_x = MEM_mallocN(sizeof(*node_x) * (nr + 1), __func__);
+
+ /* Loop through the rows of the image. */
+ for (pixel_y = ymin; pixel_y < ymax; pixel_y++) {
+
+ /* Build a list of nodes. */
+ nodes = 0; j = nr - 1;
+ for (i = 0; i < nr; i++) {
+ if ((verts[i][1] < pixel_y && verts[j][1] >= pixel_y) ||
+ (verts[j][1] < pixel_y && verts[i][1] >= pixel_y))
+ {
+ node_x[nodes++] = (int)(verts[i][0] +
+ ((double)(pixel_y - verts[i][1]) / (verts[j][1] - verts[i][1])) *
+ (verts[j][0] - verts[i][0]));
+ }
+ j = i;
+ }
+
+ /* Sort the nodes, via a simple "Bubble" sort. */
+ i = 0;
+ while (i < nodes - 1) {
+ if (node_x[i] > node_x[i + 1]) {
+ SWAP_TVAL(swap, node_x[i], node_x[i + 1]);
+ if (i) i--;
+ }
+ else {
+ i++;
+ }
+ }
+
+ /* Fill the pixels between node pairs. */
+ for (i = 0; i < nodes; i += 2) {
+ if (node_x[i] >= xmax) break;
+ if (node_x[i + 1] > xmin) {
+ if (node_x[i ] < xmin) node_x[i ] = xmin;
+ if (node_x[i + 1] > xmax) node_x[i + 1] = xmax;
+ for (j = node_x[i]; j < node_x[i + 1]; j++) {
+ callback(j - xmin, pixel_y - ymin, userData);
+ }
+ }
+ }
+ }
+ MEM_freeN(node_x);
+}
+
/****************************** Axis Utils ********************************/
/**
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 6bac102e1b1..2eebe10dd58 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -286,7 +286,7 @@ void mat3_to_quat(float q[4], float wmat[3][3])
tr = 0.25 * (double)(1.0f + mat[0][0] + mat[1][1] + mat[2][2]);
- if (tr > (double)FLT_EPSILON) {
+ if (tr > (double)1e-4f) {
s = sqrt(tr);
q[0] = (float)s;
s = 1.0 / (4.0 * s);
@@ -300,7 +300,7 @@ void mat3_to_quat(float q[4], float wmat[3][3])
q[1] = (float)(0.25 * s);
s = 1.0 / s;
- q[0] = (float)((double)(mat[2][1] - mat[1][2]) * s);
+ q[0] = (float)((double)(mat[1][2] - mat[2][1]) * s);
q[2] = (float)((double)(mat[1][0] + mat[0][1]) * s);
q[3] = (float)((double)(mat[2][0] + mat[0][2]) * s);
}
@@ -318,7 +318,7 @@ void mat3_to_quat(float q[4], float wmat[3][3])
q[3] = (float)(0.25 * s);
s = 1.0 / s;
- q[0] = (float)((double)(mat[1][0] - mat[0][1]) * s);
+ q[0] = (float)((double)(mat[0][1] - mat[1][0]) * s);
q[1] = (float)((double)(mat[2][0] + mat[0][2]) * s);
q[2] = (float)((double)(mat[2][1] + mat[1][2]) * s);
}
diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c
index 2f94e833e9d..5b9fefe77bb 100644
--- a/source/blender/blenlib/intern/noise.c
+++ b/source/blender/blenlib/intern/noise.c
@@ -42,7 +42,7 @@
/* local */
static float noise3_perlin(float vec[3]);
-//static float turbulence_perlin(float *point, float lofreq, float hifreq);
+//static float turbulence_perlin(const float point[3], float lofreq, float hifreq);
//static float turbulencep(float noisesize, float x, float y, float z, int nr);
/* UNUSED */
@@ -50,7 +50,7 @@ static float noise3_perlin(float vec[3]);
/* needed for voronoi */
#define HASHPNT(x, y, z) hashpntf + 3 * hash[(hash[(hash[(z) & 255] + (y)) & 255] + (x)) & 255]
-static float hashpntf[768] = {
+static const float hashpntf[768] = {
0.536902, 0.020915, 0.501445, 0.216316, 0.517036, 0.822466, 0.965315,
0.377313, 0.678764, 0.744545, 0.097731, 0.396357, 0.247202, 0.520897,
0.613396, 0.542124, 0.146813, 0.255489, 0.810868, 0.638641, 0.980742,
@@ -163,7 +163,7 @@ static float hashpntf[768] = {
0.114246, 0.905043, 0.713870, 0.555261, 0.951333
};
-unsigned char hash[512] = {
+const unsigned char hash[512] = {
0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC,
0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63,
0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80,
@@ -194,7 +194,7 @@ unsigned char hash[512] = {
};
-float hashvectf[768] = {
+const float hashvectf[768] = {
0.33783, 0.715698, -0.611206, -0.944031, -0.326599, -0.045624, -0.101074, -0.416443, -0.903503, 0.799286, 0.49411,
-0.341949, -0.854645, 0.518036, 0.033936, 0.42514, -0.437866, -0.792114, -0.358948, 0.597046, 0.717377, -0.985413,
0.144714, 0.089294, -0.601776, -0.33728, -0.723907, -0.449921, 0.594513, 0.666382, 0.208313, -0.10791, 0.972076,
@@ -327,7 +327,8 @@ static float newPerlinU(float x, float y, float z)
/* Was BLI_hnoise(), removed noisesize, so other functions can call it without scaling. */
static float orgBlenderNoise(float x, float y, float z)
{
- register float cn1, cn2, cn3, cn4, cn5, cn6, i, *h;
+ register float cn1, cn2, cn3, cn4, cn5, cn6, i;
+ register const float *h;
float fx, fy, fz, ox, oy, oz, jx, jy, jz;
float n = 0.5;
int ix, iy, iz, b00, b01, b10, b11, b20, b21;
@@ -504,7 +505,7 @@ static const char p[512 + 2] = {
};
-static float g[512 + 2][3] = {
+static const float g[512 + 2][3] = {
{0.33783, 0.715698, -0.611206},
{-0.944031, -0.326599, -0.045624},
{-0.101074, -0.416443, -0.903503},
@@ -1034,7 +1035,8 @@ static float g[512 + 2][3] = {
static float noise3_perlin(float vec[3])
{
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
- float rx0, rx1, ry0, ry1, rz0, rz1, *q, sx, sy, sz, a, b, c, d, t, u, v;
+ float rx0, rx1, ry0, ry1, rz0, rz1, sx, sy, sz, a, b, c, d, t, u, v;
+ const float *q;
register int i, j;
@@ -1095,7 +1097,7 @@ static float noise3_perlin(float vec[3])
}
#if 0
-static float turbulence_perlin(float *point, float lofreq, float hifreq)
+static float turbulence_perlin(const float point[3], float lofreq, float hifreq)
{
float freq, t, p[3];
@@ -1227,7 +1229,7 @@ static float dist_Minkovsky(float x, float y, float z, float e)
void voronoi(float x, float y, float z, float *da, float *pa, float me, int dtype)
{
int xx, yy, zz, xi, yi, zi;
- float xd, yd, zd, d, *p;
+ float xd, yd, zd, d;
float (*distfunc)(float, float, float, float);
switch (dtype) {
@@ -1262,7 +1264,7 @@ void voronoi(float x, float y, float z, float *da, float *pa, float me, int dtyp
for (xx = xi - 1; xx <= xi + 1; xx++) {
for (yy = yi - 1; yy <= yi + 1; yy++) {
for (zz = zi - 1; zz <= zi + 1; zz++) {
- p = HASHPNT(xx, yy, zz);
+ const float *p = HASHPNT(xx, yy, zz);
xd = x - (p[0] + xx);
yd = y - (p[1] + yy);
zd = z - (p[2] + zz);
@@ -1416,7 +1418,7 @@ void cellNoiseV(float x, float y, float z, float *ca)
int xi = (int)(floor(x));
int yi = (int)(floor(y));
int zi = (int)(floor(z));
- float *p = HASHPNT(xi, yi, zi);
+ const float *p = HASHPNT(xi, yi, zi);
ca[0] = p[0];
ca[1] = p[1];
ca[2] = p[2];
diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c
index 19eb88f9e15..9790ce1f0b4 100644
--- a/source/blender/blenlib/intern/smallhash.c
+++ b/source/blender/blenlib/intern/smallhash.c
@@ -55,7 +55,7 @@
((h) + (((hoff) = ((hoff) * 2) + 1), (hoff))) \
)
-extern unsigned int hashsizes[];
+extern const unsigned int hashsizes[];
void BLI_smallhash_init(SmallHash *hash)
{
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
new file mode 100644
index 00000000000..7fa108b906f
--- /dev/null
+++ b/source/blender/blenlib/intern/task.c
@@ -0,0 +1,424 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_task.h"
+#include "BLI_threads.h"
+
+/* Types */
+
+typedef struct Task {
+ struct Task *next, *prev;
+
+ TaskRunFunction run;
+ void *taskdata;
+ bool free_taskdata;
+ TaskPool *pool;
+} Task;
+
+struct TaskPool {
+ TaskScheduler *scheduler;
+
+ volatile size_t num;
+ volatile size_t done;
+ ThreadMutex num_mutex;
+ ThreadCondition num_cond;
+
+ void *userdata;
+ ThreadMutex user_mutex;
+
+ volatile bool do_cancel;
+};
+
+struct TaskScheduler {
+ pthread_t *threads;
+ struct TaskThread *task_threads;
+ int num_threads;
+
+ ListBase queue;
+ ThreadMutex queue_mutex;
+ ThreadCondition queue_cond;
+
+ volatile bool do_exit;
+};
+
+typedef struct TaskThread {
+ TaskScheduler *scheduler;
+ int id;
+} TaskThread;
+
+/* Task Scheduler */
+
+static void task_pool_num_decrease(TaskPool *pool, size_t done)
+{
+ BLI_mutex_lock(&pool->num_mutex);
+
+ BLI_assert(pool->num >= done);
+
+ pool->num -= done;
+ pool->done += done;
+
+ if (pool->num == 0)
+ BLI_condition_notify_all(&pool->num_cond);
+
+ BLI_mutex_unlock(&pool->num_mutex);
+}
+
+static void task_pool_num_increase(TaskPool *pool)
+{
+ BLI_mutex_lock(&pool->num_mutex);
+
+ pool->num++;
+ BLI_condition_notify_all(&pool->num_cond);
+
+ BLI_mutex_unlock(&pool->num_mutex);
+}
+
+static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task)
+{
+ BLI_mutex_lock(&scheduler->queue_mutex);
+
+ while (!scheduler->queue.first && !scheduler->do_exit)
+ BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex);
+
+ if (!scheduler->queue.first) {
+ BLI_mutex_unlock(&scheduler->queue_mutex);
+ BLI_assert(scheduler->do_exit);
+ return false;
+ }
+
+ *task = scheduler->queue.first;
+ BLI_remlink(&scheduler->queue, *task);
+
+ BLI_mutex_unlock(&scheduler->queue_mutex);
+
+ return true;
+}
+
+static void *task_scheduler_thread_run(void *thread_p)
+{
+ TaskThread *thread = (TaskThread *) thread_p;
+ TaskScheduler *scheduler = thread->scheduler;
+ int thread_id = thread->id;
+ Task *task;
+
+ /* keep popping off tasks */
+ while (task_scheduler_thread_wait_pop(scheduler, &task)) {
+ TaskPool *pool = task->pool;
+
+ /* run task */
+ task->run(pool, task->taskdata, thread_id);
+
+ /* delete task */
+ if (task->free_taskdata)
+ MEM_freeN(task->taskdata);
+ MEM_freeN(task);
+
+ /* notify pool task was done */
+ task_pool_num_decrease(pool, 1);
+ }
+
+ return NULL;
+}
+
+TaskScheduler *BLI_task_scheduler_create(int num_threads)
+{
+ TaskScheduler *scheduler = MEM_callocN(sizeof(TaskScheduler), "TaskScheduler");
+
+ /* multiple places can use this task scheduler, sharing the same
+ * threads, so we keep track of the number of users. */
+ scheduler->do_exit = false;
+
+ scheduler->queue.first = scheduler->queue.last = NULL;
+ BLI_mutex_init(&scheduler->queue_mutex);
+ BLI_condition_init(&scheduler->queue_cond);
+
+ if (num_threads == 0) {
+ /* automatic number of threads will be main thread + num cores */
+ num_threads = BLI_system_thread_count();
+ }
+
+ /* main thread will also work, so we count it too */
+ num_threads -= 1;
+
+ /* launch threads that will be waiting for work */
+ if (num_threads > 0) {
+ int i;
+
+ scheduler->num_threads = num_threads;
+ scheduler->threads = MEM_callocN(sizeof(pthread_t) * num_threads, "TaskScheduler threads");
+ scheduler->task_threads = MEM_callocN(sizeof(TaskThread) * num_threads, "TaskScheduler task threads");
+
+ for (i = 0; i < num_threads; i++) {
+ TaskThread *thread = &scheduler->task_threads[i];
+ thread->scheduler = scheduler;
+ thread->id = i + 1;
+
+ if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) {
+ fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads);
+ MEM_freeN(thread);
+ }
+ }
+ }
+
+ return scheduler;
+}
+
+void BLI_task_scheduler_free(TaskScheduler *scheduler)
+{
+ Task *task;
+
+ /* stop all waiting threads */
+ BLI_mutex_lock(&scheduler->queue_mutex);
+ scheduler->do_exit = true;
+ BLI_condition_notify_all(&scheduler->queue_cond);
+ BLI_mutex_unlock(&scheduler->queue_mutex);
+
+ /* delete threads */
+ if (scheduler->threads) {
+ int i;
+
+ for (i = 0; i < scheduler->num_threads; i++) {
+ if (pthread_join(scheduler->threads[i], NULL) != 0)
+ fprintf(stderr, "TaskScheduler failed to join thread %d/%d\n", i, scheduler->num_threads);
+ }
+
+ MEM_freeN(scheduler->threads);
+ }
+
+ /* Delete task thread data */
+ if (scheduler->task_threads) {
+ MEM_freeN(scheduler->task_threads);
+ }
+
+ /* delete leftover tasks */
+ for (task = scheduler->queue.first; task; task = task->next) {
+ if (task->free_taskdata)
+ MEM_freeN(task->taskdata);
+ }
+ BLI_freelistN(&scheduler->queue);
+
+ /* delete mutex/condition */
+ BLI_mutex_end(&scheduler->queue_mutex);
+ BLI_condition_end(&scheduler->queue_cond);
+
+ MEM_freeN(scheduler);
+}
+
+int BLI_task_scheduler_num_threads(TaskScheduler *scheduler)
+{
+ return scheduler->num_threads + 1;
+}
+
+static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriority priority)
+{
+ task_pool_num_increase(task->pool);
+
+ /* add task to queue */
+ BLI_mutex_lock(&scheduler->queue_mutex);
+
+ if (priority == TASK_PRIORITY_HIGH)
+ BLI_addhead(&scheduler->queue, task);
+ else
+ BLI_addtail(&scheduler->queue, task);
+
+ BLI_condition_notify_one(&scheduler->queue_cond);
+ BLI_mutex_unlock(&scheduler->queue_mutex);
+}
+
+static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool)
+{
+ Task *task, *nexttask;
+ size_t done = 0;
+
+ BLI_mutex_lock(&scheduler->queue_mutex);
+
+ /* free all tasks from this pool from the queue */
+ for (task = scheduler->queue.first; task; task = nexttask) {
+ nexttask = task->next;
+
+ if (task->pool == pool) {
+ if (task->free_taskdata)
+ MEM_freeN(task->taskdata);
+ BLI_freelinkN(&scheduler->queue, task);
+
+ done++;
+ }
+ }
+
+ BLI_mutex_unlock(&scheduler->queue_mutex);
+
+ /* notify done */
+ task_pool_num_decrease(pool, done);
+}
+
+/* Task Pool */
+
+TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata)
+{
+ TaskPool *pool = MEM_callocN(sizeof(TaskPool), "TaskPool");
+
+ pool->scheduler = scheduler;
+ pool->num = 0;
+ pool->do_cancel = false;
+
+ BLI_mutex_init(&pool->num_mutex);
+ BLI_condition_init(&pool->num_cond);
+
+ pool->userdata = userdata;
+ BLI_mutex_init(&pool->user_mutex);
+
+ /* Ensure malloc will go fine from threads,
+ *
+ * This is needed because we could be in main thread here
+ * and malloc could be non-threda safe at this point because
+ * no other jobs are running.
+ */
+ BLI_begin_threaded_malloc();
+
+ return pool;
+}
+
+void BLI_task_pool_free(TaskPool *pool)
+{
+ BLI_task_pool_stop(pool);
+
+ BLI_mutex_end(&pool->num_mutex);
+ BLI_condition_end(&pool->num_cond);
+
+ BLI_mutex_end(&pool->user_mutex);
+
+ MEM_freeN(pool);
+
+ BLI_end_threaded_malloc();
+}
+
+void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run,
+ void *taskdata, bool free_taskdata, TaskPriority priority)
+{
+ Task *task = MEM_callocN(sizeof(Task), "Task");
+
+ task->run = run;
+ task->taskdata = taskdata;
+ task->free_taskdata = free_taskdata;
+ task->pool = pool;
+
+ task_scheduler_push(pool->scheduler, task, priority);
+}
+
+void BLI_task_pool_work_and_wait(TaskPool *pool)
+{
+ TaskScheduler *scheduler = pool->scheduler;
+
+ BLI_mutex_lock(&pool->num_mutex);
+
+ while (pool->num != 0) {
+ Task *task, *work_task = NULL;
+ bool found_task = false;
+
+ BLI_mutex_unlock(&pool->num_mutex);
+
+ BLI_mutex_lock(&scheduler->queue_mutex);
+
+ /* find task from this pool. if we get a task from another pool,
+ * we can get into deadlock */
+
+ for (task = scheduler->queue.first; task; task = task->next) {
+ if (task->pool == pool) {
+ work_task = task;
+ found_task = true;
+ BLI_remlink(&scheduler->queue, task);
+ break;
+ }
+ }
+
+ BLI_mutex_unlock(&scheduler->queue_mutex);
+
+ /* if found task, do it, otherwise wait until other tasks are done */
+ if (found_task) {
+ /* run task */
+ work_task->run(pool, work_task->taskdata, 0);
+
+ /* delete task */
+ if (work_task->free_taskdata)
+ MEM_freeN(work_task->taskdata);
+ MEM_freeN(work_task);
+
+ /* notify pool task was done */
+ task_pool_num_decrease(pool, 1);
+ }
+
+ BLI_mutex_lock(&pool->num_mutex);
+ if (pool->num == 0)
+ break;
+
+ if (!found_task)
+ BLI_condition_wait(&pool->num_cond, &pool->num_mutex);
+ }
+
+ BLI_mutex_unlock(&pool->num_mutex);
+}
+
+void BLI_task_pool_cancel(TaskPool *pool)
+{
+ pool->do_cancel = true;
+
+ task_scheduler_clear(pool->scheduler, pool);
+
+ /* wait until all entries are cleared */
+ BLI_mutex_lock(&pool->num_mutex);
+ while (pool->num)
+ BLI_condition_wait(&pool->num_cond, &pool->num_mutex);
+ BLI_mutex_unlock(&pool->num_mutex);
+
+ pool->do_cancel = false;
+}
+
+void BLI_task_pool_stop(TaskPool *pool)
+{
+ task_scheduler_clear(pool->scheduler, pool);
+
+ BLI_assert(pool->num == 0);
+}
+
+bool BLI_task_pool_cancelled(TaskPool *pool)
+{
+ return pool->do_cancel;
+}
+
+void *BLI_task_pool_userdata(TaskPool *pool)
+{
+ return pool->userdata;
+}
+
+ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool)
+{
+ return &pool->user_mutex;
+}
+
+size_t BLI_task_pool_tasks_done(TaskPool *pool)
+{
+ return pool->done;
+}
+
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index c8b84d9310a..64682965649 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -37,6 +37,7 @@
#include "BLI_listbase.h"
#include "BLI_gsqueue.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "PIL_time.h"
@@ -63,6 +64,9 @@ extern pthread_key_t gomp_tls_key;
static void *thread_tls_data;
#endif
+/* We're using one global task scheduler for all kind of tasks. */
+static TaskScheduler *task_scheduler = NULL;
+
/* ********** basic thread control API ************
*
* Many thread cases have an X amount of jobs, and only an Y amount of
@@ -151,9 +155,26 @@ void BLI_threadapi_init(void)
void BLI_threadapi_exit(void)
{
+ if (task_scheduler) {
+ BLI_task_scheduler_free(task_scheduler);
+ }
BLI_spin_end(&_malloc_lock);
}
+TaskScheduler *BLI_task_scheduler_get(void)
+{
+ if (task_scheduler == NULL) {
+ int tot_thread = BLI_system_thread_count();
+
+ /* Do a lazy initialization, so it happes after
+ * command line arguments parsing
+ */
+ task_scheduler = BLI_task_scheduler_create(tot_thread);
+ }
+
+ return task_scheduler;
+}
+
/* tot = 0 only initializes malloc mutex in a safe way (see sequence.c)
* problem otherwise: scene render will kill of the mutex!
*/
@@ -419,6 +440,11 @@ void BLI_mutex_unlock(ThreadMutex *mutex)
pthread_mutex_unlock(mutex);
}
+bool BLI_mutex_trylock(ThreadMutex *mutex)
+{
+ return (pthread_mutex_trylock(mutex) == 0);
+}
+
void BLI_mutex_end(ThreadMutex *mutex)
{
pthread_mutex_destroy(mutex);
@@ -563,97 +589,31 @@ void BLI_ticket_mutex_unlock(TicketMutex *ticket)
/* ************************************************ */
-typedef struct ThreadedWorker {
- ListBase threadbase;
- void *(*work_fnct)(void *);
- char busy[RE_MAX_THREAD];
- int total;
- int sleep_time;
-} ThreadedWorker;
-
-typedef struct WorkParam {
- ThreadedWorker *worker;
- void *param;
- int index;
-} WorkParam;
+/* Condition */
-static void *exec_work_fnct(void *v_param)
+void BLI_condition_init(ThreadCondition *cond)
{
- WorkParam *p = (WorkParam *)v_param;
- void *value;
-
- value = p->worker->work_fnct(p->param);
-
- p->worker->busy[p->index] = 0;
- MEM_freeN(p);
-
- return value;
+ pthread_cond_init(cond, NULL);
}
-ThreadedWorker *BLI_create_worker(void *(*do_thread)(void *), int tot, int sleep_time)
+void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
{
- ThreadedWorker *worker;
-
- (void)sleep_time; /* unused */
-
- worker = MEM_callocN(sizeof(ThreadedWorker), "threadedworker");
-
- if (tot > RE_MAX_THREAD) {
- tot = RE_MAX_THREAD;
- }
- else if (tot < 1) {
- tot = 1;
- }
-
- worker->total = tot;
- worker->work_fnct = do_thread;
-
- BLI_init_threads(&worker->threadbase, exec_work_fnct, tot);
-
- return worker;
+ pthread_cond_wait(cond, mutex);
}
-void BLI_end_worker(ThreadedWorker *worker)
+void BLI_condition_notify_one(ThreadCondition *cond)
{
- BLI_remove_threads(&worker->threadbase);
+ pthread_cond_signal(cond);
}
-void BLI_destroy_worker(ThreadedWorker *worker)
+void BLI_condition_notify_all(ThreadCondition *cond)
{
- BLI_end_worker(worker);
- BLI_freelistN(&worker->threadbase);
- MEM_freeN(worker);
+ pthread_cond_broadcast(cond);
}
-void BLI_insert_work(ThreadedWorker *worker, void *param)
+void BLI_condition_end(ThreadCondition *cond)
{
- WorkParam *p = MEM_callocN(sizeof(WorkParam), "workparam");
- int index;
-
- if (BLI_available_threads(&worker->threadbase) == 0) {
- index = worker->total;
- while (index == worker->total) {
- PIL_sleep_ms(worker->sleep_time);
-
- for (index = 0; index < worker->total; index++) {
- if (worker->busy[index] == 0) {
- BLI_remove_thread_index(&worker->threadbase, index);
- break;
- }
- }
- }
- }
- else {
- index = BLI_available_thread_index(&worker->threadbase);
- }
-
- worker->busy[index] = 1;
-
- p->param = param;
- p->index = index;
- p->worker = worker;
-
- BLI_insert_thread(&worker->threadbase, p);
+ pthread_cond_destroy(cond);
}
/* ************************************************ */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index d3b2e382388..40d442f4e0b 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1776,6 +1776,27 @@ static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData
}
}
+#define IDP_DirectLinkGroup_OrFree(prop, switch_endian, fd) \
+ _IDP_DirectLinkGroup_OrFree(prop, switch_endian, fd, __func__)
+
+static void _IDP_DirectLinkGroup_OrFree(IDProperty **prop, int switch_endian, FileData *fd,
+ const char *caller_func_id)
+{
+ if (*prop) {
+ if ((*prop)->type == IDP_GROUP) {
+ IDP_DirectLinkGroup(*prop, switch_endian, fd);
+ }
+ else {
+ /* corrupt file! */
+ printf("%s: found non group data, freeing type %d!\n",
+ caller_func_id, (*prop)->type);
+ /* don't risk id, data's likely corrupt. */
+ // IDP_FreeProperty(*prop);
+ *prop = NULL;
+ }
+ }
+}
+
/* stub function */
static void IDP_LibLinkProperty(IDProperty *UNUSED(prop), int UNUSED(switch_endian), FileData *UNUSED(fd))
{
@@ -1788,9 +1809,8 @@ static void direct_link_id(FileData *fd, ID *id)
/*link direct data of ID properties*/
if (id->properties) {
id->properties = newdataadr(fd, id->properties);
- if (id->properties) { /* this case means the data was written incorrectly, it should not happen */
- IDP_DirectLinkProperty(id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- }
+ /* this case means the data was written incorrectly, it should not happen */
+ IDP_DirectLinkGroup_OrFree(&id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
}
@@ -2041,7 +2061,7 @@ static void direct_link_fmodifiers(FileData *fd, ListBase *list)
FMod_Python *data = (FMod_Python *)fcm->data;
data->prop = newdataadr(fd, data->prop);
- IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
break;
}
@@ -2596,8 +2616,7 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
static void direct_link_node_socket(FileData *fd, bNodeSocket *sock)
{
sock->prop = newdataadr(fd, sock->prop);
- if (sock->prop)
- IDP_DirectLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
sock->link = newdataadr(fd, sock->link);
sock->typeinfo = NULL;
@@ -2635,8 +2654,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
link_list(fd, &node->outputs);
node->prop = newdataadr(fd, node->prop);
- if (node->prop)
- IDP_DirectLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
link_list(fd, &node->internal_links);
for (link = node->internal_links.first; link; link = link->next) {
@@ -2794,8 +2812,7 @@ static void direct_link_constraints(FileData *fd, ListBase *lb)
link_list(fd, &data->targets);
data->prop = newdataadr(fd, data->prop);
- if (data->prop)
- IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
break;
}
case CONSTRAINT_TYPE_SPLINEIK:
@@ -2894,8 +2911,7 @@ static void direct_link_bones(FileData *fd, Bone *bone)
bone->parent = newdataadr(fd, bone->parent);
bone->prop = newdataadr(fd, bone->prop);
- if (bone->prop)
- IDP_DirectLinkProperty(bone->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&bone->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
bone->flag &= ~BONE_DRAW_ACTIVE;
@@ -4148,12 +4164,6 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
direct_link_customdata(fd, &mesh->fdata, mesh->totface);
direct_link_customdata(fd, &mesh->ldata, mesh->totloop);
direct_link_customdata(fd, &mesh->pdata, mesh->totpoly);
-
- if (mesh->mloopuv || mesh->mtpoly) {
- /* for now we have to ensure texpoly and mloopuv layers are aligned
- * in the future we may allow non-aligned layers */
- BKE_mesh_cd_validate(mesh);
- }
mesh->bb = NULL;
mesh->edit_btmesh = NULL;
@@ -4163,6 +4173,12 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
mesh->totselect = 0;
}
+ if (mesh->mloopuv || mesh->mtpoly) {
+ /* for now we have to ensure texpoly and mloopuv layers are aligned
+ * in the future we may allow non-aligned layers */
+ BKE_mesh_cd_validate(mesh);
+ }
+
/* Multires data */
mesh->mr= newdataadr(fd, mesh->mr);
if (mesh->mr) {
@@ -4534,8 +4550,7 @@ static void direct_link_pose(FileData *fd, bPose *pose)
direct_link_constraints(fd, &pchan->constraints);
pchan->prop = newdataadr(fd, pchan->prop);
- if (pchan->prop)
- IDP_DirectLinkProperty(pchan->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&pchan->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
pchan->mpath = newdataadr(fd, pchan->mpath);
if (pchan->mpath)
@@ -5438,10 +5453,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
}
if (sce->r.ffcodecdata.properties) {
sce->r.ffcodecdata.properties = newdataadr(fd, sce->r.ffcodecdata.properties);
- if (sce->r.ffcodecdata.properties) {
- IDP_DirectLinkProperty(sce->r.ffcodecdata.properties,
- (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- }
+ IDP_DirectLinkGroup_OrFree(&sce->r.ffcodecdata.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
link_list(fd, &(sce->markers));
@@ -6135,8 +6147,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
ui_list->type = NULL;
ui_list->dyn_data = NULL;
ui_list->properties = newdataadr(fd, ui_list->properties);
- if (ui_list->properties)
- IDP_DirectLinkProperty(ui_list->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&ui_list->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
if (spacetype == SPACE_EMPTY) {
@@ -9702,11 +9713,27 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
+
+ if (!MAIN_VERSION_ATLEAST(main, 269, 1)) {
+ /* Removal of Cycles SSS Compatible falloff */
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_SUBSURFACE_SCATTERING) {
+ if (node->custom1 == SHD_SUBSURFACE_COMPATIBLE) {
+ node->custom1 = SHD_SUBSURFACE_CUBIC;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
- /* don't forget to set version number in blender.c! */
+ /* don't forget to set version number in BKE_blender.h! */
}
#if 0 // XXX: disabled for now... we still don't have this in the right place in the loading code for it to work
@@ -9762,8 +9789,7 @@ static void lib_link_all(FileData *fd, Main *main)
static void direct_link_keymapitem(FileData *fd, wmKeyMapItem *kmi)
{
kmi->properties = newdataadr(fd, kmi->properties);
- if (kmi->properties)
- IDP_DirectLinkProperty(kmi->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&kmi->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
kmi->ptr = NULL;
kmi->flag &= ~KMI_UPDATE;
}
@@ -9820,9 +9846,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
for (addon = user->addons.first; addon; addon = addon->next) {
addon->prop = newdataadr(fd, addon->prop);
- if (addon->prop) {
- IDP_DirectLinkProperty(addon->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- }
+ IDP_DirectLinkGroup_OrFree(&addon->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
// XXX
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index f32215dbf03..067a8629906 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -1994,15 +1994,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
while (sce) {
if (sce->toolsettings == NULL) {
sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct");
- sce->toolsettings->cornertype =0;
- sce->toolsettings->degr = 90;
- sce->toolsettings->step = 9;
- sce->toolsettings->turn = 1;
- sce->toolsettings->extr_offs = 1;
sce->toolsettings->doublimit = 0.001f;
- sce->toolsettings->segments = 32;
- sce->toolsettings->rings = 32;
- sce->toolsettings->vertices = 32;
}
sce = sce->id.next;
}
@@ -2149,9 +2141,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
for (; sce; sce = sce->id.next) {
- /* make 'innervert' the default subdivide type, for backwards compat */
- sce->toolsettings->cornertype = 1;
-
if (sce->r.scemode & R_PASSEPARTOUT) {
set_passepartout = 1;
sce->r.scemode &= ~R_PASSEPARTOUT;
@@ -2238,11 +2227,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
ntree_version_241(sce->nodetree);
/* uv calculation options moved to toolsettings */
- if (sce->toolsettings->uvcalc_radius == 0.0f) {
- sce->toolsettings->uvcalc_radius = 1.0f;
- sce->toolsettings->uvcalc_cubesize = 1.0f;
- sce->toolsettings->uvcalc_mapdir = 1;
- sce->toolsettings->uvcalc_mapalign = 1;
+ if (sce->toolsettings->unwrapper == 0) {
sce->toolsettings->uvcalc_flag = UVCALC_FILLHOLES;
sce->toolsettings->unwrapper = 1;
}
@@ -2343,8 +2328,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
for (sce = main->scene.first; sce; sce = sce->id.next) {
if (sce->toolsettings->select_thresh == 0.0f)
sce->toolsettings->select_thresh = 0.01f;
- if (sce->toolsettings->clean_thresh == 0.0f)
- sce->toolsettings->clean_thresh = 0.1f;
if (sce->r.threads == 0) {
if (sce->r.mode & R_THREADS)
@@ -2554,14 +2537,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
sce->r.bake_flag = R_BAKE_CLEAR;
}
}
-
- if (main->subversionfile < 5) {
- for (sce = main->scene.first; sce; sce = sce->id.next) {
- /* improved triangle to quad conversion settings */
- if (sce->toolsettings->jointrilimit == 0.0f)
- sce->toolsettings->jointrilimit = 0.8f;
- }
- }
}
if (main->versionfile <= 243) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index b8d0857449b..44dc98fe537 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1737,7 +1737,7 @@ static void write_grid_paint_mask(WriteData *wd, int count, GridPaintMask *grid_
for (i = 0; i < count; ++i) {
GridPaintMask *gpm = &grid_paint_mask[i];
if (gpm->data) {
- const int gridsize = ccg_gridsize(gpm->level);
+ const int gridsize = BKE_ccg_gridsize(gpm->level);
writedata(wd, DATA,
sizeof(*gpm->data) * gridsize * gridsize,
gpm->data);
@@ -1809,7 +1809,7 @@ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data,
CustomData_free(&data_tmp, count);
}
-static void write_meshs(WriteData *wd, ListBase *idbase)
+static void write_meshes(WriteData *wd, ListBase *idbase)
{
Mesh *mesh;
int save_for_old_blender= 0;
@@ -3367,7 +3367,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
write_objects (wd, &mainvar->object);
write_materials(wd, &mainvar->mat);
write_textures (wd, &mainvar->tex);
- write_meshs (wd, &mainvar->mesh);
+ write_meshes (wd, &mainvar->mesh);
write_particlesettings(wd, &mainvar->particle);
write_nodetrees(wd, &mainvar->nodetree);
write_brushes (wd, &mainvar->brush);
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index 930964667e9..1a7464ce340 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -500,10 +500,10 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len,
*/
void BMO_remove_tagged_faces(BMesh *bm, const short oflag)
{
- BMFace *f;
+ BMFace *f, *f_next;
BMIter iter;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) {
if (BMO_elem_flag_test(bm, f, oflag)) {
BM_face_kill(bm, f);
}
@@ -512,10 +512,10 @@ void BMO_remove_tagged_faces(BMesh *bm, const short oflag)
void BMO_remove_tagged_edges(BMesh *bm, const short oflag)
{
- BMEdge *e;
+ BMEdge *e, *e_next;
BMIter iter;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
if (BMO_elem_flag_test(bm, e, oflag)) {
BM_edge_kill(bm, e);
}
@@ -524,10 +524,10 @@ void BMO_remove_tagged_edges(BMesh *bm, const short oflag)
void BMO_remove_tagged_verts(BMesh *bm, const short oflag)
{
- BMVert *v;
+ BMVert *v, *v_next;
BMIter iter;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, oflag)) {
BM_vert_kill(bm, v);
}
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 164a92125cd..8441a6ec75f 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -2279,3 +2279,28 @@ BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep)
BMLoop *l = BM_face_vert_share_loop(f_sep, v_sep);
return bmesh_urmv_loop(bm, l);
}
+
+/**
+ * Avoid calling this where possible,
+ * low level function so both face pointers remain intact but point to swapped data.
+ * \note must be from the same bmesh.
+ */
+void bmesh_face_swap_data(BMesh *bm, BMFace *f_a, BMFace *f_b)
+{
+ BMLoop *l_iter, *l_first;
+
+ BLI_assert(f_a != f_b);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
+ do {
+ l_iter->f = f_b;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_b);
+ do {
+ l_iter->f = f_a;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ SWAP(BMFace, (*f_a), (*f_b));
+ bm->elem_index_dirty |= BM_FACE;
+}
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index a18c2ebd32c..9e33509c2c8 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -87,4 +87,6 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep);
BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep);
+void bmesh_face_swap_data(BMesh *bm, BMFace *f_a, BMFace *f_b);
+
#endif /* __BMESH_CORE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index 4555de7b13d..91b9774634d 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -54,6 +54,32 @@ const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = {
};
/**
+ * Utility function.
+ */
+int BM_iter_mesh_count(BMesh *bm, const char itype)
+{
+ int count;
+
+ switch (itype) {
+ case BM_VERTS_OF_MESH:
+ count = bm->totvert;
+ break;
+ case BM_EDGES_OF_MESH:
+ count = bm->totedge;
+ break;
+ case BM_FACES_OF_MESH:
+ count = bm->totface;
+ break;
+ default:
+ count = 0;
+ BLI_assert(0);
+ break;
+ }
+
+ return count;
+}
+
+/**
* \note Use #BM_vert_at_index / #BM_edge_at_index / #BM_face_at_index for mesh arrays.
*/
void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
@@ -304,36 +330,66 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const
* VERT OF MESH CALLBACKS
*/
+/* see bug [#36923] for why we need this,
+ * allow adding but not removing, this isnt _totally_ safe since
+ * you could add/remove within the same loop, but catches common cases
+ */
+#ifdef DEBUG
+# define USE_IMMUTABLE_ASSERT
+#endif
+
void bmiter__vert_of_mesh_begin(struct BMIter__vert_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ ((BMIter *)iter)->count = iter->bm->totvert;
+#endif
BLI_mempool_iternew(iter->bm->vpool, &iter->pooliter);
}
void *bmiter__vert_of_mesh_step(struct BMIter__vert_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ BLI_assert(((BMIter *)iter)->count <= iter->bm->totvert);
+#endif
return BLI_mempool_iterstep(&iter->pooliter);
}
void bmiter__edge_of_mesh_begin(struct BMIter__edge_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ ((BMIter *)iter)->count = iter->bm->totedge;
+#endif
BLI_mempool_iternew(iter->bm->epool, &iter->pooliter);
}
void *bmiter__edge_of_mesh_step(struct BMIter__edge_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ BLI_assert(((BMIter *)iter)->count <= iter->bm->totedge);
+#endif
return BLI_mempool_iterstep(&iter->pooliter);
}
void bmiter__face_of_mesh_begin(struct BMIter__face_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ ((BMIter *)iter)->count = iter->bm->totface;
+#endif
BLI_mempool_iternew(iter->bm->fpool, &iter->pooliter);
}
void *bmiter__face_of_mesh_step(struct BMIter__face_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ BLI_assert(((BMIter *)iter)->count <= iter->bm->totface);
+#endif
return BLI_mempool_iterstep(&iter->pooliter);
}
+#ifdef USE_IMMUTABLE_ASSERT
+# undef USE_IMMUTABLE_ASSERT
+#endif
+
/*
* EDGE OF VERT CALLBACKS
*/
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index bb25d3fabd1..fdf0f27f05f 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -89,6 +89,20 @@ extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX];
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar) \
for (ele = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; ele; ele = BM_iter_step(iter), (indexvar)++)
+/* a version of BM_ITER_MESH which keeps the next item in storage
+ * so we can delete the current item, see bug [#36923] */
+#ifdef DEBUG
+# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
+ for (ele = BM_iter_new(iter, bm, itype, NULL); \
+ ele ? ((void)((iter)->count = BM_iter_mesh_count(bm, itype)), \
+ (void)(ele_next = BM_iter_step(iter)), 1) : 0; \
+ ele = ele_next)
+#else
+# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
+ for (ele = BM_iter_new(iter, bm, itype, NULL); ele ? ((ele_next = BM_iter_step(iter)), 1) : 0; ele = ele_next)
+#endif
+
+
#define BM_ITER_ELEM(ele, iter, data, itype) \
for (ele = BM_iter_new(iter, NULL, itype, data); ele; ele = BM_iter_step(iter))
@@ -182,6 +196,7 @@ typedef struct BMIter {
char itype;
} BMIter;
+int BM_iter_mesh_count(BMesh *bm, const char itype);
void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT;
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len);
void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 284ff3e759c..611ee4d03b8 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -1639,9 +1639,9 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
// BMOpDefine *def;
char *opname, *ofmt, *fmt;
char slot_name[64] = {0};
- int i /*, n = strlen(fmt) */, stop /*, slot_code = -1 */, type, state;
+ int i, type;
+ bool noslot, state;
char htype;
- int noslot = 0;
/* basic useful info to help find where bmop formatting strings fail */
@@ -1662,7 +1662,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
i = strcspn(fmt, " ");
opname = fmt;
- if (!opname[i]) noslot = 1;
+ noslot = (opname[i] == '\0');
opname[i] = '\0';
fmt += i + (noslot ? 0 : 1);
@@ -1679,7 +1679,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
// def = bmo_opdefines[i];
i = 0;
- state = 1; /* 0: not inside slot_code name, 1: inside slot_code name */
+ state = true; /* false: not inside slot_code name, true: inside slot_code name */
while (*fmt) {
if (state) {
@@ -1705,7 +1705,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
BLI_strncpy(slot_name, fmt, sizeof(slot_name));
- state = 0;
+ state = false;
fmt += i;
}
else {
@@ -1726,13 +1726,13 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
else GOTO_ERROR("matrix size was not 3 or 4");
BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size);
- state = 1;
+ state = true;
break;
}
case 'v':
{
BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *));
- state = 1;
+ state = true;
break;
}
case 'e': /* single vert/edge/face */
@@ -1742,7 +1742,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
BMO_slot_buffer_from_single(op, slot, ele);
- state = 1;
+ state = true;
break;
}
case 's':
@@ -1761,20 +1761,20 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
BMO_slot_copy(op_other, slots_out, slot_name_other,
op, slots_in, slot_name);
}
- state = 1;
+ state = true;
break;
}
case 'i':
BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int));
- state = 1;
+ state = true;
break;
case 'b':
BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int));
- state = 1;
+ state = true;
break;
case 'p':
BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *));
- state = 1;
+ state = true;
break;
case 'f':
case 'F':
@@ -1787,15 +1787,16 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double));
}
else {
+ bool stop = false;
+
htype = 0;
- stop = 0;
while (1) {
switch (NEXT_CHAR(fmt)) {
case 'f': htype |= BM_FACE; break;
case 'e': htype |= BM_EDGE; break;
case 'v': htype |= BM_VERT; break;
default:
- stop = 1;
+ stop = true;
break;
}
if (stop) {
@@ -1822,7 +1823,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
}
}
- state = 1;
+ state = true;
break;
default:
fprintf(stderr,
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 2492dce05c7..e4c1180d433 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -30,10 +30,9 @@
#include "DNA_listBase.h"
-#include "MEM_guardedalloc.h"
-
#include "BLI_alloca.h"
#include "BLI_math.h"
+#include "BLI_memarena.h"
#include "BLI_scanfill.h"
#include "BLI_listbase.h"
@@ -801,195 +800,6 @@ bool BM_face_point_inside_test(BMFace *f, const float co[3])
return crosses % 2 != 0;
}
-static bool bm_face_goodline(float const (*projectverts)[2], BMFace *f, int v1i, int v2i, int v3i)
-{
- BMLoop *l_iter;
- BMLoop *l_first;
-
- float pv1[2];
- const float *v1 = projectverts[v1i];
- const float *v2 = projectverts[v2i];
- const float *v3 = projectverts[v3i];
- int i;
-
- /* v3 must be on the left side of [v1, v2] line, else we know [v1, v3] is outside of f! */
- if (testedgesidef(v1, v2, v3)) {
- return false;
- }
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- i = BM_elem_index_get(l_iter->v);
- copy_v2_v2(pv1, projectverts[i]);
-
- if (ELEM3(i, v1i, v2i, v3i)) {
-#if 0
- printf("%d in (%d, %d, %d) tri (from indices!), continuing\n", i, v1i, v2i, v3i);
-#endif
- continue;
- }
-
- if (isect_point_tri_v2(pv1, v1, v2, v3) ||
- isect_point_tri_v2(pv1, v3, v2, v1))
- {
-#if 0
- if (isect_point_tri_v2(pv1, v1, v2, v3))
- printf("%d in (%d, %d, %d)\n", v3i, i, v1i, v2i);
- else
- printf("%d in (%d, %d, %d)\n", v1i, i, v3i, v2i);
-#endif
- return false;
- }
- } while ((l_iter = l_iter->next) != l_first);
- return true;
-}
-
-/**
- * \brief Find Ear
- *
- * Used by tessellator to find the next triangle to 'clip off' of a polygon while tessellating.
- *
- * \param f The face to search.
- * \param projectverts an array of face vert coords.
- * \param use_beauty Currently only applies to quads, can be extended later on.
- * \param abscoss Must be allocated by caller, and at least f->len length
- * (allow to avoid allocating a new one for each tri!).
- */
-static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use_beauty, float *abscoss)
-{
- BMLoop *bestear = NULL;
-
- BMLoop *l_iter;
- BMLoop *l_first;
-
- const float cos_threshold = 0.9f;
- const float bias = 1.0f + 1e-6f;
-
- BLI_assert(BM_face_is_normal_valid(f));
- /* just triangulate degenerate faces */
- if (UNLIKELY(is_zero_v3(f->no))) {
- return BM_FACE_FIRST_LOOP(f);
- }
-
- if (f->len == 4) {
- BMLoop *larr[4];
- int i = 0, i4;
- float cos1, cos2;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- larr[i] = l_iter;
- i++;
- } while ((l_iter = l_iter->next) != l_first);
-
- /* pick 0/1 based on best length */
- /* XXX Can't only rely on such test, also must check we do not get (too much) degenerated triangles!!! */
- i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) >
- len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty);
- i4 = (i + 3) % 4;
- /* Check produced tris aren't too flat/narrow...
- * Probably not the best test, but is quite efficient and should at least avoid null-area faces! */
- cos1 = fabsf(cos_v3v3v3(larr[i4]->v->co, larr[i]->v->co, larr[i + 1]->v->co));
- cos2 = fabsf(cos_v3v3v3(larr[i4]->v->co, larr[i + 2]->v->co, larr[i + 1]->v->co));
-#if 0
- printf("%d, (%f, %f), (%f, %f)\n", i, cos1, cos2,
- fabsf(cos_v3v3v3(larr[i]->v->co, larr[i4]->v->co, larr[i + 2]->v->co)),
- fabsf(cos_v3v3v3(larr[i]->v->co, larr[i + 1]->v->co, larr[i + 2]->v->co)));
-#endif
- if (cos1 < cos2)
- cos1 = cos2;
-
- if (cos1 > cos_threshold) {
- if (cos1 > fabsf(cos_v3v3v3(larr[i]->v->co, larr[i4]->v->co, larr[i + 2]->v->co)) &&
- cos1 > fabsf(cos_v3v3v3(larr[i]->v->co, larr[i + 1]->v->co, larr[i + 2]->v->co)))
- {
- i = !i;
- }
- }
- /* Last check we do not get overlapping triangles
- * (as much as possible, there are some cases with no good solution!) */
- i4 = (i + 3) % 4;
- if (!bm_face_goodline((float const (*)[2])projectverts, f,
- BM_elem_index_get(larr[i4]->v),
- BM_elem_index_get(larr[i]->v),
- BM_elem_index_get(larr[i + 1]->v)))
- {
- i = !i;
- }
-/* printf("%d\n", i);*/
- bestear = larr[i];
-
- }
- else {
- /* float angle, bestangle = 180.0f; */
- const int len = f->len;
- float cos, cos_best = 1.0f;
- int i, j;
-
- /* Compute cos of all corners! */
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const BMVert *v1 = l_iter->prev->v;
- const BMVert *v2 = l_iter->v;
- const BMVert *v3 = l_iter->next->v;
-
- abscoss[i] = fabsf(cos_v3v3v3(v1->co, v2->co, v3->co));
-/* printf("tcoss: %f\n", *tcoss);*/
- i++;
- } while ((l_iter = l_iter->next) != l_first);
-
- i = 0;
- l_iter = l_first;
- do {
- const BMVert *v1 = l_iter->prev->v;
- const BMVert *v2 = l_iter->v;
- const BMVert *v3 = l_iter->next->v;
-
- /* Compute highest cos (i.e. narrowest angle) of this tri. */
- cos = max_fff(abscoss[i],
- fabsf(cos_v3v3v3(v2->co, v3->co, v1->co)),
- fabsf(cos_v3v3v3(v3->co, v1->co, v2->co)));
-
- /* Compare to prev best (i.e. lowest) cos. */
- if (cos < cos_best) {
- if (bm_face_goodline((float const (*)[2])projectverts, f,
- BM_elem_index_get(v1),
- BM_elem_index_get(v2),
- BM_elem_index_get(v3)))
- {
- /* We must check this tri would not leave a (too much) degenerated remaining face! */
- /* For now just assume if the average of cos of all
- * "remaining face"'s corners is below a given threshold, it's OK. */
- float cos_mean = fabsf(cos_v3v3v3(v1->co, v3->co, l_iter->next->next->v->co));
- const int i_limit = (i - 1 + len) % len;
- cos_mean += fabsf(cos_v3v3v3(l_iter->prev->prev->v->co, v1->co, v3->co));
- j = (i + 2) % len;
- do {
- cos_mean += abscoss[j];
- } while ((j = (j + 1) % len) != i_limit);
- cos_mean /= len - 1;
-
- /* We need a best ear in any case... */
- if (cos_mean < cos_threshold || (!bestear && cos_mean < 1.0f)) {
- /* OKI, keep this ear (corner...) as a potential best one! */
- bestear = l_iter;
- cos_best = cos;
- }
-#if 0
- else
- printf("Had a nice tri (higest cos of %f, current cos_best is %f), "
- "but average cos of all \"remaining face\"'s corners is too high (%f)!\n",
- cos, cos_best, cos_mean);
-#endif
- }
- }
- i++;
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- return bestear;
-}
-
/**
* \brief BMESH TRIANGULATE FACE
*
@@ -1003,63 +813,126 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use
*
* \note use_tag tags new flags and edges.
*/
+#define SF_EDGE_IS_BOUNDARY 0xff
void BM_face_triangulate(BMesh *bm, BMFace *f,
BMFace **r_faces_new,
- const bool use_beauty, const bool use_tag)
+ MemArena *sf_arena,
+ const bool UNUSED(use_beauty), const bool use_tag)
{
- const float f_len_orig = f->len;
- int i, nf_i = 0;
- BMLoop *l_new;
- BMLoop *l_iter;
- BMLoop *l_first;
- /* BM_face_triangulate: temp absolute cosines of face corners */
- float (*projectverts)[2] = BLI_array_alloca(projectverts, f_len_orig);
- float *abscoss = BLI_array_alloca(abscoss, f_len_orig);
- float mat[3][3];
+ int nf_i = 0;
+ BMLoop *l_iter, *l_first, *l_new;
+ BMFace *f_new;
BLI_assert(BM_face_is_normal_valid(f));
- axis_dominant_v3_to_m3(mat, f->no);
- /* copy vertex coordinates to vertspace area */
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- mul_v2_m3v3(projectverts[i], mat, l_iter->v->co);
- BM_elem_index_set(l_iter->v, i++); /* set dirty! */
- } while ((l_iter = l_iter->next) != l_first);
+ if (f->len == 4) {
+ l_first = BM_FACE_FIRST_LOOP(f);
- bm->elem_index_dirty |= BM_VERT; /* see above */
+ f_new = BM_face_split(bm, f, l_first->v, l_first->next->next->v, &l_new, NULL, false);
+ copy_v3_v3(f_new->no, f->no);
- while (f->len > 3) {
- l_iter = poly_find_ear(f, projectverts, use_beauty, abscoss);
+ if (use_tag) {
+ BM_elem_flag_enable(l_new->e, BM_ELEM_TAG);
+ BM_elem_flag_enable(f_new, BM_ELEM_TAG);
+ }
- /* force triangulation - if we can't find an ear the face is degenerate */
- if (l_iter == NULL) {
- l_iter = BM_FACE_FIRST_LOOP(f);
+ if (r_faces_new) {
+ r_faces_new[nf_i++] = f_new;
}
+ }
+ else if (f->len > 4) {
+ /* scanfill */
+ ScanFillContext sf_ctx;
+ ScanFillVert *sf_vert, *sf_vert_prev = NULL;
+ ScanFillEdge *sf_edge;
+ ScanFillFace *sf_tri;
+ int totfilltri;
-/* printf("Subdividing face...\n");*/
- f = BM_face_split(bm, l_iter->f, l_iter->prev->v, l_iter->next->v, &l_new, NULL, true);
+ /* populate scanfill */
+ BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- if (UNLIKELY(!f)) {
- fprintf(stderr, "%s: triangulator failed to split face! (bmesh internal error)\n", __func__);
- break;
- }
+ /* step once before entering the loop */
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co);
+ sf_vert->tmp.p = l_iter;
+ sf_vert_prev = sf_vert;
+ l_iter = l_iter->next;
+
+ do {
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co);
+ sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_prev, sf_vert);
+ sf_edge->tmp.c = SF_EDGE_IS_BOUNDARY;
+
+ sf_vert->tmp.p = l_iter;
+ sf_vert_prev = sf_vert;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_prev, sf_ctx.fillvertbase.first);
+ sf_edge->tmp.c = SF_EDGE_IS_BOUNDARY;
+
+ /* calculate filled triangles */
+ totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, f->no);
+ BLI_assert(totfilltri <= f->len - 2);
- copy_v3_v3(f->no, l_iter->f->no);
+
+ /* loop over calculated triangles and create new geometry */
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ /* the order is reverse, otherwise the normal is flipped */
+ BMLoop *l_tri[3] = {
+ sf_tri->v3->tmp.p,
+ sf_tri->v2->tmp.p,
+ sf_tri->v1->tmp.p};
+
+ BMVert *v_tri[3] = {
+ l_tri[0]->v,
+ l_tri[1]->v,
+ l_tri[2]->v};
+
+ f_new = BM_face_create_verts(bm, v_tri, 3, f, false, true);
+ l_new = BM_FACE_FIRST_LOOP(f_new);
+
+ BLI_assert(v_tri[0] == l_new->v);
+
+ /* copy CD data */
+ BM_elem_attrs_copy(bm, bm, l_tri[0], l_new);
+ BM_elem_attrs_copy(bm, bm, l_tri[1], l_new->next);
+ BM_elem_attrs_copy(bm, bm, l_tri[2], l_new->prev);
+
+ /* add all but the last face which is swapped and removed (below) */
+ if (sf_tri->next) {
+ if (use_tag) {
+ BM_elem_flag_enable(f_new, BM_ELEM_TAG);
+ }
+ if (r_faces_new && sf_tri->next) {
+ r_faces_new[nf_i++] = f_new;
+ }
+ }
+ }
if (use_tag) {
- BM_elem_flag_enable(l_new->e, BM_ELEM_TAG);
- BM_elem_flag_enable(f, BM_ELEM_TAG);
+ ScanFillEdge *sf_edge;
+ for (sf_edge = sf_ctx.filledgebase.first; sf_edge; sf_edge = sf_edge->next) {
+ if (sf_edge->tmp.c != SF_EDGE_IS_BOUNDARY) {
+ BMLoop *l1 = sf_edge->v1->tmp.p;
+ BMLoop *l2 = sf_edge->v2->tmp.p;
+
+ BMEdge *e = BM_edge_exists(l1->v, l2->v);
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ }
}
- if (r_faces_new) {
- r_faces_new[nf_i++] = f;
+ if (sf_ctx.fillfacebase.first) {
+ /* we can't delete the real face, because some of the callers expect it to remain valid.
+ * so swap data and delete the last created tri */
+ bmesh_face_swap_data(bm, f, f_new);
+ BM_face_kill(bm, f_new);
}
- }
- BLI_assert(f->len == 3);
+ /* garbage collection */
+ BLI_scanfill_end_arena(&sf_ctx, sf_arena);
+ }
}
/**
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index 14fe1e76360..b7117621273 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -53,6 +53,7 @@ void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL();
bool BM_face_point_inside_test(BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BM_face_triangulate(BMesh *bm, BMFace *f, BMFace **newfaces,
+ struct MemArena *sf_arena,
const bool use_beauty, const bool use_tag) ATTR_NONNULL(1, 2);
void BM_face_legal_splits(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index a68d9ccd2bc..238b7b4aaaa 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_impl.c
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -26,6 +26,8 @@
* BMesh Walker Code.
*/
+#include <string.h>
+
#include "BLI_utildefines.h"
#include "BKE_customdata.h"
@@ -34,6 +36,12 @@
#include "intern/bmesh_private.h"
#include "intern/bmesh_walkers_private.h"
+/* pop into stack memory (common operation) */
+#define BMW_state_remove_r(walker, owalk) { \
+ memcpy(owalk, BMW_current_state(walker), sizeof(*(owalk))); \
+ BMW_state_remove(walker); \
+} (void)0
+
static bool bmw_mask_check_vert(BMWalker *walker, BMVert *v)
{
if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
@@ -140,14 +148,16 @@ static void *bmw_ShellWalker_yield(BMWalker *walker)
static void *bmw_ShellWalker_step(BMWalker *walker)
{
- BMwShellWalker *swalk = BMW_current_state(walker);
+ BMwShellWalker *swalk, owalk;
BMEdge *e, *e2;
BMVert *v;
BMIter iter;
int i;
+ BMW_state_remove_r(walker, &owalk);
+ swalk = &owalk;
+
e = swalk->curedge;
- BMW_state_remove(walker);
for (i = 0; i < 2; i++) {
v = i ? e->v2 : e->v1;
@@ -240,14 +250,15 @@ static void *bmw_ConnectedVertexWalker_yield(BMWalker *walker)
static void *bmw_ConnectedVertexWalker_step(BMWalker *walker)
{
- BMwConnectedVertexWalker *vwalk = BMW_current_state(walker);
+ BMwConnectedVertexWalker *vwalk, owalk;
BMVert *v, *v2;
BMEdge *e;
BMIter iter;
- v = vwalk->curvert;
+ BMW_state_remove_r(walker, &owalk);
+ vwalk = &owalk;
- BMW_state_remove(walker);
+ v = vwalk->curvert;
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
v2 = BM_edge_other_vert(e, v);
@@ -289,14 +300,19 @@ static void *bmw_IslandboundWalker_yield(BMWalker *walker)
static void *bmw_IslandboundWalker_step(BMWalker *walker)
{
- BMwIslandboundWalker *iwalk = BMW_current_state(walker), owalk;
+ BMwIslandboundWalker *iwalk, owalk;
BMVert *v;
- BMEdge *e = iwalk->curloop->e;
+ BMEdge *e;
BMFace *f;
- BMLoop *l = iwalk->curloop;
+ BMLoop *l;
/* int found = 0; */
- owalk = *iwalk;
+ memcpy(&owalk, BMW_current_state(walker), sizeof(owalk));
+ /* normally we'd remove here, but delay until after error checking */
+ iwalk = &owalk;
+
+ l = iwalk->curloop;
+ e = l->e;
v = BM_edge_other_vert(e, iwalk->lastv);
@@ -307,7 +323,7 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker)
return NULL;
}
- /* pop off current stat */
+ /* pop off current state */
BMW_state_remove(walker);
f = l->f;
@@ -381,13 +397,13 @@ static void *bmw_IslandWalker_yield(BMWalker *walker)
static void *bmw_IslandWalker_step(BMWalker *walker)
{
- BMwIslandWalker *iwalk = BMW_current_state(walker);
- /* BMwIslandWalker *owalk = iwalk; */ /* UNUSED */
+ BMwIslandWalker *iwalk, owalk;
BMIter iter, liter;
- BMFace *f, *curf = iwalk->cur;
+ BMFace *f;
BMLoop *l;
- BMW_state_remove(walker);
+ BMW_state_remove_r(walker, &owalk);
+ iwalk = &owalk;
l = BM_iter_new(&liter, walker->bm, BM_LOOPS_OF_FACE, iwalk->cur);
for ( ; l; l = BM_iter_step(&liter)) {
@@ -419,7 +435,7 @@ static void *bmw_IslandWalker_step(BMWalker *walker)
}
}
- return curf;
+ return owalk.cur;
}
@@ -507,15 +523,16 @@ static void *bmw_LoopWalker_yield(BMWalker *walker)
static void *bmw_LoopWalker_step(BMWalker *walker)
{
- BMwLoopWalker *lwalk = BMW_current_state(walker), owalk;
- BMEdge *e = lwalk->cur, *nexte = NULL;
+ BMwLoopWalker *lwalk, owalk;
+ BMEdge *e, *nexte = NULL;
BMLoop *l;
BMVert *v;
int i = 0;
- owalk = *lwalk;
- BMW_state_remove(walker);
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
+ e = lwalk->cur;
l = e->l;
if (owalk.f_hub) { /* NGON EDGE */
@@ -770,13 +787,15 @@ static void *bmw_FaceLoopWalker_yield(BMWalker *walker)
static void *bmw_FaceLoopWalker_step(BMWalker *walker)
{
- BMwFaceLoopWalker *lwalk = BMW_current_state(walker);
- BMFace *f = lwalk->l->f;
- BMLoop *l = lwalk->l, *origl = lwalk->l;
+ BMwFaceLoopWalker *lwalk, owalk;
+ BMFace *f;
+ BMLoop *l;
- BMW_state_remove(walker);
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
- l = l->radial_next;
+ f = lwalk->l->f;
+ l = lwalk->l->radial_next;
if (lwalk->no_calc) {
return f;
@@ -797,7 +816,7 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker)
if (l->f->len != 4) {
lwalk->no_calc = true;
- lwalk->l = origl;
+ lwalk->l = owalk.l;
}
else {
lwalk->no_calc = false;
@@ -878,19 +897,21 @@ static void *bmw_EdgeringWalker_yield(BMWalker *walker)
static void *bmw_EdgeringWalker_step(BMWalker *walker)
{
- BMwEdgeringWalker *lwalk = BMW_current_state(walker);
- BMEdge *e, *wireedge = lwalk->wireedge;
- BMLoop *l = lwalk->l, *origl = lwalk->l;
+ BMwEdgeringWalker *lwalk, owalk;
+ BMEdge *e;
+ BMLoop *l;
#ifdef BMW_EDGERING_NGON
int i, len;
#endif
#define EDGE_CHECK(e) (bmw_mask_check_edge(walker, e) && (BM_edge_is_boundary(e) || BM_edge_is_manifold(e)))
- BMW_state_remove(walker);
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
+ l = lwalk->l;
if (!l)
- return wireedge;
+ return lwalk->wireedge;
e = l->e;
if (!EDGE_CHECK(e)) {
@@ -913,7 +934,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker)
if ((len <= 0) || (len % 2 != 0) || !EDGE_CHECK(l->e) ||
!bmw_mask_check_face(walker, l->f))
{
- l = origl;
+ l = owalk.l;
i = len;
while (i > 0) {
l = l->next;
@@ -930,7 +951,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker)
l = l->next->next;
if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) {
- l = origl->next->next;
+ l = owalk.l->next->next;
}
/* only walk to manifold edge */
if ((l->f->len == 4) && EDGE_CHECK(l->e) &&
@@ -975,17 +996,18 @@ static void *bmw_UVEdgeWalker_yield(BMWalker *walker)
static void *bmw_UVEdgeWalker_step(BMWalker *walker)
{
- BMwUVEdgeWalker *lwalk = BMW_current_state(walker);
+ const int type = walker->bm->ldata.layers[walker->layer].type;
+ BMwUVEdgeWalker *lwalk, owalk;
BMLoop *l, *l2, *l3, *nl, *cl;
BMIter liter;
void *d1, *d2;
- int i, j, rlen, type;
+ int i, j, rlen;
+
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
l = lwalk->l;
nl = l->next;
- type = walker->bm->ldata.layers[walker->layer].type;
-
- BMW_state_remove(walker);
if (!bmw_mask_check_edge(walker, l->e)) {
return l;
diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c
index 9dfbf951fc0..10d15d93995 100644
--- a/source/blender/bmesh/operators/bmo_bridge.c
+++ b/source/blender/bmesh/operators/bmo_bridge.c
@@ -26,8 +26,6 @@
* Connect verts across faces (splits faces) and bridge tool.
*/
-#include "MEM_guardedalloc.h"
-
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index b3a42ba533e..d0f64eb2892 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -26,8 +26,6 @@
* Connect verts across faces (splits faces).
*/
-#include "MEM_guardedalloc.h"
-
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
diff --git a/source/blender/bmesh/operators/bmo_connect_nonplanar.c b/source/blender/bmesh/operators/bmo_connect_nonplanar.c
index 61085596acc..bd7a625406c 100644
--- a/source/blender/bmesh/operators/bmo_connect_nonplanar.c
+++ b/source/blender/bmesh/operators/bmo_connect_nonplanar.c
@@ -26,8 +26,6 @@
* Connect verts non-planer faces iteratively (splits faces).
*/
-#include "MEM_guardedalloc.h"
-
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index d3c7a6864c3..cf36e88ea98 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -37,14 +37,21 @@
#include "intern/bmesh_operators_private.h"
+/* ***_ISGC: mark for garbage-collection */
+
#define FACE_MARK 1
#define FACE_ORIG 2
#define FACE_NEW 4
+
#define EDGE_MARK 1
#define EDGE_TAG 2
+#define EDGE_ISGC 8
#define VERT_MARK 1
#define VERT_TAG 2
+#define VERT_ISGC 8
+
+
static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f)
{
@@ -232,14 +239,12 @@ cleanup:
void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
{
- /* might want to make this an option or mode - campbell */
-
/* BMOperator fop; */
BMFace *act_face = bm->act_face;
BMOIter eiter;
- BMEdge *e;
- BMIter viter;
- BMVert *v;
+ BMIter iter;
+ BMEdge *e, *e_next;
+ BMVert *v, *v_next;
const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
@@ -247,10 +252,10 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
if (use_face_split) {
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_TAG);
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- BMIter iter;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BMIter itersub;
int untag_count = 0;
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) {
if (!BMO_elem_flag_test(bm, e, EDGE_TAG)) {
untag_count++;
}
@@ -266,22 +271,34 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
}
if (use_verts) {
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
BMO_elem_flag_set(bm, v, VERT_MARK, (BM_vert_edge_count(v) != 2));
}
}
+ /* tag all verts/edges connected to faces */
BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) {
- BMFace *fa, *fb;
+ BMFace *f_pair[2];
+ if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) {
+ unsigned int j;
+ for (j = 0; j < 2; j++) {
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_pair[j]);
+ do {
+ BMO_elem_flag_enable(bm, l_iter->v, VERT_ISGC);
+ BMO_elem_flag_enable(bm, l_iter->e, EDGE_ISGC);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ }
+ BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) {
+ BMFace *fa, *fb;
if (BM_edge_face_pair(e, &fa, &fb)) {
BMFace *f_new;
/* join faces */
-
- /* BMESH_TODO - check on delaying edge removal since we may end up removing more than
- * one edge, and later reference a removed edge */
- f_new = BM_faces_join_pair(bm, fa, fb, e, true);
+ f_new = BM_faces_join_pair(bm, fa, fb, e, false);
if (f_new) {
/* maintain active face */
@@ -292,8 +309,23 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
}
}
+ /* Cleanup geometry (#BM_faces_join_pair, but it removes geometry we're looping on)
+ * so do this in a separate pass instead. */
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
+ if ((e->l == NULL) && BMO_elem_flag_test(bm, e, EDGE_ISGC)) {
+ BM_edge_kill(bm, e);
+ }
+ }
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if ((v->e == NULL) && BMO_elem_flag_test(bm, v, VERT_ISGC)) {
+ BM_vert_kill(bm, v);
+ }
+ }
+ /* done with cleanup */
+
+
if (use_verts) {
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
if (BM_vert_edge_count(v) == 2) {
BM_vert_collapse_edge(bm, v->e, v, true);
@@ -349,7 +381,7 @@ static bool test_extra_verts(BMesh *bm, BMVert *v)
void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
{
BMIter iter, fiter;
- BMVert *v;
+ BMVert *v, *v_next;
BMFace *f;
const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
@@ -361,7 +393,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
bm_face_split(bm, VERT_MARK);
}
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
/* check if it's a two-valence ver */
if (BM_vert_edge_count(v) == 2) {
@@ -409,7 +441,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
}
/* clean up any remainin */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
if (!BM_vert_dissolve(bm, v)) {
BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, NULL);
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index bd2485b92fb..a5c34f7623b 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -26,8 +26,6 @@
* Duplicate, Split, Split operators.
*/
-#include "MEM_guardedalloc.h"
-
#include "BLI_math.h"
#include "BLI_alloca.h"
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c
index c58a11f21ec..de41bc7937d 100644
--- a/source/blender/bmesh/operators/bmo_edgenet.c
+++ b/source/blender/bmesh/operators/bmo_edgenet.c
@@ -28,13 +28,8 @@
#include "MEM_guardedalloc.h"
-#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_array.h"
-#include "BLI_alloca.h"
-#include "BLI_smallhash.h"
-#include "BLI_rand.h"
-#include "BLI_heap.h"
#include "bmesh.h"
#include "bmesh_tools.h"
@@ -44,10 +39,7 @@
#define EDGE_MARK 1
#define EDGE_VIS 2
-#define FACE_NEW 1
-
#define ELE_NEW 1
-#define ELE_ORIG 4
void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
{
diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c
index f53b4536e44..fa77e6b509c 100644
--- a/source/blender/bmesh/operators/bmo_fill_attribute.c
+++ b/source/blender/bmesh/operators/bmo_fill_attribute.c
@@ -27,8 +27,6 @@
* Fill in geometry with the attributes of their adjacent data.
*/
-#include "MEM_guardedalloc.h"
-
#include "BLI_utildefines.h"
#include "BLI_linklist_stack.h"
diff --git a/source/blender/bmesh/operators/bmo_fill_holes.c b/source/blender/bmesh/operators/bmo_fill_holes.c
index 8160d28d7a7..eadfbdb1aa8 100644
--- a/source/blender/bmesh/operators/bmo_fill_holes.c
+++ b/source/blender/bmesh/operators/bmo_fill_holes.c
@@ -26,8 +26,6 @@
* Fill boundary edge loop(s) with faces.
*/
-#include "MEM_guardedalloc.h"
-
#include "BLI_utildefines.h"
#include "bmesh.h"
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index 20cd828af1e..e20556a830d 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -31,7 +31,6 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
-#include "BLI_array.h"
#include "BLI_alloca.h"
#include "BLI_memarena.h"
#include "BKE_customdata.h"
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index 6d4f257909c..6562f26062f 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -203,7 +203,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
BMIter iter;
BMOIter siter;
BMFace *f;
- BMEdge *e;
+ BMEdge *e, *e_next;
/* data: edge-to-join, sort_value: error weight */
struct SortPointerByFloat *jedges;
unsigned i, totedge;
@@ -291,7 +291,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
MEM_freeN(jedges);
/* join best weighted */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
BMFace *f_new;
BMFace *f_a, *f_b;
@@ -308,7 +308,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
}
/* join 2-tri islands */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
BMLoop *l_a, *l_b;
BMFace *f_a, *f_b;
@@ -326,7 +326,11 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
(BMO_elem_flag_test(bm, l_a->next->e, EDGE_MARK) == false) &&
(BMO_elem_flag_test(bm, l_a->prev->e, EDGE_MARK) == false) &&
(BMO_elem_flag_test(bm, l_b->next->e, EDGE_MARK) == false) &&
- (BMO_elem_flag_test(bm, l_b->prev->e, EDGE_MARK) == false))
+ (BMO_elem_flag_test(bm, l_b->prev->e, EDGE_MARK) == false) &&
+ /* check for faces that use same verts, this is supported but raises an error
+ * and cancels the operation when performed from editmode, since this is only
+ * two triangles we only need to compare a single vertex */
+ (LIKELY(l_a->prev->v != l_b->prev->v)))
{
BMFace *f_new;
f_new = BM_faces_join_pair(bm, f_a, f_b, e, true);
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index 45653f3411f..6a540928d43 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -36,7 +36,7 @@
/* ************************ primitives ******************* */
-static float icovert[12][3] = {
+static const float icovert[12][3] = {
{0.0f, 0.0f, -200.0f},
{144.72f, -105.144f, -89.443f},
{-55.277f, -170.128, -89.443f},
@@ -51,7 +51,7 @@ static float icovert[12][3] = {
{0.0f, 0.0f, 200.0f}
};
-static short icoface[20][3] = {
+static const short icoface[20][3] = {
{0, 1, 2},
{1, 0, 5},
{0, 2, 3},
@@ -78,10 +78,10 @@ static short icoface[20][3] = {
* this hack is only used so that scons & mingw + split-sources hack works
* ------------------------------- start copied code */
/* these are not the monkeys you are looking for */
-static int monkeyo = 4;
-static int monkeynv = 271;
-static int monkeynf = 250;
-static signed char monkeyv[271][3] = {
+static const int monkeyo = 4;
+static const int monkeynv = 271;
+static const int monkeynf = 250;
+static const signed char monkeyv[271][3] = {
{-71, 21, 98}, {-63, 12, 88}, {-57, 7, 74}, {-82, -3, 79}, {-82, 4, 92},
{-82, 17, 100}, {-92, 21, 102}, {-101, 12, 95}, {-107, 7, 83},
{-117, 31, 84}, {-109, 31, 95}, {-96, 31, 102}, {-92, 42, 102},
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index 5ab909ffb0c..cc5a635092a 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -354,7 +354,7 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
BMEdge *e, **edges = NULL;
BLI_array_declare(edges);
float min[3], max[3], center[3];
- int i, tot;
+ unsigned int i, tot;
BMOpSlot *slot_targetmap;
BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
@@ -369,6 +369,8 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
BMW_NIL_LAY);
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BMVert *v_tar;
+
if (!BMO_elem_flag_test(bm, e, EDGE_MARK))
continue;
@@ -381,19 +383,29 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
minmax_v3v3_v3(min, max, e->v1->co);
minmax_v3v3_v3(min, max, e->v2->co);
+
+ /* prevent adding to slot_targetmap multiple times */
+ BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
}
mid_v3_v3v3(center, min, max);
/* snap edges to a point. for initial testing purposes anyway */
+ v_tar = edges[0]->v1;
+
for (i = 0; i < tot; i++) {
- copy_v3_v3(edges[i]->v1->co, center);
- copy_v3_v3(edges[i]->v2->co, center);
-
- if (edges[i]->v1 != edges[0]->v1)
- BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v1, edges[0]->v1);
- if (edges[i]->v2 != edges[0]->v1)
- BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v2, edges[0]->v1);
+ unsigned int j;
+
+ for (j = 0; j < 2; j++) {
+ BMVert *v_src = *((&edges[i]->v1) + j);
+
+ copy_v3_v3(v_src->co, center);
+ if ((v_src != v_tar) && !BM_elem_flag_test(v_src, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(v_src, BM_ELEM_TAG);
+ BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_src, v_tar);
+ }
+ }
}
}
diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c
index 4b538dccb4e..5c1b4287c2f 100644
--- a/source/blender/bmesh/operators/bmo_symmetrize.c
+++ b/source/blender/bmesh/operators/bmo_symmetrize.c
@@ -26,9 +26,6 @@
* Makes the mesh symmetrical by splitting along an axis and duplicating the geometry.
*/
-
-#include "MEM_guardedalloc.h"
-
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -59,7 +56,7 @@ void bmo_symmetrize_exec(BMesh *bm, BMOperator *op)
copy_v3_fl(plane_no, 0.0f);
copy_v3_fl(scale, 1.0f);
- plane_no[axis] = direction > 2 ? 1.0f : -1.0f;
+ plane_no[axis] = direction > 2 ? -1.0f : 1.0f;
scale[axis] *= -1.0f;
/* Cut in half */
diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c
index 590b5ea97c4..ca45289520b 100644
--- a/source/blender/bmesh/operators/bmo_triangulate.c
+++ b/source/blender/bmesh/operators/bmo_triangulate.c
@@ -26,7 +26,6 @@
* Triangulate faces, also defines triangle fill.
*/
-#include "MEM_guardedalloc.h"
#include "DNA_listBase.h"
#include "BLI_math.h"
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index e23358bf4ff..c89fee71cbc 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -32,7 +32,6 @@
#include "DNA_meshdata_types.h"
#include "BLI_math.h"
-#include "BLI_heap.h"
#include "BLI_alloca.h"
#include "BKE_customdata.h"
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 1463b3155c0..bb3fe129e0b 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -1207,8 +1207,12 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
f = boundvert_rep_face(v);
f2 = boundvert_rep_face(v->next);
if (!v->any_seam) {
- for (ring = 1; ring < ns2; ring++)
- bev_merge_uvs(bm, mesh_vert(vm, i, ring, ns2)->v);
+ for (ring = 1; ring < ns2; ring++) {
+ BMVert *v_uv = mesh_vert(vm, i, ring, ns2)->v;
+ if (v_uv) {
+ bev_merge_uvs(bm, v_uv);
+ }
+ }
}
} while ((v = v->next) != vm->boundstart);
if (!bv->any_seam)
@@ -2371,7 +2375,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments,
const struct MDeformVert *dvert, const int vertex_group)
{
BMIter iter;
- BMVert *v;
+ BMVert *v, *v_next;
BMEdge *e;
BevelParams bp = {NULL};
@@ -2385,7 +2389,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments,
if (bp.offset > 0) {
/* primary alloc */
bp.vert_hash = BLI_ghash_ptr_new(__func__);
- bp.mem_arena = BLI_memarena_new((1 << 16), __func__);
+ bp.mem_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), __func__);
BLI_memarena_use_calloc(bp.mem_arena);
if (limit_offset)
@@ -2414,7 +2418,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments,
}
}
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
BLI_assert(find_bevvert(&bp, v) != NULL);
BM_vert_kill(bm, v);
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c
index 3baf8675a0d..9cfe17d6413 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.c
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c
@@ -39,7 +39,6 @@
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
-#include "BLI_mempool.h"
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
#include "BLI_math.h"
@@ -122,9 +121,6 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
l_first = BM_FACE_FIRST_LOOP(f);
- (void)bm;
- (void)plane;
-
/* add plane-aligned verts to the stack
* and check we have verts from both sides in this face,
* ... that the face doesn't only have boundry verts on the plane for eg. */
@@ -238,7 +234,7 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
face_verts_proj_2d[BM_VERT_LOOPINDEX(v_a)],
face_verts_proj_2d[BM_VERT_LOOPINDEX(v_b)]);
- if (isect_point_poly_v2(co_mid, (const float (*)[2])face_verts_proj_2d, f_len_orig)) {
+ if (isect_point_poly_v2(co_mid, (const float (*)[2])face_verts_proj_2d, f_len_orig, false)) {
BMLoop *l_a, *l_b;
bool found = false;
unsigned int j;
diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
index bc9288f98f6..868caa49ec7 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
@@ -197,7 +197,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool
}
for (iter_step = 0; iter_step < iterations; iter_step++) {
- BMVert *v;
+ BMVert *v, *v_next;
bool iter_done;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@@ -318,7 +318,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool
/* now we tagged all verts -1 for removal, lets loop over and rebuild faces */
iter_done = false;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) {
if (bm_vert_dissolve_fan(bm, v)) {
iter_done = true;
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c
index 2eacf62d68a..34ff493a026 100644
--- a/source/blender/bmesh/tools/bmesh_triangulate.c
+++ b/source/blender/bmesh/tools/bmesh_triangulate.c
@@ -31,6 +31,9 @@
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
+#include "BLI_memarena.h"
+#include "BLI_listbase.h"
+#include "BLI_scanfill.h"
#include "bmesh.h"
@@ -39,14 +42,14 @@
/**
* a version of #BM_face_triangulate that maps to #BMOpSlot
*/
-static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, const bool use_beauty, const bool use_tag,
+static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, MemArena *sf_arena, const bool use_beauty, const bool use_tag,
BMOperator *op, BMOpSlot *slot_facemap_out)
{
const int faces_array_tot = face->len - 3;
BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
BLI_assert(face->len > 3);
- BM_face_triangulate(bm, face, faces_array, use_beauty, use_tag);
+ BM_face_triangulate(bm, face, faces_array, sf_arena, use_beauty, use_tag);
if (faces_array) {
int i;
@@ -63,13 +66,16 @@ void BM_mesh_triangulate(BMesh *bm, const bool use_beauty, const bool tag_only,
{
BMIter iter;
BMFace *face;
+ MemArena *sf_arena;
+
+ sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
if (slot_facemap_out) {
/* same as below but call: bm_face_triangulate_mapping() */
BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
if (face->len > 3) {
if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
- bm_face_triangulate_mapping(bm, face, use_beauty, tag_only,
+ bm_face_triangulate_mapping(bm, face, sf_arena, use_beauty, tag_only,
op, slot_facemap_out);
}
}
@@ -79,9 +85,11 @@ void BM_mesh_triangulate(BMesh *bm, const bool use_beauty, const bool tag_only,
BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
if (face->len > 3) {
if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
- BM_face_triangulate(bm, face, NULL, use_beauty, tag_only);
+ BM_face_triangulate(bm, face, NULL, sf_arena, use_beauty, tag_only);
}
}
}
}
+
+ BLI_memarena_free(sf_arena);
}
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index bcbcdd42752..c1b6dc83139 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -963,10 +963,10 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
else
copy_m4_m4(mat, pchan->pose_mat);
- // SECOND_LIFE_COMPATIBILITY
+ // OPEN_SIM_COMPATIBILITY
// AFAIK animation to second life is via BVH, but no
// reason to not have the collada-animation be correct
- if (export_settings->second_life) {
+ if (export_settings->open_sim) {
float temp[4][4];
copy_m4_m4(temp, bone->arm_mat);
temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 438421ccd14..174331c4644 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -193,11 +193,11 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
// and not it's head, seems arbitrary.
(*i)->parentinv[3][1] += bone->length;
- // SECOND_LIFE_COMPATIBILITY
+ // OPEN_SIM_COMPATIBILITY
// TODO: when such objects are animated as
// single matrix the tweak must be applied
// to the result.
- if (export_settings->second_life) {
+ if (export_settings->open_sim) {
// tweak objects parentinverse to match compatibility
float temp[4][4];
@@ -272,8 +272,8 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW:
copy_m4_m4(mat, bone->arm_mat);
}
- // SECOND_LIFE_COMPATIBILITY
- if (export_settings->second_life) {
+ // OPEN_SIM_COMPATIBILITY
+ if (export_settings->open_sim) {
// Remove rotations vs armature from transform
// parent_rest_rot * mat * irest_rot
float temp[4][4];
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index d04ed8d6fa1..948a3dc5ae1 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -507,8 +507,8 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas
float world[4][4];
float inv_bind_mat[4][4];
- // SECOND_LIFE_COMPATIBILITY
- if (export_settings->second_life) {
+ // OPEN_SIM_COMPATIBILITY
+ if (export_settings->open_sim) {
// Only translations, no rotation vs armature
float temp[4][4];
unit_m4(temp);
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index f9eb4cbc26f..3dc7e74379e 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -50,7 +50,7 @@ public:
bool use_object_instantiation;
bool sort_by_name;
BC_export_transformation_type export_transformation_type;
- bool second_life;
+ bool open_sim;
char *filepath;
LinkNode *export_set;
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index 85bbaf4748f..223ab3eca2a 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -79,7 +79,7 @@ int collada_export(Scene *sce,
int use_object_instantiation,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int second_life)
+ int open_sim)
{
ExportSettings export_settings;
@@ -102,7 +102,7 @@ int collada_export(Scene *sce,
export_settings.use_object_instantiation = use_object_instantiation != 0;
export_settings.sort_by_name = sort_by_name != 0;
export_settings.export_transformation_type = export_transformation_type;
- export_settings.second_life = second_life != 0;
+ export_settings.open_sim = open_sim != 0;
int includeFilter = OB_REL_NONE;
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index b3a8156b6fe..e96bc2ea8a4 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -77,7 +77,7 @@ int collada_export(Scene *sce,
int use_object_instantiation,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int second_life);
+ int open_sim);
diff --git a/source/blender/collada/version.conf b/source/blender/collada/version.conf
new file mode 100644
index 00000000000..d39af7a53df
--- /dev/null
+++ b/source/blender/collada/version.conf
@@ -0,0 +1 @@
+463ba8a2ef5a021ce21df614dde29e0ee800e10b
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
index 4bebf004a89..f10e6696c6a 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
@@ -179,7 +179,7 @@ void MemoryBuffer::addPixel(int x, int y, const float color[4])
// table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2
// used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible
#define EWA_MAXIDX 255
-static float EWA_WTS[EWA_MAXIDX + 1] = {
+static const float EWA_WTS[EWA_MAXIDX + 1] = {
1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f,
0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f,
0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f,
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 041a2c2216e..09b6e7d2206 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -1546,7 +1546,9 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data
for (srl = sce->r.layers.first; srl; srl = srl->next) {
for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
- lineset->linestyle->id.flag |= LIB_DOIT;
+ if (lineset->linestyle) {
+ lineset->linestyle->id.flag |= LIB_DOIT;
+ }
}
}
@@ -1562,8 +1564,11 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
- if (!(linestyle->id.flag & LIB_DOIT))
+ if ((linestyle == NULL) ||
+ !(linestyle->id.flag & LIB_DOIT))
+ {
continue;
+ }
linestyle->id.flag &= ~LIB_DOIT;
/* add scene-level animation channels */
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 3c8576be312..34246427b7e 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -1380,7 +1380,7 @@ static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, const wm
RNA_string_set(op->ptr, "name", marker->name);
/* now see if the operator is usable */
- return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_props_popup);
+ return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_props_popup_confirm);
}
static void MARKER_OT_rename(wmOperatorType *ot)
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index decbc351cad..71717284d8e 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -396,7 +396,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
int filter;
/* when not in graph view, don't use handles */
SpaceIpo *sipo = (ac->spacetype == SPACE_IPO) ? (SpaceIpo *)ac->sl : NULL;
- const short use_handle = sipo ? !(sipo->flag & SIPO_NOHANDLES) : FALSE;
+ const bool use_handle = sipo ? !(sipo->flag & SIPO_NOHANDLES) : false;
/* filter animation data */
filter = ANIMFILTER_DATA_VISIBLE;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 70361f00004..6b9200afb75 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -61,6 +61,7 @@
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_main.h"
+#include "BKE_idcode.h"
#include "BKE_nla.h"
#include "BKE_global.h"
#include "BKE_context.h"
@@ -141,9 +142,18 @@ bAction *verify_adt_action(ID *id, short add)
/* init action if none available yet */
/* TODO: need some wizardry to handle NLA stuff correct */
if ((adt->action == NULL) && (add)) {
+ /* init action name from name of ID block */
char actname[sizeof(id->name) - 2];
BLI_snprintf(actname, sizeof(actname), "%sAction", id->name + 2);
+
+ /* create action */
adt->action = add_empty_action(G.main, actname);
+
+ /* set ID-type from ID-block that this is going to be assigned to
+ * so that users can't accidentally break actions by assigning them
+ * to the wrong places
+ */
+ adt->action->idroot = GS(id->name);
}
/* return the action */
@@ -996,6 +1006,34 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
* The flag argument is used for special settings that alter the behavior of
* the keyframe deletion. These include the quick refresh options.
*/
+
+
+
+/**
+ * \note caller needs to run #BKE_nla_tweakedit_remap to get NLA relative frame.
+ * caller should also check #BKE_fcurve_is_protected before keying.
+ */
+static bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra)
+{
+ bool found;
+ int i;
+
+ /* try to find index of beztriple to get rid of */
+ i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
+ if (found) {
+ /* delete the key at the index (will sanity check + do recalc afterwards) */
+ delete_fcurve_key(fcu, i, 1);
+
+ /* Only delete curve too if it won't be doing anything anymore */
+ if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
+ ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
+
+ /* return success */
+ return true;
+ }
+ return false;
+}
+
short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short UNUSED(flag))
{
AnimData *adt = BKE_animdata_from_id(id);
@@ -1055,32 +1093,20 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
/* will only loop once unless the array index was -1 */
for (; array_index < array_index_max; array_index++) {
FCurve *fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, 0);
- bool found;
- int i;
-
+
/* check if F-Curve exists and/or whether it can be edited */
if (fcu == NULL)
continue;
-
- if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) {
- if (G.debug & G_DEBUG)
- printf("WARNING: not deleting keyframe for locked F-Curve\n");
+
+ if (BKE_fcurve_is_protected(fcu)) {
+ BKE_reportf(reports, RPT_WARNING,
+ "not deleting keyframe for locked F-Curve '%s' for %s '%s'",
+ fcu->rna_path, BKE_idcode_to_name(GS(id->name)), id->name + 2);
continue;
}
-
- /* try to find index of beztriple to get rid of */
- i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
- if (found) {
- /* delete the key at the index (will sanity check + do recalc afterwards) */
- delete_fcurve_key(fcu, i, 1);
-
- /* Only delete curve too if it won't be doing anything anymore */
- if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
- ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
-
- /* return success */
- ret++;
- }
+
+ ret += delete_keyframe_fcurve(adt, fcu, cfra);
+
}
/* return success/failure */
@@ -1158,7 +1184,7 @@ static short clear_keyframe(ReportList *reports, ID *id, bAction *act, const cha
if (fcu == NULL)
continue;
- if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) {
+ if (BKE_fcurve_is_protected(fcu)) {
if (G.debug & G_DEBUG)
printf("WARNING: not deleting keyframe for locked F-Curve\n");
continue;
@@ -1537,14 +1563,22 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op)
AnimData *adt = ob->adt;
bAction *act = adt->action;
FCurve *fcu, *fcn;
+ const float cfra_unmap = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
for (fcu = act->curves.first; fcu; fcu = fcn) {
fcn = fcu->next;
-
+
+ if (BKE_fcurve_is_protected(fcu)) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "not deleting keyframe for locked F-Curve '%s', object '%s'",
+ fcu->rna_path, id->name + 2);
+ continue;
+ }
+
/* delete keyframes on current frame
* WARNING: this can delete the next F-Curve, hence the "fcn" copying
*/
- success += delete_keyframe(op->reports, id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0);
+ success += delete_keyframe_fcurve(adt, fcu, cfra_unmap);
}
}
diff --git a/source/blender/editors/armature/BIF_retarget.h b/source/blender/editors/armature/BIF_retarget.h
index 2ea0e0ab0d7..21e85b6fe89 100644
--- a/source/blender/editors/armature/BIF_retarget.h
+++ b/source/blender/editors/armature/BIF_retarget.h
@@ -29,6 +29,7 @@
#include "BLI_graph.h"
#include "BLI_ghash.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "reeb.h"
@@ -68,7 +69,8 @@ typedef struct RigGraph {
ReebGraph *link_mesh;
- struct ThreadedWorker *worker;
+ TaskScheduler *task_scheduler;
+ TaskPool *task_pool;
GHash *bones_map; /* map of editbones by name */
GHash *controls_map; /* map of rigcontrols by bone pointer */
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 1ee2dc80a97..8745d571a28 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -182,16 +182,22 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
if (ob->pose) {
bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname);
if (pchan) {
+ GHash *gh = ob->pose->chanhash;
+
+ /* remove the old hash entry, and replace with the new name */
+ if (gh) {
+ BLI_assert(BLI_ghash_haskey(gh, pchan->name));
+ BLI_ghash_remove(gh, pchan->name, NULL, NULL);
+ }
+
BLI_strncpy(pchan->name, newname, MAXBONENAME);
-
- if (ob->pose->chanhash) {
- GHash *gh = ob->pose->chanhash;
-
- /* remove the old hash entry, and replace with the new name */
- BLI_ghash_remove(gh, oldname, NULL, NULL);
+
+ if (gh) {
BLI_ghash_insert(gh, pchan->name, pchan);
}
}
+
+ BLI_assert(BKE_pose_channels_is_valid(ob->pose) == true);
}
/* Update any object constraints to use the new bone name */
@@ -294,9 +300,13 @@ static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
/* since we renamed stuff... */
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
+ /* copied from #rna_Bone_update_renamed */
+ /* redraw view */
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+
+ /* update animation channels */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, ob->data);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index 687455495a1..c03e7861307 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -83,7 +83,7 @@ static RigGraph *GLOBAL_RIGG = NULL;
/*******************************************************************************************************/
-void *exec_retargetArctoArc(void *param);
+void exec_retargetArctoArc(TaskPool *pool, void *taskdata, int threadid);
static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second);
float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4]);
@@ -235,9 +235,8 @@ void RIG_freeRigGraph(BGraph *rg)
BNode *node;
BArc *arc;
-#ifdef USE_THREADS
- BLI_destroy_worker(rigg->worker);
-#endif
+ BLI_task_pool_free(rigg->task_pool);
+ BLI_task_scheduler_free(rigg->task_scheduler);
if (rigg->link_mesh) {
REEB_freeGraph(rigg->link_mesh);
@@ -284,12 +283,14 @@ static RigGraph *newRigGraph(void)
rg->free_node = NULL;
#ifdef USE_THREADS
- //totthread = BKE_scene_num_threads(G.scene);
- totthread = BLI_system_thread_count();
-
- rg->worker = BLI_create_worker(exec_retargetArctoArc, totthread, 20); /* fix number of threads */
+ totthread = TASK_SCHEDULER_AUTO_THREADS;
+#else
+ totthread = TASK_SCHEDULER_SINGLE_THREAD;
#endif
-
+
+ rg->task_scheduler = BLI_task_scheduler_create(totthread);
+ rg->task_pool = BLI_task_pool_create(rg->task_scheduler, NULL);
+
return rg;
}
@@ -2133,7 +2134,6 @@ static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, Ri
static void retargetArctoArc(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
{
-#ifdef USE_THREADS
RetargetParam *p = MEM_callocN(sizeof(RetargetParam), "RetargetParam");
p->rigg = rigg;
@@ -2141,22 +2141,12 @@ static void retargetArctoArc(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode
p->inode_start = inode_start;
p->context = C;
- BLI_insert_work(rigg->worker, p);
-#else
- RetargetParam p;
-
- p.rigg = rigg;
- p.iarc = iarc;
- p.inode_start = inode_start;
- p.context = C;
-
- exec_retargetArctoArc(&p);
-#endif
+ BLI_task_pool_push(rigg->task_pool, exec_retargetArctoArc, p, true, TASK_PRIORITY_HIGH);
}
-void *exec_retargetArctoArc(void *param)
+void exec_retargetArctoArc(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
{
- RetargetParam *p = (RetargetParam *)param;
+ RetargetParam *p = (RetargetParam *)taskdata;
RigGraph *rigg = p->rigg;
RigArc *iarc = p->iarc;
bContext *C = p->context;
@@ -2183,12 +2173,6 @@ void *exec_retargetArctoArc(void *param)
retargetArctoArcLength(C, rigg, iarc, inode_start);
}
}
-
-#ifdef USE_THREADS
- MEM_freeN(p);
-#endif
-
- return NULL;
}
static void matchMultiResolutionNode(RigGraph *rigg, RigNode *inode, ReebNode *top_node)
@@ -2414,9 +2398,7 @@ static void retargetSubgraph(bContext *C, RigGraph *rigg, RigArc *start_arc, Rig
static void finishRetarget(RigGraph *rigg)
{
-#ifdef USE_THREADS
- BLI_end_worker(rigg->worker);
-#endif
+ BLI_task_pool_work_and_wait(rigg->task_pool);
}
static void adjustGraphs(bContext *C, RigGraph *rigg)
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index cb7a699b522..182f94b3693 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -638,7 +638,7 @@ static int poselib_rename_invoke(bContext *C, wmOperator *op, const wmEvent *eve
}
/* part to sync with other similar operators... */
- return WM_operator_props_popup(C, op, event);
+ return WM_operator_props_popup_confirm(C, op, event);
}
static int poselib_rename_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index 0bcb550b930..9b858a2c4e9 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -58,7 +58,7 @@
#include "curve_intern.h"
-static float nurbcircle[8][2] = {
+static const float nurbcircle[8][2] = {
{0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0, 1.0},
{0.0, 1.0}, { 1.0, 1.0}, { 1.0, 0.0}, { 1.0, -1.0}
};
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index b9759e16f20..ac9c338e431 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -981,7 +981,7 @@ void FONT_OT_move_select(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Move Select";
- ot->description = "Make selection from current cursor position to new cursor position type";
+ ot->description = "Move the cursor while selecting";
ot->idname = "FONT_OT_move_select";
/* api callbacks */
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 352a74cf172..dd1995a5428 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -221,8 +221,5 @@ void glaDrawImBuf_glsl(struct ImBuf *ibuf, float x, float y, int zoomfilter,
/* Draw imbuf on a screen, preferably using GLSL display transform */
void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter);
-/* Transform buffer from role to scene linear space using GLSL OCIO conversion */
-int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role);
-
#endif /* __BIF_GLUTIL_H__ */
diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h
index 3e2dbe255df..8da36f015dc 100644
--- a/source/blender/editors/include/ED_mask.h
+++ b/source/blender/editors/include/ED_mask.h
@@ -57,7 +57,7 @@ void ED_operatormacros_mask(void);
/* mask_draw.c */
void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type);
void ED_mask_draw_region(struct Mask *mask, struct ARegion *ar,
- const char draw_flag, const char draw_type,
+ const char draw_flag, const char draw_type, const char overlay_mode,
const int width_i, const int height_i,
const float aspx, const float aspy,
const short do_scale_applied, const short do_draw_cb,
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index b7fd181883b..5d3d72d0e3d 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -152,7 +152,7 @@ void EDBM_select_mirrored(struct BMEditMesh *em, bool extend,
void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag);
bool EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
-int EDBM_backbuf_check(unsigned int index);
+bool EDBM_backbuf_check(unsigned int index);
void EDBM_backbuf_free(void);
bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2], short tot,
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index bdfbbbb9c74..518bee665ae 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -40,6 +40,7 @@ struct Scene;
struct ScrArea;
struct RegionView3D;
struct RenderEngine;
+struct View3D;
/* render_ops.c */
@@ -51,6 +52,7 @@ void ED_render_id_flush_update(struct Main *bmain, struct ID *id);
void ED_render_engine_changed(struct Main *bmain);
void ED_render_engine_area_exit(struct ScrArea *sa);
void ED_render_scene_update(struct Main *bmain, struct Scene *scene, int updated);
+void ED_render_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa);
void ED_viewport_render_kill_jobs(const struct bContext *C, bool free_database);
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 81308dd84f2..eff79b6a039 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -103,7 +103,7 @@ enum TfmMode {
* returns 1 if successful, 0 otherwise (usually means there's no selection)
* (if 0 is returns, *vec is unmodified)
* */
-int calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], int cent2d[2]);
+int calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], float cent2d[2]);
struct TransInfo;
struct ScrArea;
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index ce9d3af3013..86abf29c308 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -336,4 +336,7 @@ void ED_view3d_operator_properties_viewmat_set(struct bContext *C, struct wmOper
void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx, int *winy, float persmat[4][4]);
#endif
+/* render */
+void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa);
+
#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index a8b8765a5c6..e13517adbb3 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -40,6 +40,7 @@ set(SRC
interface.c
interface_anim.c
interface_draw.c
+ interface_eyedropper.c
interface_handlers.c
interface_icons.c
interface_layout.c
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index e02cdf018c0..3bad2577409 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -611,6 +611,9 @@ static void ui_but_update_linklines(uiBlock *block, uiBut *oldbut, uiBut *newbut
static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut **butpp)
{
+ /* flags from the buttons we want to refresh, may want to add more here... */
+ const int flag_copy = UI_BUT_REDALERT;
+
uiBlock *oldblock;
uiBut *oldbut, *but = *butpp;
int found = 0;
@@ -659,6 +662,7 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut
/* drawing */
oldbut->icon = but->icon;
oldbut->iconadd = but->iconadd;
+ oldbut->alignnr = but->alignnr;
/* typically the same pointers, but not on undo/redo */
/* XXX some menu buttons store button itself in but->poin. Ugly */
@@ -667,6 +671,8 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut
SWAP(void *, oldbut->func_argN, but->func_argN);
}
+ oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy);
+
/* copy hardmin for list rows to prevent 'sticking' highlight to mouse position
* when scrolling without moving mouse (see [#28432]) */
if (ELEM(oldbut->type, ROW, LISTROW))
@@ -2869,7 +2875,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
}
/* keep track of UI_interface.h */
- if (ELEM8(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, BUTM, SCROLL, SEPR)) {}
+ if (ELEM9(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX, BUTM, SCROLL, SEPR)) {}
else if (but->type >= SEARCH_MENU) {}
else but->flag |= UI_BUT_UNDO;
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index cd845da10c6..11062ea2bd2 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -1389,7 +1389,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (scopes->track_disabled) {
glColor4f(0.7f, 0.3f, 0.3f, 0.3f);
- uiSetRoundBox(15);
+ uiSetRoundBox(UI_CNR_ALL);
uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
ok = 1;
@@ -1437,7 +1437,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (scopes->use_track_mask) {
glColor4f(0.0f, 0.0f, 0.0f, 0.3f);
- uiSetRoundBox(15);
+ uiSetRoundBox(UI_CNR_ALL);
uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
}
@@ -1478,7 +1478,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (!ok) {
glColor4f(0.f, 0.f, 0.f, 0.3f);
- uiSetRoundBox(15);
+ uiSetRoundBox(UI_CNR_ALL);
uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
}
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
new file mode 100644
index 00000000000..783a777a2fe
--- /dev/null
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -0,0 +1,642 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/interface/interface_eyedropper.c
+ * \ingroup edinterface
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math_vector.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_report.h"
+#include "BKE_idcode.h"
+
+#include "RNA_access.h"
+
+#include "BIF_gl.h"
+
+#include "UI_interface.h"
+
+#include "IMB_colormanagement.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "interface_intern.h"
+
+/* for HDR color sampling */
+#include "ED_image.h"
+#include "ED_node.h"
+#include "ED_clip.h"
+
+/* for ID data eyedropper */
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Eyedropper
+ */
+
+/** \name Eyedropper (RGB Color)
+ * \{ */
+
+typedef struct Eyedropper {
+ struct ColorManagedDisplay *display;
+
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+
+ int accum_start; /* has mouse been presed */
+ float accum_col[3];
+ int accum_tot;
+} Eyedropper;
+
+static int eyedropper_init(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Eyedropper *eye;
+
+ op->customdata = eye = MEM_callocN(sizeof(Eyedropper), "Eyedropper");
+
+ uiContextActiveProperty(C, &eye->ptr, &eye->prop, &eye->index);
+
+ if ((eye->ptr.data == NULL) ||
+ (eye->prop == NULL) ||
+ (RNA_property_editable(&eye->ptr, eye->prop) == FALSE) ||
+ (RNA_property_array_length(&eye->ptr, eye->prop) < 3) ||
+ (RNA_property_type(eye->prop) != PROP_FLOAT))
+ {
+ return FALSE;
+ }
+
+ if (RNA_property_subtype(eye->prop) == PROP_COLOR) {
+ const char *display_device;
+
+ display_device = scene->display_settings.display_device;
+ eye->display = IMB_colormanagement_display_get_named(display_device);
+ }
+
+ return TRUE;
+}
+
+static void eyedropper_exit(bContext *C, wmOperator *op)
+{
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ }
+}
+
+static int eyedropper_cancel(bContext *C, wmOperator *op)
+{
+ eyedropper_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+/* *** eyedropper_color_ helper functions *** */
+
+/**
+ * \brief get the color from the screen.
+ *
+ * Special check for image or nodes where we MAY have HDR pixels which don't display.
+ */
+static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int mx, int my, float r_col[3])
+{
+
+ /* we could use some clever */
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa;
+ for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
+ if (sa->spacetype == SPACE_IMAGE) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ SpaceImage *sima = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_image_color_sample(sima, ar, mval, r_col)) {
+ return;
+ }
+ }
+ }
+ else if (sa->spacetype == SPACE_NODE) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ SpaceNode *snode = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_node_color_sample(snode, ar, mval, r_col)) {
+ return;
+ }
+ }
+ }
+ else if (sa->spacetype == SPACE_CLIP) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ SpaceClip *sc = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_clip_color_sample(sc, ar, mval, r_col)) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ /* fallback to simple opengl picker */
+ glReadBuffer(GL_FRONT);
+ glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col);
+ glReadBuffer(GL_BACK);
+}
+
+/* sets the sample color RGB, maintaining A */
+static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3])
+{
+ float col_conv[4];
+
+ /* to maintain alpha */
+ RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv);
+
+ /* convert from display space to linear rgb space */
+ if (eye->display) {
+ copy_v3_v3(col_conv, col);
+ IMB_colormanagement_display_to_scene_linear_v3(col_conv, eye->display);
+ }
+ else {
+ copy_v3_v3(col_conv, col);
+ }
+
+ RNA_property_float_set_array(&eye->ptr, eye->prop, col_conv);
+
+ RNA_property_update(C, &eye->ptr, eye->prop);
+}
+
+/* set sample from accumulated values */
+static void eyedropper_color_set_accum(bContext *C, Eyedropper *eye)
+{
+ float col[3];
+ mul_v3_v3fl(col, eye->accum_col, 1.0f / (float)eye->accum_tot);
+ eyedropper_color_set(C, eye, col);
+}
+
+/* single point sample & set */
+static void eyedropper_color_sample(bContext *C, Eyedropper *eye, int mx, int my)
+{
+ float col[3];
+ eyedropper_color_sample_fl(C, eye, mx, my, col);
+ eyedropper_color_set(C, eye, col);
+}
+
+static void eyedropper_color_sample_accum(bContext *C, Eyedropper *eye, int mx, int my)
+{
+ float col[3];
+ eyedropper_color_sample_fl(C, eye, mx, my, col);
+ /* delay linear conversion */
+ add_v3_v3(eye->accum_col, col);
+ eye->accum_tot++;
+}
+
+/* main modal status check */
+static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Eyedropper *eye = (Eyedropper *)op->customdata;
+
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ return eyedropper_cancel(C, op);
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ if (eye->accum_tot == 0) {
+ eyedropper_color_sample(C, eye, event->x, event->y);
+ }
+ else {
+ eyedropper_color_set_accum(C, eye);
+ }
+ eyedropper_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else if (event->val == KM_PRESS) {
+ /* enable accum and make first sample */
+ eye->accum_start = TRUE;
+ eyedropper_color_sample_accum(C, eye, event->x, event->y);
+ }
+ break;
+ case MOUSEMOVE:
+ if (eye->accum_start) {
+ /* button is pressed so keep sampling */
+ eyedropper_color_sample_accum(C, eye, event->x, event->y);
+ eyedropper_color_set_accum(C, eye);
+ }
+ break;
+ case SPACEKEY:
+ if (event->val == KM_RELEASE) {
+ eye->accum_tot = 0;
+ zero_v3(eye->accum_col);
+ eyedropper_color_sample_accum(C, eye, event->x, event->y);
+ eyedropper_color_set_accum(C, eye);
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Modal Operator init */
+static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ /* init */
+ if (eyedropper_init(C, op)) {
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ eyedropper_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+}
+
+/* Repeat operator */
+static int eyedropper_exec(bContext *C, wmOperator *op)
+{
+ /* init */
+ if (eyedropper_init(C, op)) {
+
+ /* do something */
+
+ /* cleanup */
+ eyedropper_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int eyedropper_poll(bContext *C)
+{
+ if (!CTX_wm_window(C)) return 0;
+ else return 1;
+}
+
+void UI_OT_eyedropper_color(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Eyedropper";
+ ot->idname = "UI_OT_eyedropper_color";
+ ot->description = "Sample a color from the Blender Window to store in a property";
+
+ /* api callbacks */
+ ot->invoke = eyedropper_invoke;
+ ot->modal = eyedropper_modal;
+ ot->cancel = eyedropper_cancel;
+ ot->exec = eyedropper_exec;
+ ot->poll = eyedropper_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
+
+ /* properties */
+}
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* Data Dropper
+ *
+ * note: datadropper is only internal name to avoid confusion in this file
+ */
+
+/** \name Eyedropper (ID data-blocks)
+ * \{ */
+
+typedef struct DataDropper {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ short idcode;
+ const char *idcode_name;
+
+ ARegionType *art;
+ void *draw_handle_pixel;
+ char name[200];
+} DataDropper;
+
+
+static void datadropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg)
+{
+ DataDropper *ddr = arg;
+ int width;
+ const char *name = ddr->name;
+ wmWindow *win = CTX_wm_window(C);
+ int x = win->eventstate->x;
+ int y = win->eventstate->y;
+
+ if ((name[0] == '\0') ||
+ (BLI_rcti_isect_pt(&ar->winrct, x, y) == false))
+ {
+ return;
+ }
+
+ width = UI_GetStringWidth(name);
+ x = x - ar->winrct.xmin;
+ y = y - ar->winrct.ymin;
+
+ y += 20;
+
+ glColor4ub(0, 0, 0, 50);
+
+ uiSetRoundBox(UI_CNR_ALL | UI_RB_ALPHA);
+ uiRoundBox(x, y, x + width + 8, y + 15, 4);
+
+ glColor4ub(255, 255, 255, 255);
+ UI_DrawString(x + 4, y + 4, name);
+}
+
+
+static int datadropper_init(bContext *C, wmOperator *op)
+{
+ DataDropper *ddr;
+ int index_dummy;
+ StructRNA *type;
+
+ SpaceType *st;
+ ARegionType *art;
+
+ st = BKE_spacetype_from_id(SPACE_VIEW3D);
+ art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW);
+
+ op->customdata = ddr = MEM_callocN(sizeof(DataDropper), "DataDropper");
+
+ uiContextActiveProperty(C, &ddr->ptr, &ddr->prop, &index_dummy);
+
+ if ((ddr->ptr.data == NULL) ||
+ (ddr->prop == NULL) ||
+ (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
+ (RNA_property_type(ddr->prop) != PROP_POINTER))
+ {
+ return false;
+ }
+
+ ddr->art = art;
+ ddr->draw_handle_pixel = ED_region_draw_cb_activate(art, datadropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
+
+ type = RNA_property_pointer_type(&ddr->ptr, ddr->prop);
+ ddr->idcode = RNA_type_to_ID_code(type);
+ BLI_assert(ddr->idcode != 0);
+ ddr->idcode_name = BKE_idcode_to_name(ddr->idcode);
+
+ return true;
+}
+
+static void datadropper_exit(bContext *C, wmOperator *op)
+{
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ if (op->customdata) {
+ DataDropper *ddr = (DataDropper *)op->customdata;
+
+ ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel);
+
+ MEM_freeN(op->customdata);
+
+ op->customdata = NULL;
+ }
+}
+
+static int datadropper_cancel(bContext *C, wmOperator *op)
+{
+ datadropper_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+/* *** datadropper id helper functions *** */
+/**
+ * \brief get the ID from the screen.
+ *
+ */
+static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id)
+{
+
+ /* we could use some clever */
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa;
+
+ ScrArea *area_prev = CTX_wm_area(C);
+ ARegion *ar_prev = CTX_wm_region(C);
+
+ ddr->name[0] = '\0';
+
+ for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+ Base *base;
+
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ /* grr, always draw else we leave stale text */
+ ED_region_tag_redraw(ar);
+
+ base = ED_view3d_give_base_under_cursor(C, mval);
+ if (base) {
+ Object *ob = base->object;
+ ID *id = NULL;
+ if (ddr->idcode == ID_OB) {
+ id = (ID *)ob;
+ }
+ else if (ob->data) {
+ if (GS(((ID *)ob->data)->name) == ddr->idcode) {
+ id = (ID *)ob->data;
+ }
+ else {
+ BLI_snprintf(ddr->name, sizeof(ddr->name), "Incompatible, expected a %s",
+ ddr->idcode_name);
+ }
+ }
+
+ if (id) {
+ BLI_snprintf(ddr->name, sizeof(ddr->name), "%s: %s",
+ ddr->idcode_name, id->name + 2);
+ *r_id = id;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ CTX_wm_area_set(C, area_prev);
+ CTX_wm_region_set(C, ar_prev);
+}
+
+/* sets the ID, returns success */
+static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id)
+{
+ PointerRNA ptr_value;
+
+ RNA_id_pointer_create(id, &ptr_value);
+
+ RNA_property_pointer_set(&ddr->ptr, ddr->prop, ptr_value);
+
+ RNA_property_update(C, &ddr->ptr, ddr->prop);
+
+ ptr_value = RNA_property_pointer_get(&ddr->ptr, ddr->prop);
+
+ return (ptr_value.id.data == id);
+}
+
+/* single point sample & set */
+static bool datadropper_id_sample(bContext *C, DataDropper *ddr, int mx, int my)
+{
+ ID *id = NULL;
+
+ datadropper_id_sample_pt(C, ddr, mx, my, &id);
+ return datadropper_id_set(C, ddr, id);
+}
+
+/* main modal status check */
+static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ DataDropper *ddr = (DataDropper *)op->customdata;
+
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ return datadropper_cancel(C, op);
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ bool success;
+
+ success = datadropper_id_sample(C, ddr, event->x, event->y);
+ datadropper_exit(C, op);
+
+ if (success) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "Failed to set value");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ break;
+ case MOUSEMOVE:
+ {
+ ID *id = NULL;
+ datadropper_id_sample_pt(C, ddr, event->x, event->y, &id);
+ break;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Modal Operator init */
+static int datadropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ /* init */
+ if (datadropper_init(C, op)) {
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ datadropper_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+}
+
+/* Repeat operator */
+static int datadropper_exec(bContext *C, wmOperator *op)
+{
+ /* init */
+ if (datadropper_init(C, op)) {
+ /* cleanup */
+ datadropper_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int datadropper_poll(bContext *C)
+{
+ if (!CTX_wm_window(C)) return 0;
+ else return 1;
+}
+
+void UI_OT_eyedropper_id(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Eyedropper Datablock";
+ ot->idname = "UI_OT_eyedropper_id";
+ ot->description = "Sample a color from the Blender Window to store in a property";
+
+ /* api callbacks */
+ ot->invoke = datadropper_invoke;
+ ot->modal = datadropper_modal;
+ ot->cancel = datadropper_cancel;
+ ot->exec = datadropper_exec;
+ ot->poll = datadropper_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
+
+ /* properties */
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 20e03e7dcd5..c5faa99e067 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -2227,8 +2227,16 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
break;
case AKEY:
+
/* Ctrl + A: Select all */
- if (event->ctrl && !(event->alt || event->shift || event->oskey)) {
+#if defined(__APPLE__)
+ /* OSX uses cmd-a systemwide, so add it */
+ if ((event->oskey && !(event->alt || event->shift || event->ctrl)) ||
+ (event->ctrl && !(event->alt || event->shift || event->oskey)))
+#else
+ if (event->ctrl && !(event->alt || event->shift || event->oskey))
+#endif
+ {
ui_textedit_move(but, data, STRCUR_DIR_PREV,
false, STRCUR_JUMP_ALL);
ui_textedit_move(but, data, STRCUR_DIR_NEXT,
@@ -2613,7 +2621,10 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM4(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) {
- if (but->dt == UI_EMBOSSN && !event->ctrl) {
+ if (ELEM(event->type, PADENTER, RETKEY) && (!ui_is_but_utf8(but))) {
+ /* pass - allow filesel, enter to execute */
+ }
+ else if (but->dt == UI_EMBOSSN && !event->ctrl) {
/* pass */
}
else {
@@ -2647,13 +2658,8 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa
BLI_rcti_rctf_copy(&rect, &but->rect);
rect.xmin = rect.xmax - (BLI_rcti_size_y(&rect));
- if ( BLI_rcti_isect_pt(&rect, x, y) ) {
- /* most likely NULL, but let's check, and give it temp zero string */
- if (data->str == NULL)
- data->str = MEM_callocN(16, "temp str");
- data->str[0] = 0;
-
- ui_apply_but_TEX(C, but, data);
+ if (BLI_rcti_isect_pt(&rect, x, y)) {
+ ui_set_but_string(C, but, "");
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
@@ -3579,31 +3585,6 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
return WM_UI_HANDLER_BREAK;
}
}
- else if (but->type == COLOR) {
- if (ELEM3(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
- float *hsv = ui_block_hsv_get(but->block);
- float col[3];
-
- ui_get_but_vectorf(but, col);
- rgb_to_hsv_compat_v(col, hsv);
-
- if (event->type == WHEELDOWNMOUSE)
- hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
- else if (event->type == WHEELUPMOUSE)
- hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
- else {
- float fac = 0.005 * (event->y - event->prevy);
- hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f);
- }
-
- hsv_to_rgb_v(hsv, data->vec);
- ui_set_but_vectorf(but, data->vec);
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- ui_apply_button(C, but->block, but, data, true);
- return WM_UI_HANDLER_BREAK;
- }
- }
}
else if (data->state == BUTTON_STATE_WAIT_DRAG) {
@@ -3691,6 +3672,41 @@ static bool ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx,
return changed;
}
+static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM3(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
+ float *hsv = ui_block_hsv_get(but->block);
+ float col[3];
+
+ ui_get_but_vectorf(but, col);
+ rgb_to_hsv_compat_v(col, hsv);
+
+ if (event->type == WHEELDOWNMOUSE)
+ hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
+ else if (event->type == WHEELUPMOUSE)
+ hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
+ else {
+ float fac = 0.005 * (event->y - event->prevy);
+ hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f);
+ }
+
+ hsv_to_rgb_v(hsv, data->vec);
+ ui_set_but_vectorf(but, data->vec);
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ ui_apply_button(C, but->block, but, data, true);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -5389,6 +5405,28 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
else if (event->type == EVT_DROP) {
ui_but_drop(C, event, but, data);
}
+ /* handle eyedropper */
+ else if ((event->type == EKEY) && (event->val == KM_PRESS)) {
+ if (event->alt || event->shift || event->ctrl || event->oskey) {
+ /* pass */
+ }
+ else {
+ if (but->type == COLOR) {
+ WM_operator_name_call(C, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, NULL);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (but->type == SEARCH_MENU_UNLINK) {
+ if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_POINTER) {
+ StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ const short idcode = RNA_type_to_ID_code(type);
+ if ((idcode == ID_OB) || OB_DATA_SUPPORT_ID(idcode)) {
+ WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+ }
+ }
/* handle keyframing */
else if ((event->type == IKEY) &&
!ELEM(KM_MOD_FIRST, event->ctrl, event->oskey) &&
@@ -5534,7 +5572,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
if (but->a1 == UI_GRAD_V_ALT) /* signal to prevent calling up color picker */
retval = ui_do_but_EXIT(C, but, data, event);
else
- retval = ui_do_but_BLOCK(C, but, data, event);
+ retval = ui_do_but_COLOR(C, but, data, event);
break;
case BUT_NORMAL:
retval = ui_do_but_NORMAL(C, block, but, data, event);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 6382130cbbd..9cc16d82810 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -584,4 +584,8 @@ int ui_but_anim_expression_set(uiBut *but, const char *str);
int ui_but_anim_expression_create(uiBut *but, const char *str);
void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, float cfra);
-#endif
+/* interface_eyedropper.c */
+void UI_OT_eyedropper_color(struct wmOperatorType *ot);
+void UI_OT_eyedropper_id(struct wmOperatorType *ot);
+
+#endif /* __INTERFACE_INTERN_H__ */
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 424d2231a03..b453a3b8363 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -505,6 +505,14 @@ static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2)
static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop,
const char *uiname, int h, int icon_only)
{
+ /* XXX The way this function currently handles uiname parameter is insane and inconsistent with general UI API:
+ * * uiname is the *enum property* label.
+ * * when it is NULL or empty, we do not draw *enum items* labels, this doubles the icon_only parameter.
+ * * we *never* draw (i.e. really use) the enum label uiname, it is just used as a mere flag!
+ * Unfortunately, fixing this implies an API "soft break", so better to defer it for later... :/
+ * --mont29
+ */
+
uiBut *but;
EnumPropertyItem *item, *item_array;
const char *name;
@@ -3091,20 +3099,25 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,
/* set various special settings for buttons */
{
+ uiBlock *block = uiLayoutGetBlock(layout);
+ const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0;
uiBut *but;
+
- for (but = uiLayoutGetBlock(layout)->buttons.first; but; but = but->next) {
+ for (but = block->buttons.first; but; but = but->next) {
/* no undo for buttons for operator redo panels */
uiButClearFlag(but, UI_BUT_UNDO);
-#if 0 /* broken, causes freedback loop, see [#36109] */
+ /* only for popups, see [#36109] */
+
/* if button is operator's default property, and a text-field, enable focus for it
* - this is used for allowing operators with popups to rename stuff with fewer clicks
*/
- if ((but->rnaprop == op->type->prop) && (but->type == TEX)) {
- uiButSetFocusOnEnter(CTX_wm_window(C), but);
+ if (is_popup) {
+ if ((but->rnaprop == op->type->prop) && (but->type == TEX)) {
+ uiButSetFocusOnEnter(CTX_wm_window(C), but);
+ }
}
-#endif
}
}
}
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index d52702c2d51..36e965e13d2 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -27,20 +27,14 @@
* \ingroup edinterface
*/
-#include <stdio.h>
-#include <math.h>
#include <string.h>
#include "MEM_guardedalloc.h"
-#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_text_types.h" /* for UI_OT_reports_to_text */
#include "BLI_blenlib.h"
-#include "BLI_math_color.h"
-#include "BLI_math_vector.h"
-#include "BLI_utildefines.h"
#include "BLF_api.h"
#include "BLF_translation.h"
@@ -54,12 +48,8 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "BIF_gl.h"
-
#include "UI_interface.h"
-#include "IMB_colormanagement.h"
-
#include "interface_intern.h"
#include "WM_api.h"
@@ -70,282 +60,6 @@
#include "BKE_main.h"
#include "BLI_ghash.h"
-#include "ED_image.h" /* for HDR color sampling */
-#include "ED_node.h" /* for HDR color sampling */
-#include "ED_clip.h" /* for HDR color sampling */
-
-/* ********************************************************** */
-
-typedef struct Eyedropper {
- struct ColorManagedDisplay *display;
-
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
-
- int accum_start; /* has mouse been presed */
- float accum_col[3];
- int accum_tot;
-} Eyedropper;
-
-static int eyedropper_init(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- Eyedropper *eye;
-
- op->customdata = eye = MEM_callocN(sizeof(Eyedropper), "Eyedropper");
-
- uiContextActiveProperty(C, &eye->ptr, &eye->prop, &eye->index);
-
- if ((eye->ptr.data == NULL) ||
- (eye->prop == NULL) ||
- (RNA_property_editable(&eye->ptr, eye->prop) == FALSE) ||
- (RNA_property_array_length(&eye->ptr, eye->prop) < 3) ||
- (RNA_property_type(eye->prop) != PROP_FLOAT))
- {
- return FALSE;
- }
-
- if (RNA_property_subtype(eye->prop) == PROP_COLOR) {
- const char *display_device;
-
- display_device = scene->display_settings.display_device;
- eye->display = IMB_colormanagement_display_get_named(display_device);
- }
-
- return TRUE;
-}
-
-static void eyedropper_exit(bContext *C, wmOperator *op)
-{
- WM_cursor_modal_restore(CTX_wm_window(C));
-
- if (op->customdata)
- MEM_freeN(op->customdata);
- op->customdata = NULL;
-}
-
-static int eyedropper_cancel(bContext *C, wmOperator *op)
-{
- eyedropper_exit(C, op);
- return OPERATOR_CANCELLED;
-}
-
-/* *** eyedropper_color_ helper functions *** */
-
-/**
- * \brief get the color from the screen.
- *
- * Special check for image or nodes where we MAY have HDR pixels which don't display.
- */
-static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int mx, int my, float r_col[3])
-{
-
- /* we could use some clever */
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa;
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
- if (sa->spacetype == SPACE_IMAGE) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceImage *sima = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_image_color_sample(sima, ar, mval, r_col)) {
- return;
- }
- }
- }
- else if (sa->spacetype == SPACE_NODE) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceNode *snode = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_node_color_sample(snode, ar, mval, r_col)) {
- return;
- }
- }
- }
- else if (sa->spacetype == SPACE_CLIP) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceClip *sc = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_clip_color_sample(sc, ar, mval, r_col)) {
- return;
- }
- }
- }
- }
- }
-
- /* fallback to simple opengl picker */
- glReadBuffer(GL_FRONT);
- glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col);
- glReadBuffer(GL_BACK);
-}
-
-/* sets the sample color RGB, maintaining A */
-static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3])
-{
- float col_conv[4];
-
- /* to maintain alpha */
- RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv);
-
- /* convert from display space to linear rgb space */
- if (eye->display) {
- copy_v3_v3(col_conv, col);
- IMB_colormanagement_display_to_scene_linear_v3(col_conv, eye->display);
- }
- else {
- copy_v3_v3(col_conv, col);
- }
-
- RNA_property_float_set_array(&eye->ptr, eye->prop, col_conv);
-
- RNA_property_update(C, &eye->ptr, eye->prop);
-}
-
-/* set sample from accumulated values */
-static void eyedropper_color_set_accum(bContext *C, Eyedropper *eye)
-{
- float col[3];
- mul_v3_v3fl(col, eye->accum_col, 1.0f / (float)eye->accum_tot);
- eyedropper_color_set(C, eye, col);
-}
-
-/* single point sample & set */
-static void eyedropper_color_sample(bContext *C, Eyedropper *eye, int mx, int my)
-{
- float col[3];
- eyedropper_color_sample_fl(C, eye, mx, my, col);
- eyedropper_color_set(C, eye, col);
-}
-
-static void eyedropper_color_sample_accum(bContext *C, Eyedropper *eye, int mx, int my)
-{
- float col[3];
- eyedropper_color_sample_fl(C, eye, mx, my, col);
- /* delay linear conversion */
- add_v3_v3(eye->accum_col, col);
- eye->accum_tot++;
-}
-
-/* main modal status check */
-static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Eyedropper *eye = (Eyedropper *)op->customdata;
-
- switch (event->type) {
- case ESCKEY:
- case RIGHTMOUSE:
- return eyedropper_cancel(C, op);
- case LEFTMOUSE:
- if (event->val == KM_RELEASE) {
- if (eye->accum_tot == 0) {
- eyedropper_color_sample(C, eye, event->x, event->y);
- }
- else {
- eyedropper_color_set_accum(C, eye);
- }
- eyedropper_exit(C, op);
- return OPERATOR_FINISHED;
- }
- else if (event->val == KM_PRESS) {
- /* enable accum and make first sample */
- eye->accum_start = TRUE;
- eyedropper_color_sample_accum(C, eye, event->x, event->y);
- }
- break;
- case MOUSEMOVE:
- if (eye->accum_start) {
- /* button is pressed so keep sampling */
- eyedropper_color_sample_accum(C, eye, event->x, event->y);
- eyedropper_color_set_accum(C, eye);
- }
- break;
- case SPACEKEY:
- if (event->val == KM_RELEASE) {
- eye->accum_tot = 0;
- zero_v3(eye->accum_col);
- eyedropper_color_sample_accum(C, eye, event->x, event->y);
- eyedropper_color_set_accum(C, eye);
- }
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-/* Modal Operator init */
-static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- /* init */
- if (eyedropper_init(C, op)) {
- WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- eyedropper_exit(C, op);
- return OPERATOR_CANCELLED;
- }
-}
-
-/* Repeat operator */
-static int eyedropper_exec(bContext *C, wmOperator *op)
-{
- /* init */
- if (eyedropper_init(C, op)) {
-
- /* do something */
-
- /* cleanup */
- eyedropper_exit(C, op);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
-}
-
-static int eyedropper_poll(bContext *C)
-{
- if (!CTX_wm_window(C)) return 0;
- else return 1;
-}
-
-static void UI_OT_eyedropper(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Eyedropper";
- ot->idname = "UI_OT_eyedropper";
- ot->description = "Sample a color from the Blender Window to store in a property";
-
- /* api callbacks */
- ot->invoke = eyedropper_invoke;
- ot->modal = eyedropper_modal;
- ot->cancel = eyedropper_cancel;
- ot->exec = eyedropper_exec;
- ot->poll = eyedropper_poll;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
-
- /* properties */
-}
-
/* Reset Default Theme ------------------------ */
static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
@@ -1114,7 +828,6 @@ static void UI_OT_reloadtranslation(wmOperatorType *ot)
void UI_buttons_operatortypes(void)
{
- WM_operatortype_append(UI_OT_eyedropper);
WM_operatortype_append(UI_OT_reset_default_theme);
WM_operatortype_append(UI_OT_copy_data_path_button);
WM_operatortype_append(UI_OT_reset_default_button);
@@ -1127,4 +840,8 @@ void UI_buttons_operatortypes(void)
WM_operatortype_append(UI_OT_edittranslation_init);
#endif
WM_operatortype_append(UI_OT_reloadtranslation);
+
+ /* external */
+ WM_operatortype_append(UI_OT_eyedropper_color);
+ WM_operatortype_append(UI_OT_eyedropper_id);
}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 35741618211..15fbd51c6fc 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -2185,7 +2185,7 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
yco = -3.0f * UI_UNIT_Y;
if (show_picker) {
- bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, yco, UI_UNIT_X, UI_UNIT_Y, NULL);
+ bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, yco, UI_UNIT_X, UI_UNIT_Y, NULL);
uiButSetFunc(bt, close_popup_cb, bt, NULL);
}
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 22c20842723..00113666872 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -1374,14 +1374,16 @@ static void VIEW2D_OT_smoothview(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Smooth View 2D";
- ot->description = "Zoom in the view to the nearest item contained in the border";
+ ot->description = "";
ot->idname = "VIEW2D_OT_smoothview";
/* api callbacks */
ot->invoke = view2d_smoothview_invoke;
-
ot->poll = view2d_poll;
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
+
/* rna */
WM_operator_properties_gesture_border(ot, FALSE);
}
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 70fa97bebc1..f50e4400b91 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -96,7 +96,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int use_object_instantiation;
int sort_by_name;
int export_transformation_type;
- int second_life;
+ int open_sim;
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
@@ -142,7 +142,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation");
sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name");
export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection");
- second_life = RNA_boolean_get(op->ptr, "second_life");
+ open_sim = RNA_boolean_get(op->ptr, "open_sim");
/* get editmode results */
ED_object_editmode_load(CTX_data_edit_object(C));
@@ -168,7 +168,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
use_object_instantiation,
sort_by_name,
export_transformation_type,
- second_life))
+ open_sim))
{
return OPERATOR_FINISHED;
}
@@ -236,7 +236,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, FALSE);
uiItemR(row, imfptr, "deform_bones_only", 0, NULL, ICON_NONE);
row = uiLayoutRow(box, FALSE);
- uiItemR(row, imfptr, "second_life", 0, NULL, ICON_NONE);
+ uiItemR(row, imfptr, "open_sim", 0, NULL, ICON_NONE);
/* Collada options: */
box = uiLayoutBox(layout);
@@ -350,8 +350,8 @@ void WM_OT_collada_export(wmOperatorType *ot)
RNA_def_enum(ot->srna, "export_transformation_type_selection", prop_bc_export_transformation_type, 0,
"Transform", "Transformation type for translation, scale and rotation");
- RNA_def_boolean(ot->srna, "second_life", 0, "Export for Second Life",
- "Compatibility mode for Second Life");
+ RNA_def_boolean(ot->srna, "open_sim", 0, "Export for OpenSim",
+ "Compatibility mode for OpenSim and compatible online worlds");
}
diff --git a/source/blender/editors/mask/SConscript b/source/blender/editors/mask/SConscript
index a80d3317c89..9dd521e3a7c 100644
--- a/source/blender/editors/mask/SConscript
+++ b/source/blender/editors/mask/SConscript
@@ -41,5 +41,8 @@ incs = [
'../../makesrna',
'../../windowmanager',
]
+
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ incs.append(env['BF_PTHREADS_INC'])
env.BlenderLib('bf_editors_mask', sources, incs, defs, libtype=['core'], priority=[100])
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index fec4ab87996..50d8e653737 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -35,6 +35,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BLI_task.h"
#include "BKE_context.h"
#include "BKE_mask.h"
@@ -48,6 +49,7 @@
#include "ED_mask.h" /* own include */
#include "ED_space_api.h"
#include "BIF_gl.h"
+#include "BIF_glutil.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -535,10 +537,93 @@ void ED_mask_draw(const bContext *C,
draw_masklays(C, mask, draw_flag, draw_type, width, height);
}
+typedef struct ThreadedMaskRasterizeState {
+ MaskRasterHandle *handle;
+ float *buffer;
+ int width, height;
+} ThreadedMaskRasterizeState;
+
+typedef struct ThreadedMaskRasterizeData {
+ int start_scanline;
+ int num_scanlines;
+} ThreadedMaskRasterizeData;
+
+static void mask_rasterize_func(TaskPool *pool, void *taskdata, int UNUSED(threadid))
+{
+ ThreadedMaskRasterizeState *state = (ThreadedMaskRasterizeState *) BLI_task_pool_userdata(pool);
+ ThreadedMaskRasterizeData *data = (ThreadedMaskRasterizeData *) taskdata;
+ int scanline;
+
+ for (scanline = 0; scanline < data->num_scanlines; scanline++) {
+ int x, y = data->start_scanline + scanline;
+ for (x = 0; x < state->width; x++) {
+ int index = y * state->width + x;
+ float xy[2];
+
+ xy[0] = (float) x / state->width;
+ xy[1] = (float) y / state->height;
+
+ state->buffer[index] = BKE_maskrasterize_handle_sample(state->handle, xy);
+ }
+ }
+}
+
+static float *threaded_mask_rasterize(Mask *mask, const int width, const int height)
+{
+ TaskScheduler *task_scheduler = BLI_task_scheduler_get();
+ TaskPool *task_pool;
+ MaskRasterHandle *handle;
+ ThreadedMaskRasterizeState state;
+ float *buffer;
+ int i, num_threads = BLI_task_scheduler_num_threads(task_scheduler), scanlines_per_thread;
+
+ buffer = MEM_mallocN(sizeof(float) * height * width, "rasterized mask buffer");
+
+ /* Initialize rasterization handle. */
+ handle = BKE_maskrasterize_handle_new();
+ BKE_maskrasterize_handle_init(handle, mask, width, height, TRUE, TRUE, TRUE);
+
+ state.handle = handle;
+ state.buffer = buffer;
+ state.width = width;
+ state.height = height;
+
+ task_pool = BLI_task_pool_create(task_scheduler, &state);
+
+ BLI_begin_threaded_malloc();
+
+ scanlines_per_thread = height / num_threads;
+ for (i = 0; i < num_threads; i++) {
+ ThreadedMaskRasterizeData *data = MEM_mallocN(sizeof(ThreadedMaskRasterizeData),
+ "threaded mask rasterize data");
+
+ data->start_scanline = i * scanlines_per_thread;
+
+ if (i < num_threads - 1) {
+ data->num_scanlines = scanlines_per_thread;
+ }
+ else {
+ data->num_scanlines = height - data->start_scanline;
+ }
+
+ BLI_task_pool_push(task_pool, mask_rasterize_func, data, true, TASK_PRIORITY_LOW);
+ }
+
+ /* work and wait until tasks are done */
+ BLI_task_pool_work_and_wait(task_pool);
+
+ /* Free memory. */
+ BLI_task_pool_free(task_pool);
+ BLI_end_threaded_malloc();
+ BKE_maskrasterize_handle_free(handle);
+
+ return buffer;
+}
+
/* sets up the opengl context.
* width, height are to match the values from ED_mask_get_size() */
void ED_mask_draw_region(Mask *mask, ARegion *ar,
- const char draw_flag, const char draw_type,
+ const char draw_flag, const char draw_type, const char overlay_mode,
const int width_i, const int height_i, /* convert directly into aspect corrected vars */
const float aspx, const float aspy,
const short do_scale_applied, const short do_draw_cb,
@@ -592,6 +677,37 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
yofs = ((width - height) / -2.0f) * zoomy;
}
+ if (draw_flag & MASK_DRAWFLAG_OVERLAY) {
+ float *buffer = threaded_mask_rasterize(mask, width, height);
+ int format;
+
+ if (overlay_mode == MASK_OVERLAY_ALPHACHANNEL) {
+ glColor3f(1.0f, 1.0f, 1.0f);
+ format = GL_LUMINANCE;
+ }
+ else {
+ /* More blending types could be supported in the future. */
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
+ format = GL_ALPHA;
+ }
+
+ glPushMatrix();
+ glTranslatef(x, y, 0);
+ glScalef(zoomx, zoomy, 0);
+ if (stabmat) {
+ glMultMatrixf(stabmat);
+ }
+ glaDrawPixelsTex(0.0f, 0.0f, width, height, format, GL_FLOAT, GL_NEAREST, buffer);
+ glPopMatrix();
+
+ if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
+ glDisable(GL_BLEND);
+ }
+
+ MEM_freeN(buffer);
+ }
+
/* apply transformation so mask editing tools will assume drawing from the origin in normalized space */
glPushMatrix();
glTranslatef(x + xofs, y + yofs, 0);
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 6033e7ee471..97da0047793 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -64,7 +64,7 @@ typedef struct {
float shift_factor; /* The current factor when shift is pressed. Negative when shift not active. */
/* modal only */
- int mcenter[2];
+ float mcenter[2];
BMBackup mesh_backup;
void *draw_handle_pixel;
short twtype;
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index afafd8458c5..5431b1deb1c 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -300,7 +300,7 @@ void MESH_OT_bisect(struct wmOperatorType *ot)
/* identifiers */
ot->name = "Bisect";
- ot->description = "Enforce symmetry (both form and topological) across an axis";
+ ot->description = "Cut geometry along a plane";
ot->idname = "MESH_OT_bisect";
/* api callbacks */
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 300fb67ec80..3df4ad738ae 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -290,7 +290,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
//BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "extrude_face_region geom=%hef", BM_ELEM_SELECT);
BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS,
"translate vec=%v verts=%hv",
- (float *)dvec, BM_ELEM_SELECT);
+ dvec, BM_ELEM_SELECT);
//extrudeflag(obedit, em, SELECT, nor);
//translateflag(em, SELECT, dvec);
}
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index 3966826a5b2..eb66cf50a1e 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -68,7 +68,7 @@ typedef struct {
NumInput num_input;
/* modal only */
- int mcenter[2];
+ float mcenter[2];
BMBackup mesh_backup;
void *draw_handle_pixel;
short twtype;
@@ -96,10 +96,10 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
BLI_snprintf(msg, HEADER_LENGTH, str,
flts_str,
flts_str + NUM_STR_REP_LEN,
- opdata->modify_depth ? IFACE_("On") : IFACE_("Off"),
- RNA_boolean_get(op->ptr, "use_outset") ? IFACE_("On") : IFACE_("Off"),
- RNA_boolean_get(op->ptr, "use_boundary") ? IFACE_("On") : IFACE_("Off"),
- RNA_boolean_get(op->ptr, "use_individual") ? IFACE_("On") : IFACE_("Off")
+ WM_bool_as_string(opdata->modify_depth),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "use_outset")),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "use_boundary")),
+ WM_bool_as_string(RNA_boolean_get(op->ptr, "use_individual"))
);
ED_area_headerprint(sa, msg);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index a60b0248644..b0dc30d73f7 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -230,10 +230,10 @@ static void knife_update_header(bContext *C, KnifeTool_OpData *kcd)
BLI_snprintf(header, HEADER_LENGTH, IFACE_("LMB: define cut lines, Return/Spacebar: confirm, Esc or RMB: cancel, "
"E: new cut, Ctrl: midpoint snap (%s), Shift: ignore snap (%s), "
"C: angle constrain (%s), Z: cut through (%s)"),
- kcd->snap_midpoints ? IFACE_("On") : IFACE_("Off"),
- kcd->ignore_edge_snapping ? IFACE_("On") : IFACE_("Off"),
- kcd->angle_snapping ? IFACE_("On") : IFACE_("Off"),
- kcd->cut_through ? IFACE_("On") : IFACE_("Off"));
+ WM_bool_as_string(kcd->snap_midpoints),
+ WM_bool_as_string(kcd->ignore_edge_snapping),
+ WM_bool_as_string(kcd->angle_snapping),
+ WM_bool_as_string(kcd->cut_through));
ED_area_headerprint(CTX_wm_area(C), header);
}
@@ -1546,8 +1546,16 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
knife_project_v2(kcd, v1, s1);
knife_project_v2(kcd, v2, s2);
- if (len_squared_v2v2(s1, s2) < 1)
- return;
+ if (kcd->is_interactive) {
+ if (len_squared_v2v2(s1, s2) < 1.0f) {
+ return;
+ }
+ }
+ else {
+ if (len_squared_v2v2(s1, s2) < KNIFE_FLT_EPS_SQUARED) {
+ return;
+ }
+ }
/* unproject screen line */
ED_view3d_win_to_segment(kcd->ar, kcd->vc.v3d, s1, v1, v3, true);
@@ -2123,7 +2131,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd)
facenet_entry *entry;
ListBase *face_nets = MEM_callocN(sizeof(ListBase) * bm->totface, "face_nets");
BMFace **faces = MEM_callocN(sizeof(BMFace *) * bm->totface, "faces knife");
- MemArena *arena = BLI_memarena_new(1 << 16, "knifenet_fill_faces");
+ MemArena *arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "knifenet_fill_faces");
SmallHash shash;
RNG *rng;
int i, j, k = 0, totface = bm->totface;
@@ -3151,7 +3159,7 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
(only_select ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN),
kcd->cagecos, false);
- kcd->arena = BLI_memarena_new(1 << 15, "knife");
+ kcd->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 15), "knife");
kcd->vthresh = KMAXDIST - 1;
kcd->ethresh = KMAXDIST;
@@ -3517,7 +3525,7 @@ static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f,
while (p) {
const float (*mval_fl)[2] = p->link;
const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
- isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1);
+ isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false);
p = p->next;
}
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 892b773b1ba..ae1007cb98a 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -537,7 +537,8 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event->val == KM_PRESS) {
/* finish */
ED_region_tag_redraw(lcd->ar);
-
+ ED_area_headerprint(CTX_wm_area(C), NULL);
+
if (lcd->eed) {
/* set for redo */
BM_mesh_elem_index_ensure(lcd->em->bm, BM_EDGE);
@@ -550,9 +551,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
else {
return ringcut_cancel(C, op);
}
-
- ED_area_headerprint(CTX_wm_area(C), NULL);
-
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 806ae96cb61..f975d801d10 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -31,6 +31,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_bitmap.h"
#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
@@ -184,55 +185,13 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag)
unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0; /* set in drawobject.c ... for colorindices */
/* facilities for border select and circle select */
-static char *selbuf = NULL;
+static BLI_bitmap *selbuf = NULL;
-/* opengl doesn't support concave... */
-static void draw_triangulated(const int mcords[][2], const short tot)
+static BLI_bitmap *edbm_backbuf_alloc(const int size)
{
- ListBase lb = {NULL, NULL};
- DispList *dl;
- float *fp;
- int a;
- const float z_up[3] = {0.0f, 0.0f, 1.0f};
-
- /* make displist */
- dl = MEM_callocN(sizeof(DispList), "poly disp");
- dl->type = DL_POLY;
- dl->parts = 1;
- dl->nr = tot;
- dl->verts = fp = MEM_callocN(tot * 3 * sizeof(float), "poly verts");
- BLI_addtail(&lb, dl);
-
- for (a = 0; a < tot; a++, fp += 3) {
- fp[0] = (float)mcords[a][0];
- fp[1] = (float)mcords[a][1];
- }
-
- /* do the fill */
- BKE_displist_fill(&lb, &lb, z_up, false);
-
- /* do the draw */
- dl = lb.first; /* filldisplist adds in head of list */
- if (dl->type == DL_INDEX3) {
- int *index;
-
- a = dl->parts;
- fp = dl->verts;
- index = dl->index;
- glBegin(GL_TRIANGLES);
- while (a--) {
- glVertex3fv(fp + 3 * index[0]);
- glVertex3fv(fp + 3 * index[1]);
- glVertex3fv(fp + 3 * index[2]);
- index += 3;
- }
- glEnd();
- }
-
- BKE_displist_free(&lb);
+ return BLI_BITMAP_NEW(size, "selbuf");
}
-
/* reads rect, and builds selection array for quick lookup */
/* returns if all is OK */
bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
@@ -252,24 +211,31 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma
dr = buf->rect;
/* build selection lookup */
- selbuf = MEM_callocN(bm_vertoffs + 1, "selbuf");
+ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
a = (xmax - xmin + 1) * (ymax - ymin + 1);
while (a--) {
- if (*dr > 0 && *dr <= bm_vertoffs)
- selbuf[*dr] = 1;
+ if (*dr > 0 && *dr <= bm_vertoffs) {
+ BLI_BITMAP_SET(selbuf, *dr);
+ }
dr++;
}
IMB_freeImBuf(buf);
return true;
}
-int EDBM_backbuf_check(unsigned int index)
+bool EDBM_backbuf_check(unsigned int index)
{
- if (selbuf == NULL) return 1;
+ /* odd logic, if selbuf is NULL we assume no zbuf-selection is enabled
+ * and just ignore the depth buffer, this is error prone since its possible
+ * code doesn't set the depth buffer by accident, but leave for now. - Campbell */
+ if (selbuf == NULL)
+ return true;
+
if (index > 0 && index <= bm_vertoffs)
- return selbuf[index];
- return 0;
+ return BLI_BITMAP_GET_BOOL(selbuf, index);
+
+ return false;
}
void EDBM_backbuf_free(void)
@@ -278,6 +244,18 @@ void EDBM_backbuf_free(void)
selbuf = NULL;
}
+struct LassoMaskData {
+ unsigned int *px;
+ int width;
+};
+
+static void edbm_mask_lasso_px_cb(int x, int y, void *user_data)
+{
+ struct LassoMaskData *data = user_data;
+ data->px[(y * data->width) + x] = true;
+}
+
+
/* mcords is a polygon mask
* - grab backbuffer,
* - draw with black in backbuffer,
@@ -286,9 +264,10 @@ void EDBM_backbuf_free(void)
*/
bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
{
- unsigned int *dr, *drm;
- struct ImBuf *buf, *bufmask;
+ unsigned int *dr, *dr_mask, *dr_mask_arr;
+ struct ImBuf *buf;
int a;
+ struct LassoMaskData lasso_mask_data;
/* method in use for face selecting too */
if (vc->obedit == NULL) {
@@ -306,49 +285,27 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short
dr = buf->rect;
- if (vc->rv3d->gpuoffscreen)
- GPU_offscreen_bind(vc->rv3d->gpuoffscreen);
-
- /* draw the mask */
- glDisable(GL_DEPTH_TEST);
-
- glColor3ub(0, 0, 0);
-
- /* yah, opengl doesn't do concave... tsk! */
- ED_region_pixelspace(vc->ar);
- draw_triangulated(mcords, tot);
-
- glBegin(GL_LINE_LOOP); /* for zero sized masks, lines */
- for (a = 0; a < tot; a++) {
- glVertex2iv(mcords[a]);
- }
- glEnd();
-
- glFinish(); /* to be sure readpixels sees mask */
-
- if (vc->rv3d->gpuoffscreen)
- GPU_offscreen_unbind(vc->rv3d->gpuoffscreen);
-
- /* grab mask */
- bufmask = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf->x * buf->y, __func__);
+ lasso_mask_data.px = dr_mask;
+ lasso_mask_data.width = (xmax - xmin) + 1;
- if (bufmask == NULL) {
- return false; /* only when mem alloc fails, go crash somewhere else! */
- }
- else {
- drm = bufmask->rect;
- }
+ fill_poly_v2i_n(
+ xmin, ymin, xmax + 1, ymax + 1,
+ mcords, tot,
+ edbm_mask_lasso_px_cb, &lasso_mask_data);
/* build selection lookup */
- selbuf = MEM_callocN(bm_vertoffs + 1, "selbuf");
+ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
a = (xmax - xmin + 1) * (ymax - ymin + 1);
while (a--) {
- if (*dr > 0 && *dr <= bm_vertoffs && *drm == 0) selbuf[*dr] = 1;
- dr++; drm++;
+ if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) {
+ BLI_BITMAP_SET(selbuf, *dr);
+ }
+ dr++; dr_mask++;
}
IMB_freeImBuf(buf);
- IMB_freeImBuf(bufmask);
+ MEM_freeN(dr_mask_arr);
return true;
}
@@ -380,12 +337,14 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
dr = buf->rect;
/* build selection lookup */
- selbuf = MEM_callocN(bm_vertoffs + 1, "selbuf");
+ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
radsq = rads * rads;
for (yc = -rads; yc <= rads; yc++) {
for (xc = -rads; xc <= rads; xc++, dr++) {
if (xc * xc + yc * yc < radsq) {
- if (*dr > 0 && *dr <= bm_vertoffs) selbuf[*dr] = 1;
+ if (*dr > 0 && *dr <= bm_vertoffs) {
+ BLI_BITMAP_SET(selbuf, *dr);
+ }
}
}
}
@@ -1897,7 +1856,6 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
BMIter iter;
- BMVert *v;
BMEdge *e;
BMWalker walker;
@@ -1911,8 +1869,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
BMFace *efa;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_set(efa, BM_ELEM_TAG, (BM_elem_flag_test(efa, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)));
+ BM_elem_flag_set(efa, BM_ELEM_TAG, BM_elem_flag_test(efa, BM_ELEM_SELECT));
}
if (limit) {
@@ -1932,6 +1889,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) {
BM_face_select_set(bm, efa, true);
+ BM_elem_flag_disable(efa, BM_ELEM_TAG);
}
}
}
@@ -1942,13 +1900,10 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
}
}
else {
+ BMVert *v;
+
BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
- else {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- }
+ BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
}
BMW_init(&walker, em->bm, BMW_SHELL,
@@ -1960,6 +1915,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
for (e = BMW_begin(&walker, v); e; e = BMW_step(&walker)) {
BM_edge_select_set(em->bm, e, true);
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
}
}
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index f0e5a64b1bd..9e5782c12f2 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -983,12 +983,6 @@ void MESH_OT_flip_normals(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static const EnumPropertyItem direction_items[] = {
- {false, "CW", 0, "Clockwise", ""},
- {true, "CCW", 0, "Counter Clockwise", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
/* only accepts 1 selected edge, or 2 selected faces */
static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
{
@@ -3008,7 +3002,7 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
}
offset = RNA_property_int_get(op->ptr, prop_offset);
- offset = mod_i(offset, clamp);
+ offset = clamp ? mod_i(offset, clamp) : 0;
/* in simple cases, move selection for tags, but also support more advanced cases */
edbm_fill_grid_prepare(em->bm, offset, &span, calc_span);
@@ -3342,7 +3336,7 @@ void MESH_OT_dissolve_verts(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Dissolve Vertices";
- ot->description = "Dissolve geometry";
+ ot->description = "Dissolve verts, merge edges and faces";
ot->idname = "MESH_OT_dissolve_verts";
/* api callbacks */
@@ -3379,7 +3373,7 @@ void MESH_OT_dissolve_edges(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Dissolve Edges";
- ot->description = "Dissolve geometry";
+ ot->description = "Dissolve edges, merging faces";
ot->idname = "MESH_OT_dissolve_edges";
/* api callbacks */
@@ -3418,7 +3412,7 @@ void MESH_OT_dissolve_faces(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Dissolve Faces";
- ot->description = "Dissolve geometry";
+ ot->description = "Dissolve faces";
ot->idname = "MESH_OT_dissolve_faces";
/* api callbacks */
@@ -4519,7 +4513,7 @@ void MESH_OT_wireframe(wmOperatorType *ot)
/* identifiers */
ot->name = "Wire Frame";
ot->idname = "MESH_OT_wireframe";
- ot->description = "Inset new faces into selected faces";
+ ot->description = "Create a solid wire-frame from faces";
/* api callbacks */
ot->exec = edbm_wireframe_exec;
@@ -4561,7 +4555,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
+
/* Delete unused vertices, edges, and faces */
if (RNA_boolean_get(op->ptr, "delete_unused")) {
if (!EDBM_op_callf(em, op, "delete geom=%S context=%i",
@@ -4584,9 +4579,11 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
/* Merge adjacent triangles */
if (RNA_boolean_get(op->ptr, "join_triangles")) {
- if (!EDBM_op_callf(em, op, "join_triangles faces=%S limit=%f",
- &bmop, "geom.out",
- RNA_float_get(op->ptr, "limit")))
+ if (!EDBM_op_call_and_selectf(em, op,
+ "faces.out", true,
+ "join_triangles faces=%S limit=%f",
+ &bmop, "geom.out",
+ RNA_float_get(op->ptr, "limit")))
{
EDBM_op_finish(em, &bmop, op, true);
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index 376f2ed294b..4a8097f260e 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -91,20 +91,24 @@
typedef struct MultiresBakerJobData {
struct MultiresBakerJobData *next, *prev;
DerivedMesh *lores_dm, *hires_dm;
- int simple, lvl, tot_lvl;
+ bool simple;
+ int lvl, tot_lvl;
ListBase images;
} MultiresBakerJobData;
/* data passing to multires-baker job */
typedef struct {
ListBase data;
- int bake_clear, bake_filter;
- short mode, use_lores_mesh;
- int number_of_rays;
- float bias;
- int raytrace_structure;
- int octree_resolution;
- int threads;
+ bool bake_clear; /* Clear the images before baking */
+ int bake_filter; /* Bake-filter, aka margin */
+ short mode; /* mode of baking (displacement, normals, AO) */
+ bool use_lores_mesh; /* Use low-resolution mesh when baking displacement maps */
+ int number_of_rays; /* Number of rays to be cast when doing AO baking */
+ float bias; /* Bias between object and start ray point when doing AO baking */
+ int raytrace_structure; /* Optimization structure to be used for AO baking */
+ int octree_resolution; /* Reslution of octotree when using octotree optimization structure */
+ int threads; /* Number of threads to be used for baking */
+ float user_scale; /* User scale used to scale displacement when baking derivative map. */
} MultiresBakeJob;
static bool multiresbake_check(bContext *C, wmOperator *op)
@@ -236,7 +240,7 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l
return dm;
}
-static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, int *simple)
+static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, bool *simple)
{
Mesh *me = (Mesh *)ob->data;
MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
@@ -253,7 +257,7 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l
CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH);
*lvl = mmd->totlvl;
- *simple = mmd->simple;
+ *simple = mmd->simple != 0;
tmp_mmd.lvl = mmd->totlvl;
tmp_mmd.sculptlvl = mmd->totlvl;
@@ -349,7 +353,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
if (scene->r.bake_mode == RE_BAKE_NORMALS) {
clear_flag = CLEAR_TANGENT_NORMAL;
}
- else if (scene->r.bake_mode == RE_BAKE_DISPLACEMENT) {
+ else if (ELEM(scene->r.bake_mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) {
clear_flag = CLEAR_DISPLACEMENT;
}
@@ -376,6 +380,8 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
bkr.raytrace_structure = scene->r.raytrace_structure;
bkr.octree_resolution = scene->r.ocres;
bkr.threads = BKE_scene_num_threads(scene);
+ bkr.user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
+ //bkr.reports= op->reports;
/* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple);
@@ -414,6 +420,8 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
bkj->raytrace_structure = scene->r.raytrace_structure;
bkj->octree_resolution = scene->r.ocres;
bkj->threads = BKE_scene_num_threads(scene);
+ bkj->user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
+ //bkj->reports = op->reports;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
@@ -453,7 +461,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
if (bkj->mode == RE_BAKE_NORMALS) {
clear_flag = CLEAR_TANGENT_NORMAL;
}
- else if (bkj->mode == RE_BAKE_DISPLACEMENT) {
+ else if (ELEM(bkj->mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) {
clear_flag = CLEAR_DISPLACEMENT;
}
@@ -468,6 +476,8 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
bkr.bake_filter = bkj->bake_filter;
bkr.mode = bkj->mode;
bkr.use_lores_mesh = bkj->use_lores_mesh;
+ bkr.user_scale = bkj->user_scale;
+ //bkr.reports = bkj->reports;
/* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
bkr.lores_dm = data->lores_dm;
@@ -773,7 +783,7 @@ static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), const
static int is_multires_bake(Scene *scene)
{
- if (ELEM3(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_AO))
+ if (ELEM4(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_AO))
return scene->r.bake_flag & R_BAKE_MULTIRES;
return 0;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 96144d13519..bd4c2e997fe 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -1471,12 +1471,14 @@ static EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED(
ob = CTX_data_active_object(C);
if (ob) {
+ const bool use_mode_particle_edit = (ob->particlesystem.first != NULL) || (ob->soft != NULL) ||
+ (modifiers_findByType(ob, eModifierType_Cloth) != NULL);
while (input->identifier) {
if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
(input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
- (input->value == OB_MODE_PARTICLE_EDIT && ob->particlesystem.first) ||
- ((input->value == OB_MODE_SCULPT || input->value == OB_MODE_VERTEX_PAINT ||
- input->value == OB_MODE_WEIGHT_PAINT || input->value == OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
+ (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
+ (ELEM4(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT,
+ OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
(input->value == OB_MODE_OBJECT))
{
RNA_enum_item_add(&item, &totitem, input);
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 1f52346222c..a9fd3ce1288 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -289,7 +289,7 @@ void GROUP_OT_objects_remove_all(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Remove From All Groups";
- ot->description = "Remove selected objects from all groups or a selected group";
+ ot->description = "Remove selected objects from all groups";
ot->idname = "GROUP_OT_objects_remove_all";
/* api callbacks */
@@ -335,7 +335,7 @@ void GROUP_OT_objects_remove(wmOperatorType *ot)
/* identifiers */
ot->name = "Remove From Group";
- ot->description = "Remove selected objects from all groups or a selected group";
+ ot->description = "Remove selected objects from a group";
ot->idname = "GROUP_OT_objects_remove";
/* api callbacks */
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 5b20489c9cb..37656f82b25 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -569,7 +569,7 @@ void OBJECT_OT_hook_add_selob(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Hook to Selected Object";
- ot->description = "Hook selected vertices to the first selected Object";
+ ot->description = "Hook selected vertices to the first selected object";
ot->idname = "OBJECT_OT_hook_add_selob";
/* api callbacks */
@@ -603,7 +603,7 @@ void OBJECT_OT_hook_add_newob(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Hook to New Object";
- ot->description = "Hook selected vertices to the first selected Object";
+ ot->description = "Hook selected vertices to a newly created object";
ot->idname = "OBJECT_OT_hook_add_newob";
/* api callbacks */
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 917f816d6b1..d6c365e9247 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -47,6 +47,7 @@
#include "DNA_scene_types.h"
#include "DNA_particle_types.h"
+#include "BLI_alloca.h"
#include "BLI_array.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -1480,7 +1481,7 @@ bool *ED_vgroup_subset_from_select_type(Object *ob, eVGroupSelect subset_type, i
const int def_nr_active = ob->actdef - 1;
vgroup_validmap = MEM_mallocN(*r_vgroup_tot * sizeof(*vgroup_validmap), __func__);
memset(vgroup_validmap, false, *r_vgroup_tot * sizeof(*vgroup_validmap));
- if (def_nr_active < *r_vgroup_tot) {
+ if ((def_nr_active >= 0) && (def_nr_active < *r_vgroup_tot)) {
*r_subset_count = 1;
vgroup_validmap[def_nr_active] = true;
}
@@ -2000,7 +2001,11 @@ static void vgroup_levels_subset(Object *ob, const bool *vgroup_validmap, const
}
}
-static void vgroup_normalize_all(Object *ob, const bool lock_active)
+static void vgroup_normalize_all(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int subset_count,
+ const bool lock_active)
{
MDeformVert *dv, **dvert_array = NULL;
int i, dvert_tot = 0;
@@ -2008,7 +2013,7 @@ static void vgroup_normalize_all(Object *ob, const bool lock_active)
const int use_vert_sel = vertex_group_use_vert_sel(ob);
- if (lock_active && !BLI_findlink(&ob->defbase, def_nr)) {
+ if ((lock_active && !BLI_findlink(&ob->defbase, def_nr)) || subset_count == 0) {
return;
}
@@ -2029,13 +2034,15 @@ static void vgroup_normalize_all(Object *ob, const bool lock_active)
/* in case its not selected */
if ((dv = dvert_array[i])) {
if (lock_flags) {
- defvert_normalize_lock_map(dv, lock_flags, defbase_tot);
+ defvert_normalize_lock_map(dv, vgroup_validmap, vgroup_tot,
+ lock_flags, defbase_tot);
}
else if (lock_active) {
- defvert_normalize_lock_single(dv, def_nr);
+ defvert_normalize_lock_single(dv, vgroup_validmap, vgroup_tot,
+ def_nr);
}
else {
- defvert_normalize(dv);
+ defvert_normalize_subset(dv, vgroup_validmap, vgroup_tot);
}
}
}
@@ -2262,7 +2269,8 @@ static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const i
MEM_freeN(emap_mem);
}
- MEM_freeN(dvert_array);
+ if (dvert_array)
+ MEM_freeN(dvert_array);
BLI_SMALLSTACK_FREE(dv_stack);
/* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */
@@ -2270,7 +2278,8 @@ static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const i
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true);
ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot,
vgroup_validmap, vgroup_tot);
- MEM_freeN(dvert_array);
+ if (dvert_array)
+ MEM_freeN(dvert_array);
}
}
@@ -3471,8 +3480,13 @@ static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
bool lock_active = RNA_boolean_get(op->ptr, "lock_active");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- vgroup_normalize_all(ob, lock_active);
+ int subset_count, vgroup_tot;
+
+ const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_normalize_all(ob, vgroup_validmap, vgroup_tot, subset_count, lock_active);
+ MEM_freeN((void *)vgroup_validmap);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -3496,6 +3510,7 @@ void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ vgroup_operator_subset_select_props(ot, false);
RNA_def_boolean(ot->srna, "lock_active", true, "Lock Active",
"Keep the values of the active group while normalizing others");
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 1a561efd217..b0e19d04e35 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -4421,7 +4421,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
ParticleSystem *psys = psys_get_current(ob);
if (psys->edit) {
- if (psys->edit->edited || 1) { // XXX okee("Lose changes done in particle mode?"))
+ if (psys->edit->edited || 1) {
PE_free_ptcache_edit(psys->edit);
psys->edit = NULL;
@@ -4447,6 +4447,11 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
+static int clear_edited_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return WM_operator_confirm_message(C, op, "Lose changes done in particle mode? (no undo)");
+}
+
void PARTICLE_OT_edited_clear(wmOperatorType *ot)
{
/* identifiers */
@@ -4457,6 +4462,7 @@ void PARTICLE_OT_edited_clear(wmOperatorType *ot)
/* api callbacks */
ot->exec = clear_edited_exec;
ot->poll = particle_edit_toggle_poll;
+ ot->invoke = clear_edited_invoke;
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 577d8af0caf..df8d5ec4e84 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -1152,7 +1152,7 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
/* Try using GLSL display transform. */
if (force_fallback == false) {
- if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, true, false)) {
+ if (IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, true)) {
glEnable(GL_BLEND);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_FLOAT,
@@ -1170,7 +1170,7 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
"render_view3d_draw");
IMB_colormanagement_buffer_make_display_space(rres.rectf, display_buffer, rres.rectx, rres.recty,
- 4, dither, NULL, &scene->display_settings);
+ 4, dither, &scene->view_settings, &scene->display_settings);
glEnable(GL_BLEND);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index cdebbf4e103..21074bdc47c 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -517,7 +517,7 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
return 1;
}
-static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
+static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
OGLRender *oglrender = op->customdata;
@@ -549,12 +549,9 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);
if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
- printf("skipping existing frame \"%s\"\n", name);
-
- /* go to next frame */
- oglrender->nfra += scene->r.frame_step;
-
- return 1;
+ BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name);
+ ok = true;
+ goto finally;
}
}
@@ -656,6 +653,9 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
/* movie stats prints have no line break */
printf("\n");
+
+finally: /* Step the frame and bail early if needed */
+
/* go to next frame */
oglrender->nfra += scene->r.frame_step;
@@ -673,7 +673,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent
{
OGLRender *oglrender = op->customdata;
int anim = RNA_boolean_get(op->ptr, "animation");
- int ret;
+ bool ret;
switch (event->type) {
case ESCKEY:
@@ -698,11 +698,12 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent
screen_opengl_render_end(C, op->customdata);
return OPERATOR_FINISHED;
}
- else
+ else {
ret = screen_opengl_render_anim_step(C, op);
+ }
/* stop at the end or on error */
- if (ret == 0) {
+ if (ret == false) {
return OPERATOR_FINISHED;
}
@@ -750,7 +751,7 @@ static int screen_opengl_render_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
else {
- int ret = 1;
+ bool ret = true;
if (!screen_opengl_render_anim_initialize(C, op))
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 58c244228ed..553a543390f 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -588,6 +588,20 @@ void SCENE_OT_render_layer_remove(wmOperatorType *ot)
#ifdef WITH_FREESTYLE
+static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports)
+{
+ if (!lineset) {
+ BKE_report(reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ return false;
+ }
+ if (!lineset->linestyle) {
+ BKE_report(reports, RPT_ERROR, "The active lineset does not have a line style (indicating data corruption)");
+ return false;
+ }
+
+ return true;
+}
+
static int freestyle_active_module_poll(bContext *C)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
@@ -860,8 +874,13 @@ static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
return OPERATOR_CANCELLED;
}
- lineset->linestyle->id.us--;
- lineset->linestyle = BKE_copy_linestyle(lineset->linestyle);
+ if (lineset->linestyle) {
+ lineset->linestyle->id.us--;
+ lineset->linestyle = BKE_copy_linestyle(lineset->linestyle);
+ }
+ else {
+ lineset->linestyle = BKE_new_linestyle("LineStyle", NULL);
+ }
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
@@ -890,10 +909,10 @@ static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
int type = RNA_enum_get(op->ptr, "type");
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
+
if (BKE_add_linestyle_color_modifier(lineset->linestyle, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
return OPERATOR_CANCELLED;
@@ -929,10 +948,10 @@ static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
int type = RNA_enum_get(op->ptr, "type");
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
+
if (BKE_add_linestyle_alpha_modifier(lineset->linestyle, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
return OPERATOR_CANCELLED;
@@ -968,10 +987,10 @@ static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
int type = RNA_enum_get(op->ptr, "type");
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
+
if (BKE_add_linestyle_thickness_modifier(lineset->linestyle, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
return OPERATOR_CANCELLED;
@@ -1007,10 +1026,10 @@ static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
int type = RNA_enum_get(op->ptr, "type");
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
+
if (BKE_add_linestyle_geometry_modifier(lineset->linestyle, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
return OPERATOR_CANCELLED;
@@ -1060,8 +1079,7 @@ static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
LineStyleModifier *modifier = ptr.data;
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
@@ -1110,8 +1128,7 @@ static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
LineStyleModifier *modifier = ptr.data;
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
@@ -1161,8 +1178,7 @@ static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
LineStyleModifier *modifier = ptr.data;
int dir = RNA_enum_get(op->ptr, "direction");
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 13befeceee9..d356c3d8de3 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -531,7 +531,7 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
components = 4;
else if (format == GL_RGB)
components = 3;
- else if (format == GL_LUMINANCE)
+ else if (ELEM(format, GL_LUMINANCE, GL_ALPHA))
components = 1;
else {
BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled");
@@ -1091,18 +1091,15 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
if (ibuf->rect_float) {
if (ibuf->float_colorspace) {
ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- ibuf->float_colorspace,
- true, false);
+ ibuf->float_colorspace, true);
}
else {
- ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings,
- true, false);
+ ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, true);
}
}
else {
ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- ibuf->rect_colorspace,
- false, false);
+ ibuf->rect_colorspace, false);
}
if (ok) {
@@ -1160,57 +1157,3 @@ void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int
glaDrawImBuf_glsl(ibuf, x, y, zoomfilter, view_settings, display_settings);
}
-
-/* Transform buffer from role to scene linear space using GLSL OCIO conversion
- *
- * See IMB_colormanagement_setup_transform_from_role_glsl description for
- * some more details
- *
- * NOTE: this only works for RGBA buffers!
- */
-int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role)
-{
- GPUOffScreen *ofs;
- char err_out[256];
- rcti display_rect;
-
- ofs = GPU_offscreen_create(width, height, err_out);
-
- if (!ofs)
- return FALSE;
-
- GPU_offscreen_bind(ofs);
-
- if (!IMB_colormanagement_setup_transform_from_role_glsl(role, true)) {
- GPU_offscreen_unbind(ofs);
- GPU_offscreen_free(ofs);
- return FALSE;
- }
-
- BLI_rcti_init(&display_rect, 0, width, 0, height);
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
-
- glaDefine2DArea(&display_rect);
-
- glaDrawPixelsTex(0, 0, width, height, GL_RGBA, GL_FLOAT,
- GL_NEAREST, buffer);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, buffer);
-
- IMB_colormanagement_finish_glsl_transform();
-
- /* unbind */
- GPU_offscreen_unbind(ofs);
- GPU_offscreen_free(ofs);
-
- return TRUE;
-}
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index 40447a0106a..dbe1197436b 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -85,7 +85,7 @@ static void screenshot_read_pixels(int x, int y, int w, int h, unsigned char *re
glFinish();
/* clear alpha, it is not set to a meaningful value in opengl */
- for (i = 0, rect += 3; i < w*h; i++, rect += 4)
+ for (i = 0, rect += 3; i < w * h; i++, rect += 4)
*rect = 255;
}
@@ -327,7 +327,7 @@ static void screenshot_updatejob(void *sjv)
if (sj->dumprect == NULL) {
dumprect = MEM_mallocN(sizeof(int) * sj->dumpsx * sj->dumpsy, "dumprect");
- screenshot_read_pixels(sj->x, sj->y, sj->dumpsx, sj->dumpsy, (unsigned char*)dumprect);
+ screenshot_read_pixels(sj->x, sj->y, sj->dumpsx, sj->dumpsy, (unsigned char *)dumprect);
sj->dumprect = dumprect;
}
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index c18afd066fa..56143d00afe 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -73,12 +73,38 @@ typedef struct TexSnapshot {
GLuint overlay_texture;
int winx;
int winy;
- bool init;
int old_size;
float old_zoom;
bool old_col;
} TexSnapshot;
+typedef struct CursorSnapshot {
+ GLuint overlay_texture;
+ int size;
+ int zoom;
+} CursorSnapshot;
+
+static TexSnapshot primary_snap = {0};
+static TexSnapshot secondary_snap = {0};
+static CursorSnapshot cursor_snap = {0};
+
+/* delete overlay cursor textures to preserve memory and invalidate all overlay flags */
+void paint_cursor_delete_textures(void)
+{
+ if (primary_snap.overlay_texture)
+ glDeleteTextures(1, &primary_snap.overlay_texture);
+ if (secondary_snap.overlay_texture)
+ glDeleteTextures(1, &secondary_snap.overlay_texture);
+ if (cursor_snap.overlay_texture)
+ glDeleteTextures(1, &cursor_snap.overlay_texture);
+
+ memset(&primary_snap, 0, sizeof(TexSnapshot));
+ memset(&secondary_snap, 0, sizeof(TexSnapshot));
+ memset(&cursor_snap, 0, sizeof(CursorSnapshot));
+
+ BKE_paint_invalidate_overlay_all();
+}
+
static int same_tex_snap(TexSnapshot *snap, MTex *mtex, ViewContext *vc, bool col, float zoom)
{
return (/* make brush smaller shouldn't cause a resample */
@@ -103,9 +129,7 @@ static void make_tex_snap(TexSnapshot *snap, ViewContext *vc, float zoom)
static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool primary)
{
- static int init = 0;
- static TexSnapshot primary_snap = {0};
- static TexSnapshot secondary_snap = {0};
+ bool init;
TexSnapshot *target;
MTex *mtex = (primary) ? &br->mtex : &br->mask_mtex;
@@ -120,12 +144,14 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
(overlay_flags & PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY);
target = (primary) ? &primary_snap : &secondary_snap;
-
+
refresh =
!target->overlay_texture ||
(invalid != 0) ||
!same_tex_snap(target, mtex, vc, col, zoom);
+ init = (target->overlay_texture != 0);
+
if (refresh) {
struct ImagePool *pool = NULL;
/* stencil is rotated later */
@@ -160,7 +186,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
target->overlay_texture = 0;
}
- init = 0;
+ init = false;
target->old_size = size;
}
@@ -267,7 +293,6 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
if (refresh) {
if (!init || (target->old_col != col)) {
glTexImage2D(GL_TEXTURE_2D, 0, format, size, size, 0, format, GL_UNSIGNED_BYTE, buffer);
- init = 1;
}
else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, format, GL_UNSIGNED_BYTE, buffer);
@@ -297,10 +322,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
{
- static GLuint overlay_texture = 0;
- static int init = 0;
- static int old_size = -1;
- static int old_zoom = -1;
+ bool init;
OverlayControlFlags overlay_flags = BKE_paint_get_overlay_flags();
GLubyte *buffer = NULL;
@@ -310,14 +332,16 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
int refresh;
refresh =
- !overlay_texture ||
+ !cursor_snap.overlay_texture ||
(overlay_flags & PAINT_INVALID_OVERLAY_CURVE) ||
- old_zoom != zoom;
+ cursor_snap.zoom != zoom;
+
+ init = (cursor_snap.overlay_texture != 0);
if (refresh) {
int s, r;
- old_zoom = zoom;
+ cursor_snap.zoom = zoom;
s = BKE_brush_size_get(vc->scene, br);
r = 1;
@@ -330,18 +354,18 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
if (size < 256)
size = 256;
- if (size < old_size)
- size = old_size;
+ if (size < cursor_snap.size)
+ size = cursor_snap.size;
- if (old_size != size) {
- if (overlay_texture) {
- glDeleteTextures(1, &overlay_texture);
- overlay_texture = 0;
+ if (cursor_snap.size != size) {
+ if (cursor_snap.overlay_texture) {
+ glDeleteTextures(1, &cursor_snap.overlay_texture);
+ cursor_snap.overlay_texture = 0;
}
- init = 0;
+ init = false;
- old_size = size;
+ cursor_snap.size = size;
}
buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
@@ -383,19 +407,18 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
}
}
- if (!overlay_texture)
- glGenTextures(1, &overlay_texture);
+ if (!cursor_snap.overlay_texture)
+ glGenTextures(1, &cursor_snap.overlay_texture);
}
else {
- size = old_size;
+ size = cursor_snap.size;
}
- glBindTexture(GL_TEXTURE_2D, overlay_texture);
+ glBindTexture(GL_TEXTURE_2D, cursor_snap.overlay_texture);
if (refresh) {
if (!init) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, size, size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
- init = 1;
}
else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index feff02fa121..a5d4ff98b4b 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -792,6 +792,7 @@ static void toggle_paint_cursor(bContext *C, int enable)
if (settings->imapaint.paintcursor && !enable) {
WM_paint_cursor_end(wm, settings->imapaint.paintcursor);
settings->imapaint.paintcursor = NULL;
+ paint_cursor_delete_textures();
}
else if (enable)
paint_cursor_start(C, image_paint_poll);
@@ -820,6 +821,9 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings)
paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll);
}
+ else {
+ paint_cursor_delete_textures();
+ }
}
/************************ grab clone operator ************************/
@@ -922,9 +926,15 @@ void PAINT_OT_grab_clone(wmOperatorType *ot)
}
/******************** sample color operator ********************/
+typedef struct {
+ bool show_cursor;
+ short event_type;
+} SampleColorData;
+
static int sample_color_exec(bContext *C, wmOperator *op)
{
- Brush *brush = image_paint_brush(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *brush = BKE_paint_brush(paint);
ARegion *ar = CTX_wm_region(C);
int location[2];
@@ -938,11 +948,17 @@ static int sample_color_exec(bContext *C, wmOperator *op)
static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ SampleColorData *data = MEM_mallocN(sizeof(SampleColorData), "sample color custom data");
+
+ data->event_type = event->type;
+ data->show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
+ op->customdata = data;
+ paint->flags &= ~PAINT_SHOW_BRUSH;
+
RNA_int_set_array(op->ptr, "location", event->mval);
sample_color_exec(C, op);
- op->customdata = SET_INT_IN_POINTER(event->type);
-
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
@@ -950,8 +966,18 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event
static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type == (intptr_t)(op->customdata) && event->val == KM_RELEASE)
+ SampleColorData *data = op->customdata;
+
+ if ((event->type == data->event_type) && (event->val == KM_RELEASE)) {
+ Paint *paint = BKE_paint_get_active_from_context(C);
+
+ if(data->show_cursor) {
+ paint->flags |= PAINT_SHOW_BRUSH;
+ }
+
+ MEM_freeN(data);
return OPERATOR_FINISHED;
+ }
switch (event->type) {
case MOUSEMOVE:
@@ -963,24 +989,9 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-/* same as image_paint_poll but fail when face mask mode is enabled */
-static int image_paint_sample_color_poll(bContext *C)
+static int sample_color_poll(bContext *C)
{
- if (image_paint_poll(C)) {
- if (CTX_wm_view3d(C)) {
- Object *obact = CTX_data_active_object(C);
- if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
- Mesh *me = BKE_mesh_from_object(obact);
- if (me) {
- return !(me->editflag & ME_EDIT_PAINT_FACE_SEL);
- }
- }
- }
-
- return 1;
- }
-
- return 0;
+ return (image_paint_poll(C) || vertex_paint_poll(C));
}
void PAINT_OT_sample_color(wmOperatorType *ot)
@@ -994,7 +1005,7 @@ void PAINT_OT_sample_color(wmOperatorType *ot)
ot->exec = sample_color_exec;
ot->invoke = sample_color_invoke;
ot->modal = sample_color_modal;
- ot->poll = image_paint_sample_color_poll;
+ ot->poll = sample_color_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index c90f9756707..4a2046f6682 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -3129,7 +3129,7 @@ static void project_paint_begin(ProjPaintState *ps)
ps->thread_tot = 1;
for (a = 0; a < ps->thread_tot; a++) {
- ps->arena_mt[a] = BLI_memarena_new(1 << 16, "project paint arena");
+ ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena");
}
arena = ps->arena_mt[0];
@@ -3841,10 +3841,10 @@ static void *do_projectpaint_thread(void *ph_v)
pos_ofs[0] = pos[0] - lastpos[0];
pos_ofs[1] = pos[1] - lastpos[1];
- smearArena = BLI_memarena_new(1 << 16, "paint smear arena");
+ smearArena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "paint smear arena");
}
else if (tool == PAINT_TOOL_SOFTEN) {
- softenArena = BLI_memarena_new(1 << 16, "paint soften arena");
+ softenArena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "paint soften arena");
}
/* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 6c13f6efb74..2545328ec65 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -74,6 +74,7 @@ bool paint_space_stroke_enabled(struct Brush *br, enum PaintMode mode);
bool paint_supports_dynamic_size(struct Brush *br, enum PaintMode mode);
bool paint_supports_dynamic_tex_coords(struct Brush *br, enum PaintMode mode);
bool paint_supports_smooth_stroke(struct Brush *br, enum PaintMode mode);
+bool paint_supports_texture(enum PaintMode mode);
bool paint_supports_jitter(enum PaintMode mode);
struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf);
@@ -86,6 +87,7 @@ void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data);
int paint_poll(struct bContext *C);
void paint_cursor_start(struct bContext *C, int (*poll)(struct bContext *C));
void paint_cursor_start_explicit(struct Paint *p, struct wmWindowManager *wm, int (*poll)(struct bContext *C));
+void paint_cursor_delete_textures(void);
/* paint_vertex.c */
int weight_paint_poll(struct bContext *C);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 0b0607babc1..8b038973831 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -728,9 +728,16 @@ static int stencil_control_modal(bContext *C, wmOperator *op, const wmEvent *eve
static int stencil_control_poll(bContext *C)
{
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *br = BKE_paint_brush(paint);
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
+
+ Paint *paint;
+ Brush *br;
+
+ if (!paint_supports_texture(mode))
+ return false;
+ paint = BKE_paint_get_active_from_context(C);
+ br = BKE_paint_brush(paint);
return (br &&
(br->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL ||
br->mask_mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL));
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 973f6555deb..b00b1c3ecff 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -572,6 +572,12 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
return true;
}
+bool paint_supports_texture(PaintMode mode)
+{
+ /* ommit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */
+ return ELEM4(mode, PAINT_SCULPT, PAINT_VERTEX, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D);
+}
+
/* return true if the brush size can change during paint (normally used for pressure) */
bool paint_supports_dynamic_tex_coords(Brush *br, PaintMode mode)
{
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index d376bd3180f..bfc431baea5 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -441,7 +441,7 @@ static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, const wm
void PAINT_OT_face_select_linked_pick(wmOperatorType *ot)
{
ot->name = "Select Linked Pick";
- ot->description = "Select linked faces";
+ ot->description = "Select linked faces under the cursor";
ot->idname = "PAINT_OT_face_select_linked_pick";
ot->invoke = paint_select_linked_pick_invoke;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 538e8394b1f..1c3caf5d8bc 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -2062,6 +2062,8 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
/* weight paint spesific */
mesh_octree_table(NULL, NULL, NULL, 'e');
mesh_mirrtopo_table(NULL, 'e');
+
+ paint_cursor_delete_textures();
}
else {
ob->mode |= mode_flag;
@@ -2684,6 +2686,8 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
BKE_mesh_flush_select_from_polys(me);
}
+
+ paint_cursor_delete_textures();
}
else {
ob->mode |= mode_flag;
@@ -2784,7 +2788,7 @@ static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me)
int *origIndex;
int i;
- vd->polyfacemap_arena = BLI_memarena_new(1 << 13, "vpaint tmp");
+ vd->polyfacemap_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "vpaint tmp");
BLI_memarena_use_calloc(vd->polyfacemap_arena);
vd->polyfacemap = BLI_memarena_alloc(vd->polyfacemap_arena, sizeof(ListBase) * me->totpoly);
@@ -3480,7 +3484,7 @@ void PAINT_OT_weight_gradient(wmOperatorType *ot)
/* identifiers */
ot->name = "Weight Gradient";
ot->idname = "PAINT_OT_weight_gradient";
- ot->description = "Sample a line and show it in Scope panels";
+ ot->description = "Draw a line to apply a weight gradient to selected vertices";
/* api callbacks */
ot->invoke = paint_weight_gradient_invoke;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 3f58795cae4..2a6b6d4b3d9 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1791,6 +1791,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
/* offset with as much as possible factored in already */
mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius);
+ mul_v3_v3(offset, ss->cache->scale);
mul_v3_fl(offset, bstrength);
/* threaded loop over nodes */
@@ -1835,6 +1836,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
/* offset with as much as possible factored in already */
mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius);
+ mul_v3_v3(offset, ss->cache->scale);
mul_v3_fl(offset, bstrength);
/* we divide out the squared alpha and multiply by the squared crease to give us the pinch strength */
@@ -2263,7 +2265,8 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
if (vd.fno) copy_v3_v3(val, vd.fno);
else normal_short_to_float_v3(val, vd.no);
- mul_v3_v3fl(proxy[vd.i], val, fade * ss->cache->radius);
+ mul_v3_fl(val, fade * ss->cache->radius);
+ mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale);
if (vd.mvert)
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@@ -2642,7 +2645,8 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
displace = radius * offset;
- mul_v3_v3fl(temp, an, displace);
+ mul_v3_v3v3(temp, an, ss->cache->scale);
+ mul_v3_fl(temp, displace);
add_v3_v3(fc, temp);
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
@@ -2711,7 +2715,8 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
displace = radius * (0.25f + offset);
- mul_v3_v3fl(temp, an, displace);
+ mul_v3_v3v3(temp, an, ss->cache->scale);
+ mul_v3_fl(temp, displace);
add_v3_v3(fc, temp);
/* add_v3_v3v3(p, ss->cache->location, an); */
@@ -2798,7 +2803,8 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
displace = radius * (0.25f + offset);
- mul_v3_v3fl(temp, sn, displace);
+ mul_v3_v3v3(temp, sn, ss->cache->scale);
+ mul_v3_fl(temp, displace);
add_v3_v3(fc, temp);
/* init mat */
@@ -2877,7 +2883,8 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
displace = radius * offset;
- mul_v3_v3fl(temp, an, displace);
+ mul_v3_v3v3(temp, an, ss->cache->scale);
+ mul_v3_fl(temp, displace);
add_v3_v3(fc, temp);
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
@@ -2940,7 +2947,8 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
displace = -radius * offset;
- mul_v3_v3fl(temp, an, displace);
+ mul_v3_v3v3(temp, an, ss->cache->scale);
+ mul_v3_fl(temp, displace);
add_v3_v3(fc, temp);
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
@@ -3787,15 +3795,26 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
Object *ob = CTX_data_active_object(C);
float mat[3][3];
float viewDir[3] = {0.0f, 0.0f, 1.0f};
+ float max_scale;
int i;
int mode;
ss->cache = cache;
/* Set scaling adjustment */
- cache->scale[0] = 1.0f / ob->size[0];
- cache->scale[1] = 1.0f / ob->size[1];
- cache->scale[2] = 1.0f / ob->size[2];
+ if (brush->sculpt_tool == SCULPT_TOOL_LAYER) {
+ max_scale = 1.0f;
+ }
+ else {
+ max_scale = 0.0f;
+ for (i = 0; i < 3; i ++) {
+ max_scale = max_ff(max_scale, fabsf(ob->size[i]));
+ }
+ }
+ cache->scale[0] = max_scale / ob->size[0];
+ cache->scale[1] = max_scale / ob->size[1];
+ cache->scale[2] = max_scale / ob->size[2];
+
cache->plane_trim_squared = brush->plane_trim * brush->plane_trim;
@@ -4920,7 +4939,7 @@ int ED_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
if (mmd && !CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) {
GridPaintMask *gmask;
int level = max_ii(1, mmd->sculptlvl);
- int gridsize = ccg_gridsize(level);
+ int gridsize = BKE_ccg_gridsize(level);
int gridarea = gridsize * gridsize;
int i, j;
@@ -5020,6 +5039,8 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
ob->mode &= ~mode_flag;
free_sculptsession(ob);
+
+ paint_cursor_delete_textures();
}
else {
/* Enter sculptmode */
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index d630b6478fb..7a973d8c1ae 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -45,6 +45,7 @@
#include "BKE_brush.h"
#include "BKE_paint.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_depsgraph.h"
@@ -538,6 +539,8 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
op->customdata = data;
+ curvemapping_initialize(ts->uvsculpt->paint.brush->curve);
+
if (data) {
int counter = 0, i;
ARegion *ar = CTX_wm_region(C);
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 0d64a3ce594..f5db34d87d7 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -710,8 +710,14 @@ static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue, MovieClip
if (queue->direction > 0) {
current_frame = prefetch_find_uncached_frame(clip, queue->current_frame + 1, queue->end_frame,
queue->render_size, queue->render_flag, 1);
+ /* switch direction if read frames from current up to scene end frames */
+ if (current_frame >= queue->end_frame) {
+ queue->current_frame = queue->initial_frame;
+ queue->direction = -1;
+ }
}
- else {
+
+ if (queue->direction < 0) {
current_frame = prefetch_find_uncached_frame(clip, queue->current_frame - 1, queue->start_frame,
queue->render_size, queue->render_flag, -1);
}
@@ -736,12 +742,6 @@ static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue, MovieClip
*queue->do_update = 1;
*queue->progress = (float)frames_processed / (queue->end_frame - queue->start_frame);
-
- /* switch direction if read frames from current up to scene end frames */
- if (current_frame == queue->end_frame) {
- queue->current_frame = queue->initial_frame;
- queue->direction = -1;
- }
}
}
BLI_spin_unlock(&queue->spin);
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 3ede63adb72..adc902bf4ba 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -1191,7 +1191,9 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
int mask_width, mask_height;
ED_mask_get_size(sa, &mask_width, &mask_height);
ED_mask_draw_region(mask, ar,
- sc->mask_info.draw_flag, sc->mask_info.draw_type,
+ sc->mask_info.draw_flag,
+ sc->mask_info.draw_type,
+ sc->mask_info.overlay_mode,
mask_width, mask_height,
aspx, aspy,
TRUE, TRUE,
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index 88a04197847..5c8d1e84fd5 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -317,6 +317,7 @@ static void console_keymap(struct wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_PREV_WORD);
WM_keymap_add_item(keymap, "CONSOLE_OT_clear_line", RETKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "CONSOLE_OT_clear_line", PADENTER, KM_PRESS, KM_SHIFT, 0);
#ifdef WITH_PYTHON
kmi = WM_keymap_add_item(keymap, "CONSOLE_OT_execute", RETKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt
index b30f008e1bf..3b2db3ee7bc 100644
--- a/source/blender/editors/space_file/CMakeLists.txt
+++ b/source/blender/editors/space_file/CMakeLists.txt
@@ -58,6 +58,10 @@ if(WITH_IMAGE_OPENEXR)
add_definitions(-DWITH_OPENEXR)
endif()
+if(WITH_OPENIMAGEIO)
+ add_definitions(-DWITH_OPENIMAGEIO)
+endif()
+
if(WITH_IMAGE_TIFF)
add_definitions(-DWITH_TIFF)
endif()
diff --git a/source/blender/editors/space_file/SConscript b/source/blender/editors/space_file/SConscript
index e1eadb66a11..d42394454eb 100644
--- a/source/blender/editors/space_file/SConscript
+++ b/source/blender/editors/space_file/SConscript
@@ -55,6 +55,9 @@ if env['WITH_BF_OPENEXR']:
if env['WITH_BF_TIFF']:
defs.append('WITH_TIFF')
+if env['WITH_BF_OIIO']:
+ defs.append('WITH_OPENIMAGEIO')
+
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index 240106d37d5..d01286442be 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -65,7 +65,7 @@ void FILE_OT_select_all_toggle(struct wmOperatorType *ot);
void FILE_OT_select_border(struct wmOperatorType *ot);
void FILE_OT_select_bookmark(struct wmOperatorType *ot);
void FILE_OT_bookmark_add(struct wmOperatorType *ot);
-void FILE_OT_delete_bookmark(struct wmOperatorType *ot);
+void FILE_OT_bookmark_delete(struct wmOperatorType *ot);
void FILE_OT_reset_recent(wmOperatorType *ot);
void FILE_OT_hidedot(struct wmOperatorType *ot);
void FILE_OT_execute(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index e3270d9ce8e..a97b3b1d719 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -503,14 +503,14 @@ static int bookmark_delete_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void FILE_OT_delete_bookmark(wmOperatorType *ot)
+void FILE_OT_bookmark_delete(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Delete Bookmark";
ot->description = "Delete selected bookmark";
- ot->idname = "FILE_OT_delete_bookmark";
+ ot->idname = "FILE_OT_bookmark_delete";
/* api callbacks */
ot->exec = bookmark_delete_exec;
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index 0efc7b927a9..f4161c7da1c 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -121,7 +121,7 @@ static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory cat
/* create delete button */
if (allow_delete && fsmenu_can_save(fsmenu, category, i)) {
uiBlockSetEmboss(block, UI_EMBOSSN);
- uiItemIntO(layout, "", ICON_X, "FILE_OT_delete_bookmark", "index", i);
+ uiItemIntO(layout, "", ICON_X, "FILE_OT_bookmark_delete", "index", i);
uiBlockSetEmboss(block, UI_EMBOSS);
}
}
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 9758e2e9135..1a8565a58b1 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -387,7 +387,7 @@ static void file_operatortypes(void)
WM_operatortype_append(FILE_OT_refresh);
WM_operatortype_append(FILE_OT_bookmark_toggle);
WM_operatortype_append(FILE_OT_bookmark_add);
- WM_operatortype_append(FILE_OT_delete_bookmark);
+ WM_operatortype_append(FILE_OT_bookmark_delete);
WM_operatortype_append(FILE_OT_reset_recent);
WM_operatortype_append(FILE_OT_hidedot);
WM_operatortype_append(FILE_OT_filenum);
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 7610f7a9192..23c39a5e99a 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -951,7 +951,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
/* 1) draw curve line */
{
/* set color/drawing style for curve itself */
- if (((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || (fcu->flag & FCURVE_PROTECTED)) {
+ if (BKE_fcurve_is_protected(fcu)) {
/* protected curves (non editable) are drawn with dotted lines */
setlinestyle(2);
}
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt
index 6509af179e7..50d8051a73e 100644
--- a/source/blender/editors/space_image/CMakeLists.txt
+++ b/source/blender/editors/space_image/CMakeLists.txt
@@ -50,6 +50,10 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_OPENIMAGEIO)
+ add_definitions(-DWITH_OPENIMAGEIO)
+endif()
+
if(WITH_IMAGE_OPENJPEG)
add_definitions(-DWITH_OPENJPEG)
endif()
diff --git a/source/blender/editors/space_image/SConscript b/source/blender/editors/space_image/SConscript
index 268172b300d..89def32e70f 100644
--- a/source/blender/editors/space_image/SConscript
+++ b/source/blender/editors/space_image/SConscript
@@ -57,6 +57,8 @@ if env['WITH_BF_TIFF']:
defs.append('WITH_TIFF')
if env['WITH_BF_CINEON']:
defs.append('WITH_CINEON')
+if env['WITH_BF_OIIO']:
+ defs.append('WITH_OPENIMAGEIO')
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 144d2c14e9f..3ff404d38a9 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -640,7 +640,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
else
uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
- row = uiLayoutRow(row, FALSE);
+ row = uiLayoutRow(row, TRUE);
uiLayoutSetEnabled(row, ima->packedfile == NULL);
uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 23c85699b00..89e57955339 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -268,8 +268,6 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
else
rgba[3] = linearcol[3];
- (void)color_manage;
-
if (use_default_view)
IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings);
else
@@ -360,14 +358,8 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
dx += BLF_width(blf_mono_font, str);
}
else if (channels >= 3) {
- if (fp) {
- rgb_to_hsv(fp[0], fp[1], fp[2], &hue, &sat, &val);
- rgb_to_yuv(fp[0], fp[1], fp[2], &lum, &u, &v);
- }
- else if (cp) {
- rgb_to_hsv((float)cp[0] / 255.0f, (float)cp[1] / 255.0f, (float)cp[2] / 255.0f, &hue, &sat, &val);
- rgb_to_yuv((float)cp[0] / 255.0f, (float)cp[1] / 255.0f, (float)cp[2] / 255.0f, &lum, &u, &v);
- }
+ rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val);
+ rgb_to_yuv(finalcol[0], finalcol[1], finalcol[2], &lum, &u, &v);
BLI_snprintf(str, sizeof(str), "H:%-.4f", hue);
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 2da109d281b..710d5c8cd81 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1804,7 +1804,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+ WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
return OPERATOR_FINISHED;
}
@@ -2417,6 +2417,9 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
hist->co[1][0] = x2f;
hist->co[1][1] = y2f;
+ /* enable line drawing */
+ hist->flag |= HISTO_FLAG_SAMPLELINE;
+
BKE_histogram_update_sample_line(hist, ibuf, &scene->view_settings, &scene->display_settings);
/* reset y zoom */
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 5a8292abcab..7b20af340ae 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -674,7 +674,6 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
}
else if (sima->mode == SI_MODE_MASK) {
mask = ED_space_image_get_mask(sima);
- draw_image_cursor(ar, sima->cursor);
}
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
@@ -715,7 +714,9 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
BLI_unlock_thread(LOCK_DRAW_IMAGE);
ED_mask_draw_region(mask, ar,
- sima->mask_info.draw_flag, sima->mask_info.draw_type,
+ sima->mask_info.draw_flag,
+ sima->mask_info.draw_type,
+ sima->mask_info.overlay_mode,
width, height,
aspx, aspy,
TRUE, FALSE,
@@ -723,7 +724,9 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
ED_mask_draw_frames(mask, ar, CFRA, mask->sfra, mask->efra);
+ UI_view2d_view_ortho(v2d);
draw_image_cursor(ar, sima->cursor);
+ UI_view2d_view_restore(C);
}
/* scrollers? */
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index c1cddf092aa..9686c6dfc29 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -194,9 +194,9 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
a = nu->pntsu;
while (a--) {
stats->totvert += 3;
- if (bezt->f1) stats->totvertsel++;
- if (bezt->f2) stats->totvertsel++;
- if (bezt->f3) stats->totvertsel++;
+ if (bezt->f1 & SELECT) stats->totvertsel++;
+ if (bezt->f2 & SELECT) stats->totvertsel++;
+ if (bezt->f3 & SELECT) stats->totvertsel++;
bezt++;
}
}
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 913e48ebb7d..ba28f502349 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -86,18 +86,6 @@ static void node_socket_button_label(bContext *UNUSED(C), uiLayout *layout, Poin
uiItemL(layout, text, 0);
}
-static void node_draw_input_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr)
-{
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- sock->typeinfo->draw(C, layout, ptr, node_ptr, IFACE_(sock->name));
-}
-
-static void node_draw_output_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr)
-{
- bNodeSocket *sock = ptr->data;
- node_socket_button_label(C, layout, ptr, node_ptr, IFACE_(sock->name));
-}
-
/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
@@ -339,7 +327,7 @@ static int node_resize_area_default(bNode *node, int x, int y)
/* ****************** BUTTON CALLBACKS FOR COMMON NODES ***************** */
-static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
+static void node_draw_buttons_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
uiTemplateIDBrowse(layout, C, ptr, "node_tree", NULL, NULL, NULL);
}
@@ -348,7 +336,7 @@ static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
* Not ideal to do this in every draw call, but doing as transform callback doesn't work,
* since the child node totr rects are not updated properly at that point.
*/
-static void node_update_frame(const bContext *UNUSED(C), bNodeTree *ntree, bNode *node)
+static void node_draw_frame_prepare(const bContext *UNUSED(C), bNodeTree *ntree, bNode *node)
{
const float margin = 1.5f * U.widget_unit;
NodeFrame *data = (NodeFrame *)node->storage;
@@ -511,7 +499,7 @@ static int node_resize_area_frame(bNode *node, int x, int y)
return dir;
}
-static void node_buts_frame_details(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_buts_frame_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "label_size", 0, IFACE_("Label Size"), ICON_NONE);
uiItemR(layout, ptr, "shrink", 0, IFACE_("Shrink"), ICON_NONE);
@@ -520,7 +508,7 @@ static void node_buts_frame_details(uiLayout *layout, bContext *UNUSED(C), Point
#define NODE_REROUTE_SIZE 8.0f
-static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntree), bNode *node)
+static void node_draw_reroute_prepare(const bContext *UNUSED(C), bNodeTree *UNUSED(ntree), bNode *node)
{
bNodeSocket *nsock;
float locx, locy;
@@ -571,7 +559,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
*/
#if 0
/* body */
- uiSetRoundBox(15);
+ uiSetRoundBox(UI_CNR_ALL);
UI_ThemeColor4(TH_NODE);
glEnable(GL_BLEND);
uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
@@ -632,17 +620,17 @@ static void node_common_set_butfunc(bNodeType *ntype)
{
switch (ntype->type) {
case NODE_GROUP:
- ntype->uifunc = node_uifunc_group;
+ ntype->draw_buttons = node_draw_buttons_group;
break;
case NODE_FRAME:
- ntype->drawfunc = node_draw_frame;
- ntype->drawupdatefunc = node_update_frame;
- ntype->uifuncbut = node_buts_frame_details;
+ ntype->draw_nodetype = node_draw_frame;
+ ntype->draw_nodetype_prepare = node_draw_frame_prepare;
+ ntype->draw_buttons_ex = node_buts_frame_ex;
ntype->resize_area_func = node_resize_area_frame;
break;
case NODE_REROUTE:
- ntype->drawfunc = node_draw_reroute;
- ntype->drawupdatefunc = node_update_reroute;
+ ntype->draw_nodetype = node_draw_reroute;
+ ntype->draw_nodetype_prepare = node_draw_reroute_prepare;
ntype->tweak_area_func = node_tweak_area_reroute;
break;
}
@@ -709,7 +697,7 @@ static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), Poin
{
uiLayout *row;
- uiItemR(layout, ptr, "type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
uiItemL(layout, IFACE_("Location:"), ICON_NONE);
row = uiLayoutRow(layout, TRUE);
@@ -739,7 +727,7 @@ static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), Po
static void node_shader_buts_vect_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
uiItemR(layout, ptr, "convert_from", 0, "", ICON_NONE);
uiItemR(layout, ptr, "convert_to", 0, "", ICON_NONE);
}
@@ -792,7 +780,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr);
}
-static void node_shader_buts_tex_image_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
+static void node_shader_buts_tex_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0);
@@ -920,7 +908,7 @@ static void node_shader_buts_subsurface(uiLayout *layout, bContext *C, PointerRN
if (scene.data) {
PointerRNA cscene = RNA_pointer_get(&scene, "cycles");
if (cscene.data && RNA_enum_get(&cscene, "device") == 1)
- uiItemL(layout, IFACE_("SSS not supported on GPU"), ICON_NONE);
+ uiItemL(layout, IFACE_("SSS not supported on GPU"), ICON_ERROR);
}
uiItemR(layout, ptr, "falloff", 0, "", ICON_NONE);
@@ -953,7 +941,7 @@ static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), Point
uiItemO(row, "", ICON_FILE_REFRESH, "node.shader_script_update");
}
-static void node_shader_buts_script_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
+static void node_shader_buts_script_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
uiItemS(layout);
@@ -971,110 +959,110 @@ static void node_shader_set_butfunc(bNodeType *ntype)
switch (ntype->type) {
case SH_NODE_MATERIAL:
case SH_NODE_MATERIAL_EXT:
- ntype->uifunc = node_shader_buts_material;
+ ntype->draw_buttons = node_shader_buts_material;
break;
case SH_NODE_TEXTURE:
- ntype->uifunc = node_buts_texture;
+ ntype->draw_buttons = node_buts_texture;
break;
case SH_NODE_NORMAL:
- ntype->uifunc = node_buts_normal;
+ ntype->draw_buttons = node_buts_normal;
break;
case SH_NODE_CURVE_VEC:
- ntype->uifunc = node_buts_curvevec;
+ ntype->draw_buttons = node_buts_curvevec;
break;
case SH_NODE_CURVE_RGB:
- ntype->uifunc = node_buts_curvecol;
+ ntype->draw_buttons = node_buts_curvecol;
break;
case SH_NODE_MAPPING:
- ntype->uifunc = node_shader_buts_mapping;
+ ntype->draw_buttons = node_shader_buts_mapping;
break;
case SH_NODE_VALUE:
- ntype->uifunc = node_buts_value;
+ ntype->draw_buttons = node_buts_value;
break;
case SH_NODE_RGB:
- ntype->uifunc = node_buts_rgb;
+ ntype->draw_buttons = node_buts_rgb;
break;
case SH_NODE_MIX_RGB:
- ntype->uifunc = node_buts_mix_rgb;
+ ntype->draw_buttons = node_buts_mix_rgb;
break;
case SH_NODE_VALTORGB:
- ntype->uifunc = node_buts_colorramp;
+ ntype->draw_buttons = node_buts_colorramp;
break;
case SH_NODE_MATH:
- ntype->uifunc = node_buts_math;
+ ntype->draw_buttons = node_buts_math;
break;
case SH_NODE_VECT_MATH:
- ntype->uifunc = node_shader_buts_vect_math;
+ ntype->draw_buttons = node_shader_buts_vect_math;
break;
case SH_NODE_VECT_TRANSFORM:
- ntype->uifunc = node_shader_buts_vect_transform;
+ ntype->draw_buttons = node_shader_buts_vect_transform;
break;
case SH_NODE_GEOMETRY:
- ntype->uifunc = node_shader_buts_geometry;
+ ntype->draw_buttons = node_shader_buts_geometry;
break;
case SH_NODE_ATTRIBUTE:
- ntype->uifunc = node_shader_buts_attribute;
+ ntype->draw_buttons = node_shader_buts_attribute;
break;
case SH_NODE_WIREFRAME:
- ntype->uifunc = node_shader_buts_wireframe;
+ ntype->draw_buttons = node_shader_buts_wireframe;
break;
case SH_NODE_TEX_SKY:
- ntype->uifunc = node_shader_buts_tex_sky;
+ ntype->draw_buttons = node_shader_buts_tex_sky;
break;
case SH_NODE_TEX_IMAGE:
- ntype->uifunc = node_shader_buts_tex_image;
- ntype->uifuncbut = node_shader_buts_tex_image_details;
+ ntype->draw_buttons = node_shader_buts_tex_image;
+ ntype->draw_buttons_ex = node_shader_buts_tex_image_ex;
break;
case SH_NODE_TEX_ENVIRONMENT:
- ntype->uifunc = node_shader_buts_tex_environment;
+ ntype->draw_buttons = node_shader_buts_tex_environment;
break;
case SH_NODE_TEX_GRADIENT:
- ntype->uifunc = node_shader_buts_tex_gradient;
+ ntype->draw_buttons = node_shader_buts_tex_gradient;
break;
case SH_NODE_TEX_MAGIC:
- ntype->uifunc = node_shader_buts_tex_magic;
+ ntype->draw_buttons = node_shader_buts_tex_magic;
break;
case SH_NODE_TEX_BRICK:
- ntype->uifunc = node_shader_buts_tex_brick;
+ ntype->draw_buttons = node_shader_buts_tex_brick;
break;
case SH_NODE_TEX_WAVE:
- ntype->uifunc = node_shader_buts_tex_wave;
+ ntype->draw_buttons = node_shader_buts_tex_wave;
break;
case SH_NODE_TEX_MUSGRAVE:
- ntype->uifunc = node_shader_buts_tex_musgrave;
+ ntype->draw_buttons = node_shader_buts_tex_musgrave;
break;
case SH_NODE_TEX_VORONOI:
- ntype->uifunc = node_shader_buts_tex_voronoi;
+ ntype->draw_buttons = node_shader_buts_tex_voronoi;
break;
case SH_NODE_TEX_COORD:
- ntype->uifunc = node_shader_buts_tex_coord;
+ ntype->draw_buttons = node_shader_buts_tex_coord;
break;
case SH_NODE_BUMP:
- ntype->uifunc = node_shader_buts_bump;
+ ntype->draw_buttons = node_shader_buts_bump;
break;
case SH_NODE_NORMAL_MAP:
- ntype->uifunc = node_shader_buts_normal_map;
+ ntype->draw_buttons = node_shader_buts_normal_map;
break;
case SH_NODE_TANGENT:
- ntype->uifunc = node_shader_buts_tangent;
+ ntype->draw_buttons = node_shader_buts_tangent;
break;
case SH_NODE_BSDF_GLOSSY:
case SH_NODE_BSDF_GLASS:
case SH_NODE_BSDF_REFRACTION:
- ntype->uifunc = node_shader_buts_glossy;
+ ntype->draw_buttons = node_shader_buts_glossy;
break;
case SH_NODE_SUBSURFACE_SCATTERING:
- ntype->uifunc = node_shader_buts_subsurface;
+ ntype->draw_buttons = node_shader_buts_subsurface;
break;
case SH_NODE_BSDF_TOON:
- ntype->uifunc = node_shader_buts_toon;
+ ntype->draw_buttons = node_shader_buts_toon;
break;
case SH_NODE_BSDF_HAIR:
- ntype->uifunc = node_shader_buts_hair;
+ ntype->draw_buttons = node_shader_buts_hair;
break;
case SH_NODE_SCRIPT:
- ntype->uifunc = node_shader_buts_script;
- ntype->uifuncbut = node_shader_buts_script_details;
+ ntype->draw_buttons = node_shader_buts_script;
+ ntype->draw_buttons_ex = node_shader_buts_script_ex;
break;
}
}
@@ -1096,7 +1084,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr);
}
-static void node_composit_buts_image_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
+static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
bNode *node = ptr->data;
PointerRNA iuserptr;
@@ -1578,46 +1566,6 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po
uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE);
}
-/* draw function for file output node sockets, displays only sub-path and format, no value button */
-static void node_draw_input_file_output(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr)
-{
- bNodeTree *ntree = ptr->id.data;
- bNodeSocket *sock = ptr->data;
- uiLayout *row;
- PointerRNA inputptr, imfptr;
- int imtype;
-
- row = uiLayoutRow(layout, FALSE);
-
- imfptr = RNA_pointer_get(node_ptr, "format");
- imtype = RNA_enum_get(&imfptr, "file_format");
- if (imtype == R_IMF_IMTYPE_MULTILAYER) {
- NodeImageMultiFileSocket *input = sock->storage;
- RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr);
-
- uiItemL(row, input->layer, ICON_NONE);
- }
- else {
- NodeImageMultiFileSocket *input = sock->storage;
- PropertyRNA *imtype_prop;
- const char *imtype_name;
- uiBlock *block;
- RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr);
-
- uiItemL(row, input->path, ICON_NONE);
-
- if (!RNA_boolean_get(&inputptr, "use_node_format"))
- imfptr = RNA_pointer_get(&inputptr, "format");
-
- imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
- RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop,
- RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
- block = uiLayoutGetBlock(row);
- uiBlockSetEmboss(block, UI_EMBOSSP);
- uiItemL(row, imtype_name, ICON_NONE);
- uiBlockSetEmboss(block, UI_EMBOSSN);
- }
-}
static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
PointerRNA imfptr = RNA_pointer_get(ptr, "format");
@@ -1629,7 +1577,7 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C)
uiItemL(layout, IFACE_("Base Path:"), ICON_NONE);
uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE);
}
-static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
+static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
PointerRNA imfptr = RNA_pointer_get(ptr, "format");
PointerRNA active_input_ptr, op_ptr;
@@ -1787,7 +1735,7 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C
}
}
-static void node_composit_buts_colorbalance_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_composit_buts_colorbalance_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
@@ -1841,7 +1789,7 @@ static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerR
uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
}
-static void node_composit_buts_movieclip_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
+static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
bNode *node = ptr->data;
PointerRNA clipptr;
@@ -1945,7 +1893,7 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSE
uiItemR(row, ptr, "midtones_end", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
-static void node_composit_buts_colorcorrection_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_composit_buts_colorcorrection_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *row;
@@ -2147,7 +2095,7 @@ static void node_composit_buts_viewer(uiLayout *layout, bContext *UNUSED(C), Poi
uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE);
}
-static void node_composit_buts_viewer_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+static void node_composit_buts_viewer_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *col;
@@ -2295,222 +2243,221 @@ static void node_composit_set_butfunc(bNodeType *ntype)
{
switch (ntype->type) {
case CMP_NODE_IMAGE:
- ntype->uifunc = node_composit_buts_image;
- ntype->uifuncbut = node_composit_buts_image_details;
+ ntype->draw_buttons = node_composit_buts_image;
+ ntype->draw_buttons_ex = node_composit_buts_image_ex;
break;
case CMP_NODE_R_LAYERS:
- ntype->uifunc = node_composit_buts_renderlayers;
+ ntype->draw_buttons = node_composit_buts_renderlayers;
break;
case CMP_NODE_NORMAL:
- ntype->uifunc = node_buts_normal;
+ ntype->draw_buttons = node_buts_normal;
break;
case CMP_NODE_CURVE_VEC:
- ntype->uifunc = node_buts_curvevec;
+ ntype->draw_buttons = node_buts_curvevec;
break;
case CMP_NODE_CURVE_RGB:
- ntype->uifunc = node_buts_curvecol;
+ ntype->draw_buttons = node_buts_curvecol;
break;
case CMP_NODE_VALUE:
- ntype->uifunc = node_buts_value;
+ ntype->draw_buttons = node_buts_value;
break;
case CMP_NODE_RGB:
- ntype->uifunc = node_buts_rgb;
+ ntype->draw_buttons = node_buts_rgb;
break;
case CMP_NODE_FLIP:
- ntype->uifunc = node_composit_buts_flip;
+ ntype->draw_buttons = node_composit_buts_flip;
break;
case CMP_NODE_SPLITVIEWER:
- ntype->uifunc = node_composit_buts_splitviewer;
+ ntype->draw_buttons = node_composit_buts_splitviewer;
break;
case CMP_NODE_MIX_RGB:
- ntype->uifunc = node_buts_mix_rgb;
+ ntype->draw_buttons = node_buts_mix_rgb;
break;
case CMP_NODE_VALTORGB:
- ntype->uifunc = node_buts_colorramp;
+ ntype->draw_buttons = node_buts_colorramp;
break;
case CMP_NODE_CROP:
- ntype->uifunc = node_composit_buts_crop;
+ ntype->draw_buttons = node_composit_buts_crop;
break;
case CMP_NODE_BLUR:
- ntype->uifunc = node_composit_buts_blur;
+ ntype->draw_buttons = node_composit_buts_blur;
break;
case CMP_NODE_DBLUR:
- ntype->uifunc = node_composit_buts_dblur;
+ ntype->draw_buttons = node_composit_buts_dblur;
break;
case CMP_NODE_BILATERALBLUR:
- ntype->uifunc = node_composit_buts_bilateralblur;
+ ntype->draw_buttons = node_composit_buts_bilateralblur;
break;
case CMP_NODE_DEFOCUS:
- ntype->uifunc = node_composit_buts_defocus;
+ ntype->draw_buttons = node_composit_buts_defocus;
break;
case CMP_NODE_GLARE:
- ntype->uifunc = node_composit_buts_glare;
+ ntype->draw_buttons = node_composit_buts_glare;
break;
case CMP_NODE_TONEMAP:
- ntype->uifunc = node_composit_buts_tonemap;
+ ntype->draw_buttons = node_composit_buts_tonemap;
break;
case CMP_NODE_LENSDIST:
- ntype->uifunc = node_composit_buts_lensdist;
+ ntype->draw_buttons = node_composit_buts_lensdist;
break;
case CMP_NODE_VECBLUR:
- ntype->uifunc = node_composit_buts_vecblur;
+ ntype->draw_buttons = node_composit_buts_vecblur;
break;
case CMP_NODE_FILTER:
- ntype->uifunc = node_composit_buts_filter;
+ ntype->draw_buttons = node_composit_buts_filter;
break;
case CMP_NODE_MAP_VALUE:
- ntype->uifunc = node_composit_buts_map_value;
+ ntype->draw_buttons = node_composit_buts_map_value;
break;
case CMP_NODE_MAP_RANGE:
- ntype->uifunc = node_composit_buts_map_range;
+ ntype->draw_buttons = node_composit_buts_map_range;
break;
case CMP_NODE_TIME:
- ntype->uifunc = node_buts_time;
+ ntype->draw_buttons = node_buts_time;
break;
case CMP_NODE_ALPHAOVER:
- ntype->uifunc = node_composit_buts_alphaover;
+ ntype->draw_buttons = node_composit_buts_alphaover;
break;
case CMP_NODE_HUE_SAT:
- ntype->uifunc = node_composit_buts_hue_sat;
+ ntype->draw_buttons = node_composit_buts_hue_sat;
break;
case CMP_NODE_TEXTURE:
- ntype->uifunc = node_buts_texture;
+ ntype->draw_buttons = node_buts_texture;
break;
case CMP_NODE_DILATEERODE:
- ntype->uifunc = node_composit_buts_dilateerode;
+ ntype->draw_buttons = node_composit_buts_dilateerode;
break;
case CMP_NODE_INPAINT:
- ntype->uifunc = node_composit_buts_inpaint;
+ ntype->draw_buttons = node_composit_buts_inpaint;
break;
case CMP_NODE_DESPECKLE:
- ntype->uifunc = node_composit_buts_despeckle;
+ ntype->draw_buttons = node_composit_buts_despeckle;
break;
case CMP_NODE_OUTPUT_FILE:
- ntype->uifunc = node_composit_buts_file_output;
- ntype->uifuncbut = node_composit_buts_file_output_details;
- ntype->drawinputfunc = node_draw_input_file_output;
+ ntype->draw_buttons = node_composit_buts_file_output;
+ ntype->draw_buttons_ex = node_composit_buts_file_output_ex;
break;
case CMP_NODE_DIFF_MATTE:
- ntype->uifunc = node_composit_buts_diff_matte;
+ ntype->draw_buttons = node_composit_buts_diff_matte;
break;
case CMP_NODE_DIST_MATTE:
- ntype->uifunc = node_composit_buts_distance_matte;
+ ntype->draw_buttons = node_composit_buts_distance_matte;
break;
case CMP_NODE_COLOR_SPILL:
- ntype->uifunc = node_composit_buts_color_spill;
+ ntype->draw_buttons = node_composit_buts_color_spill;
break;
case CMP_NODE_CHROMA_MATTE:
- ntype->uifunc = node_composit_buts_chroma_matte;
+ ntype->draw_buttons = node_composit_buts_chroma_matte;
break;
case CMP_NODE_COLOR_MATTE:
- ntype->uifunc = node_composit_buts_color_matte;
+ ntype->draw_buttons = node_composit_buts_color_matte;
break;
case CMP_NODE_SCALE:
- ntype->uifunc = node_composit_buts_scale;
+ ntype->draw_buttons = node_composit_buts_scale;
break;
case CMP_NODE_ROTATE:
- ntype->uifunc = node_composit_buts_rotate;
+ ntype->draw_buttons = node_composit_buts_rotate;
break;
case CMP_NODE_CHANNEL_MATTE:
- ntype->uifunc = node_composit_buts_channel_matte;
+ ntype->draw_buttons = node_composit_buts_channel_matte;
break;
case CMP_NODE_LUMA_MATTE:
- ntype->uifunc = node_composit_buts_luma_matte;
+ ntype->draw_buttons = node_composit_buts_luma_matte;
break;
case CMP_NODE_MAP_UV:
- ntype->uifunc = node_composit_buts_map_uv;
+ ntype->draw_buttons = node_composit_buts_map_uv;
break;
case CMP_NODE_ID_MASK:
- ntype->uifunc = node_composit_buts_id_mask;
+ ntype->draw_buttons = node_composit_buts_id_mask;
break;
case CMP_NODE_DOUBLEEDGEMASK:
- ntype->uifunc = node_composit_buts_double_edge_mask;
+ ntype->draw_buttons = node_composit_buts_double_edge_mask;
break;
case CMP_NODE_MATH:
- ntype->uifunc = node_buts_math;
+ ntype->draw_buttons = node_buts_math;
break;
case CMP_NODE_INVERT:
- ntype->uifunc = node_composit_buts_invert;
+ ntype->draw_buttons = node_composit_buts_invert;
break;
case CMP_NODE_PREMULKEY:
- ntype->uifunc = node_composit_buts_premulkey;
+ ntype->draw_buttons = node_composit_buts_premulkey;
break;
case CMP_NODE_VIEW_LEVELS:
- ntype->uifunc = node_composit_buts_view_levels;
+ ntype->draw_buttons = node_composit_buts_view_levels;
break;
case CMP_NODE_COLORBALANCE:
- ntype->uifunc = node_composit_buts_colorbalance;
- ntype->uifuncbut = node_composit_buts_colorbalance_but;
+ ntype->draw_buttons = node_composit_buts_colorbalance;
+ ntype->draw_buttons_ex = node_composit_buts_colorbalance_ex;
break;
case CMP_NODE_HUECORRECT:
- ntype->uifunc = node_composit_buts_huecorrect;
+ ntype->draw_buttons = node_composit_buts_huecorrect;
break;
case CMP_NODE_ZCOMBINE:
- ntype->uifunc = node_composit_buts_zcombine;
+ ntype->draw_buttons = node_composit_buts_zcombine;
break;
case CMP_NODE_COMBYCCA:
case CMP_NODE_SEPYCCA:
- ntype->uifunc = node_composit_buts_ycc;
+ ntype->draw_buttons = node_composit_buts_ycc;
break;
case CMP_NODE_MOVIECLIP:
- ntype->uifunc = node_composit_buts_movieclip;
- ntype->uifuncbut = node_composit_buts_movieclip_details;
+ ntype->draw_buttons = node_composit_buts_movieclip;
+ ntype->draw_buttons_ex = node_composit_buts_movieclip_ex;
break;
case CMP_NODE_STABILIZE2D:
- ntype->uifunc = node_composit_buts_stabilize2d;
+ ntype->draw_buttons = node_composit_buts_stabilize2d;
break;
case CMP_NODE_TRANSFORM:
- ntype->uifunc = node_composit_buts_transform;
+ ntype->draw_buttons = node_composit_buts_transform;
break;
case CMP_NODE_TRANSLATE:
- ntype->uifunc = node_composit_buts_translate;
+ ntype->draw_buttons = node_composit_buts_translate;
break;
case CMP_NODE_MOVIEDISTORTION:
- ntype->uifunc = node_composit_buts_moviedistortion;
+ ntype->draw_buttons = node_composit_buts_moviedistortion;
break;
case CMP_NODE_COLORCORRECTION:
- ntype->uifunc = node_composit_buts_colorcorrection;
- ntype->uifuncbut = node_composit_buts_colorcorrection_but;
+ ntype->draw_buttons = node_composit_buts_colorcorrection;
+ ntype->draw_buttons_ex = node_composit_buts_colorcorrection_ex;
break;
case CMP_NODE_SWITCH:
- ntype->uifunc = node_composit_buts_switch;
+ ntype->draw_buttons = node_composit_buts_switch;
break;
case CMP_NODE_MASK_BOX:
- ntype->uifunc = node_composit_buts_boxmask;
- ntype->uibackdropfunc = node_composit_backdrop_boxmask;
+ ntype->draw_buttons = node_composit_buts_boxmask;
+ ntype->draw_backdrop = node_composit_backdrop_boxmask;
break;
case CMP_NODE_MASK_ELLIPSE:
- ntype->uifunc = node_composit_buts_ellipsemask;
- ntype->uibackdropfunc = node_composit_backdrop_ellipsemask;
+ ntype->draw_buttons = node_composit_buts_ellipsemask;
+ ntype->draw_backdrop = node_composit_backdrop_ellipsemask;
break;
case CMP_NODE_BOKEHIMAGE:
- ntype->uifunc = node_composit_buts_bokehimage;
+ ntype->draw_buttons = node_composit_buts_bokehimage;
break;
case CMP_NODE_BOKEHBLUR:
- ntype->uifunc = node_composit_buts_bokehblur;
+ ntype->draw_buttons = node_composit_buts_bokehblur;
break;
case CMP_NODE_VIEWER:
- ntype->uifunc = node_composit_buts_viewer;
- ntype->uifuncbut = node_composit_buts_viewer_but;
- ntype->uibackdropfunc = node_composit_backdrop_viewer;
+ ntype->draw_buttons = node_composit_buts_viewer;
+ ntype->draw_buttons_ex = node_composit_buts_viewer_ex;
+ ntype->draw_backdrop = node_composit_backdrop_viewer;
break;
case CMP_NODE_COMPOSITE:
- ntype->uifunc = node_composit_buts_composite;
+ ntype->draw_buttons = node_composit_buts_composite;
break;
case CMP_NODE_MASK:
- ntype->uifunc = node_composit_buts_mask;
+ ntype->draw_buttons = node_composit_buts_mask;
break;
case CMP_NODE_KEYINGSCREEN:
- ntype->uifunc = node_composit_buts_keyingscreen;
+ ntype->draw_buttons = node_composit_buts_keyingscreen;
break;
case CMP_NODE_KEYING:
- ntype->uifunc = node_composit_buts_keying;
+ ntype->draw_buttons = node_composit_buts_keying;
break;
case CMP_NODE_TRACKPOS:
- ntype->uifunc = node_composit_buts_trackpos;
+ ntype->draw_buttons = node_composit_buts_trackpos;
break;
case CMP_NODE_PLANETRACKDEFORM:
- ntype->uifunc = node_composit_buts_planetrackdeform;
+ ntype->draw_buttons = node_composit_buts_planetrackdeform;
break;
}
}
@@ -2615,7 +2562,7 @@ static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *p
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
}
-static void node_texture_buts_image_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
+static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
bNode *node = ptr->data;
PointerRNA iuserptr;
@@ -2633,46 +2580,46 @@ static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), Poin
static void node_texture_set_butfunc(bNodeType *ntype)
{
if (ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX) {
- ntype->uifunc = node_texture_buts_proc;
+ ntype->draw_buttons = node_texture_buts_proc;
}
else {
switch (ntype->type) {
case TEX_NODE_MATH:
- ntype->uifunc = node_buts_math;
+ ntype->draw_buttons = node_buts_math;
break;
case TEX_NODE_MIX_RGB:
- ntype->uifunc = node_buts_mix_rgb;
+ ntype->draw_buttons = node_buts_mix_rgb;
break;
case TEX_NODE_VALTORGB:
- ntype->uifunc = node_buts_colorramp;
+ ntype->draw_buttons = node_buts_colorramp;
break;
case TEX_NODE_CURVE_RGB:
- ntype->uifunc = node_buts_curvecol;
+ ntype->draw_buttons = node_buts_curvecol;
break;
case TEX_NODE_CURVE_TIME:
- ntype->uifunc = node_buts_time;
+ ntype->draw_buttons = node_buts_time;
break;
case TEX_NODE_TEXTURE:
- ntype->uifunc = node_buts_texture;
+ ntype->draw_buttons = node_buts_texture;
break;
case TEX_NODE_BRICKS:
- ntype->uifunc = node_texture_buts_bricks;
+ ntype->draw_buttons = node_texture_buts_bricks;
break;
case TEX_NODE_IMAGE:
- ntype->uifunc = node_texture_buts_image;
- ntype->uifuncbut = node_texture_buts_image_details;
+ ntype->draw_buttons = node_texture_buts_image;
+ ntype->draw_buttons_ex = node_texture_buts_image_ex;
break;
case TEX_NODE_OUTPUT:
- ntype->uifunc = node_texture_buts_output;
+ ntype->draw_buttons = node_texture_buts_output;
break;
}
}
@@ -2746,14 +2693,12 @@ void ED_node_init_butfuncs(void)
extern bNodeSocketType NodeSocketTypeUndefined;
/* default ui functions */
- NodeTypeUndefined.drawfunc = node_draw_default;
- NodeTypeUndefined.drawupdatefunc = node_update_default;
+ NodeTypeUndefined.draw_nodetype = node_draw_default;
+ NodeTypeUndefined.draw_nodetype_prepare = node_update_default;
NodeTypeUndefined.select_area_func = node_select_area_default;
NodeTypeUndefined.tweak_area_func = node_tweak_area_default;
- NodeTypeUndefined.uifunc = NULL;
- NodeTypeUndefined.uifuncbut = NULL;
- NodeTypeUndefined.drawinputfunc = node_draw_input_default;
- NodeTypeUndefined.drawoutputfunc = node_draw_output_default;
+ NodeTypeUndefined.draw_buttons = NULL;
+ NodeTypeUndefined.draw_buttons_ex = NULL;
NodeTypeUndefined.resize_area_func = node_resize_area_default;
NodeSocketTypeUndefined.draw = node_socket_undefined_draw;
@@ -2764,14 +2709,12 @@ void ED_node_init_butfuncs(void)
/* node type ui functions */
NODE_TYPES_BEGIN(ntype)
/* default ui functions */
- ntype->drawfunc = node_draw_default;
- ntype->drawupdatefunc = node_update_default;
+ ntype->draw_nodetype = node_draw_default;
+ ntype->draw_nodetype_prepare = node_update_default;
ntype->select_area_func = node_select_area_default;
ntype->tweak_area_func = node_tweak_area_default;
- ntype->uifunc = NULL;
- ntype->uifuncbut = NULL;
- ntype->drawinputfunc = node_draw_input_default;
- ntype->drawoutputfunc = node_draw_output_default;
+ ntype->draw_buttons = NULL;
+ ntype->draw_buttons_ex = NULL;
ntype->resize_area_func = node_resize_area_default;
node_common_set_butfunc(ntype);
@@ -2793,10 +2736,8 @@ void ED_node_init_butfuncs(void)
void ED_init_custom_node_type(bNodeType *ntype)
{
/* default ui functions */
- ntype->drawfunc = node_draw_default;
- ntype->drawupdatefunc = node_update_default;
- ntype->drawinputfunc = node_draw_input_default;
- ntype->drawoutputfunc = node_draw_output_default;
+ ntype->draw_nodetype = node_draw_default;
+ ntype->draw_nodetype_prepare = node_update_default;
ntype->resize_area_func = node_resize_area_default;
ntype->select_area_func = node_select_area_default;
ntype->tweak_area_func = node_tweak_area_default;
@@ -2834,13 +2775,60 @@ static void std_node_socket_interface_draw_color(bContext *UNUSED(C), PointerRNA
copy_v4_v4(r_color, std_node_socket_colors[type]);
}
+/* draw function for file output node sockets, displays only sub-path and format, no value button */
+static void node_file_output_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr)
+{
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *sock = ptr->data;
+ uiLayout *row;
+ PointerRNA inputptr, imfptr;
+ int imtype;
+
+ row = uiLayoutRow(layout, FALSE);
+
+ imfptr = RNA_pointer_get(node_ptr, "format");
+ imtype = RNA_enum_get(&imfptr, "file_format");
+ if (imtype == R_IMF_IMTYPE_MULTILAYER) {
+ NodeImageMultiFileSocket *input = sock->storage;
+ RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr);
+
+ uiItemL(row, input->layer, ICON_NONE);
+ }
+ else {
+ NodeImageMultiFileSocket *input = sock->storage;
+ PropertyRNA *imtype_prop;
+ const char *imtype_name;
+ uiBlock *block;
+ RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr);
+
+ uiItemL(row, input->path, ICON_NONE);
+
+ if (!RNA_boolean_get(&inputptr, "use_node_format"))
+ imfptr = RNA_pointer_get(&inputptr, "format");
+
+ imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
+ RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop,
+ RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
+ block = uiLayoutGetBlock(row);
+ uiBlockSetEmboss(block, UI_EMBOSSP);
+ uiItemL(row, imtype_name, ICON_NONE);
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ }
+}
+
static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, const char *text)
{
+ bNode *node = node_ptr->data;
bNodeSocket *sock = ptr->data;
int type = sock->typeinfo->type;
/*int subtype = sock->typeinfo->subtype;*/
- if ((sock->flag & SOCK_IN_USE) || (sock->flag & SOCK_HIDE_VALUE)) {
+ /* XXX not nice, eventually give this node its own socket type ... */
+ if (node->type == CMP_NODE_OUTPUT_FILE) {
+ node_file_output_socket_draw(C, layout, ptr, node_ptr);
+ }
+
+ if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_IN_USE) || (sock->flag & SOCK_HIDE_VALUE)) {
node_socket_button_label(C, layout, ptr, node_ptr, text);
return;
}
@@ -3053,8 +3041,8 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
rctf *viewer_border = &snode->nodetree->viewer_border;
while (node) {
if (node->flag & NODE_SELECT) {
- if (node->typeinfo->uibackdropfunc) {
- node->typeinfo->uibackdropfunc(snode, ibuf, node, x, y);
+ if (node->typeinfo->draw_backdrop) {
+ node->typeinfo->draw_backdrop(snode, ibuf, node, x, y);
}
}
node = node->next;
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 29f796aecb1..65eb75f8523 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -351,7 +351,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
row = uiLayoutRow(layout, 1);
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
- node->typeinfo->drawoutputfunc((bContext *)C, row, &sockptr, &nodeptr);
+ nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name));
uiBlockEndAlign(node->block);
uiBlockLayoutResolve(node->block, NULL, &buty);
@@ -402,7 +402,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
}
/* buttons rect? */
- if (node->typeinfo->uifunc && (node->flag & NODE_OPTIONS)) {
+ if (node->typeinfo->draw_buttons && (node->flag & NODE_OPTIONS)) {
dy -= NODE_DYS / 2;
/* set this for uifunc() that don't use layout engine yet */
@@ -416,7 +416,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
locx + NODE_DYS, dy, node->butr.xmax, 0, UI_GetStyle());
uiLayoutSetContextPointer(layout, "node", &nodeptr);
- node->typeinfo->uifunc(layout, (bContext *)C, &nodeptr);
+ node->typeinfo->draw_buttons(layout, (bContext *)C, &nodeptr);
uiBlockEndAlign(node->block);
uiBlockLayoutResolve(node->block, NULL, &buty);
@@ -437,7 +437,9 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
uiLayoutSetContextPointer(layout, "node", &nodeptr);
uiLayoutSetContextPointer(layout, "socket", &sockptr);
- node->typeinfo->drawinputfunc((bContext *)C, layout, &sockptr, &nodeptr);
+ row = uiLayoutRow(layout, 1);
+
+ nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name));
uiBlockEndAlign(node->block);
uiBlockLayoutResolve(node->block, NULL, &buty);
@@ -1115,8 +1117,8 @@ void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTr
static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
{
- if (node->typeinfo->drawupdatefunc)
- node->typeinfo->drawupdatefunc(C, ntree, node);
+ if (node->typeinfo->draw_nodetype_prepare)
+ node->typeinfo->draw_nodetype_prepare(C, ntree, node);
}
void node_update_nodetree(const bContext *C, bNodeTree *ntree)
@@ -1131,8 +1133,8 @@ void node_update_nodetree(const bContext *C, bNodeTree *ntree)
static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
- if (node->typeinfo->drawfunc)
- node->typeinfo->drawfunc(C, ar, snode, ntree, node, key);
+ if (node->typeinfo->draw_nodetype)
+ node->typeinfo->draw_nodetype(C, ar, snode, ntree, node, key);
}
#define USE_DRAW_TOT_UPDATE
@@ -1241,7 +1243,7 @@ static void draw_group_overlay(const bContext *C, ARegion *ar)
/* shade node groups to separate them visually */
UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
glEnable(GL_BLEND);
- uiSetRoundBox(0);
+ uiSetRoundBox(UI_CNR_NONE);
uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0);
glDisable(GL_BLEND);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index ff6a8e884a6..1d93fe65c09 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -1419,7 +1419,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0)
continue;
- if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->uifunc || node->typeinfo->uifuncbut))
+ if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex))
continue;
if (node->flag & toggle_flag)
@@ -1433,7 +1433,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0)
continue;
- if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->uifunc || node->typeinfo->uifuncbut))
+ if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex))
continue;
if ((tot_eq && tot_neq) || tot_eq == 0)
@@ -1731,7 +1731,7 @@ static int node_output_file_add_socket_exec(bContext *C, wmOperator *op)
node = nodeGetActive(snode->edittree);
}
- if (!node)
+ if (!node || node->type != CMP_NODE_OUTPUT_FILE)
return OPERATOR_CANCELLED;
RNA_string_get(op->ptr, "file_path", file_path);
@@ -1777,7 +1777,7 @@ static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *U
node = nodeGetActive(snode->edittree);
}
- if (!node)
+ if (!node || node->type != CMP_NODE_OUTPUT_FILE)
return OPERATOR_CANCELLED;
if (!ntreeCompositOutputFileRemoveActiveSocket(ntree, node))
@@ -1819,7 +1819,7 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
else if (snode && snode->edittree)
node = nodeGetActive(snode->edittree);
- if (!node)
+ if (!node || node->type != CMP_NODE_OUTPUT_FILE)
return OPERATOR_CANCELLED;
nimf = node->storage;
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index 83c11e69d84..a67a8791a64 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -207,7 +207,7 @@ static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *
break;
if (node_from)
- if (node_from->inputs.first || node_from->typeinfo->uifunc || node_from->typeinfo->uifuncbut)
+ if (node_from->inputs.first || node_from->typeinfo->draw_buttons || node_from->typeinfo->draw_buttons_ex)
node_from = NULL;
if (node_prev && node_prev->type == type && node_link_item_compare(node_prev, item)) {
@@ -586,13 +586,13 @@ static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, b
RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
- if (node->typeinfo->uifunc) {
+ if (node->typeinfo->draw_buttons) {
if (node->type != NODE_GROUP) {
split = uiLayoutSplit(layout, 0.35f, FALSE);
col = uiLayoutColumn(split, FALSE);
col = uiLayoutColumn(split, FALSE);
- node->typeinfo->uifunc(col, C, &nodeptr);
+ node->typeinfo->draw_buttons(col, C, &nodeptr);
}
}
@@ -639,7 +639,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
if (depth > 0) {
uiBlockSetEmboss(block, UI_EMBOSSN);
- if (lnode && (lnode->inputs.first || (lnode->typeinfo->uifunc && lnode->type != NODE_GROUP))) {
+ if (lnode && (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) {
int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT : ICON_DISCLOSURE_TRI_DOWN;
uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon);
}
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index e4a9c4fa5db..f889a8ec97b 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -373,7 +373,7 @@ void NODE_OT_backimage_fit(wmOperatorType *ot)
/* identifiers */
ot->name = "Background Image Fit";
ot->idname = "NODE_OT_backimage_fit";
- ot->description = "Zoom in/out the background image";
+ ot->description = "Fit the background image to the view";
/* api callbacks */
ot->exec = backimage_fit_exec;
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index b86fba1398a..10890a305fb 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -384,17 +384,21 @@ static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce,
for (srl = sce->r.layers.first; srl; srl = srl->next) {
for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
- lineset->linestyle->id.flag |= LIB_DOIT;
+ FreestyleLineStyle *linestyle = lineset->linestyle;
+ if (linestyle) {
+ linestyle->id.flag |= LIB_DOIT;
+ }
}
}
for (srl = sce->r.layers.first; srl; srl = srl->next) {
for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
FreestyleLineStyle *linestyle = lineset->linestyle;
-
- if (!(linestyle->id.flag & LIB_DOIT))
- continue;
- linestyle->id.flag &= ~LIB_DOIT;
- outliner_add_element(soops, lb, linestyle, te, 0, 0);
+ if (linestyle) {
+ if (!(linestyle->id.flag & LIB_DOIT))
+ continue;
+ linestyle->id.flag &= ~LIB_DOIT;
+ outliner_add_element(soops, lb, linestyle, te, 0, 0);
+ }
}
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index dca1b481334..cb69a7fe654 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -1251,7 +1251,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
height = (scene->r.size * scene->r.ysch) / 100;
ED_mask_draw_region(mask, ar,
- 0, 0, /* TODO */
+ 0, 0, 0, /* TODO */
width, height,
aspx, aspy,
FALSE, TRUE,
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index d8b4824b528..8b2e7067eb9 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -2960,7 +2960,7 @@ void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot)
/* identifiers */
ot->name = "Border Offset View";
ot->idname = "SEQUENCER_OT_view_ghost_border";
- ot->description = "Enable border select mode";
+ ot->description = "Set the boundaries of the border used for offset-view";
/* api callbacks */
ot->invoke = WM_border_select_invoke;
diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c
index 51df21e509a..c8fd6e4b6ea 100644
--- a/source/blender/editors/space_sequencer/sequencer_modifier.c
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -99,7 +99,7 @@ void SEQUENCER_OT_strip_modifier_add(wmOperatorType *ot)
/* identifiers */
ot->name = "Add Strip Modifier";
ot->idname = "SEQUENCER_OT_strip_modifier_add";
- ot->description = "Add a modifier to strip";
+ ot->description = "Add a modifier to the strip";
/* api callbacks */
ot->exec = strip_modifier_add_exec;
@@ -142,7 +142,7 @@ void SEQUENCER_OT_strip_modifier_remove(wmOperatorType *ot)
/* identifiers */
ot->name = "Remove Strip Modifier";
ot->idname = "SEQUENCER_OT_strip_modifier_remove";
- ot->description = "Add a modifier to strip";
+ ot->description = "Remove a modifier from the strip";
/* api callbacks */
ot->exec = strip_modifier_remove_exec;
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 254d15341cd..45f05d56076 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -892,7 +892,7 @@ void SEQUENCER_OT_select_border(wmOperatorType *ot)
/* identifiers */
ot->name = "Border Select";
ot->idname = "SEQUENCER_OT_select_border";
- ot->description = "Enable border select mode";
+ ot->description = "Select strips using border selection";
/* api callbacks */
ot->invoke = WM_border_select_invoke;
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index 18733d4e409..deb37f8d943 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -220,7 +220,8 @@ static int sample_cancel(bContext *C, wmOperator *op)
static int sample_poll(bContext *C)
{
- return BKE_sequencer_editing_get(CTX_data_scene(C), FALSE) != NULL;
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
+ return sseq && BKE_sequencer_editing_get(CTX_data_scene(C), FALSE) != NULL;
}
void SEQUENCER_OT_sample(wmOperatorType *ot)
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index c5e7a47b7a2..c668c8063a8 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -309,7 +309,7 @@ static void text_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "selection", TRUE);
}
- WM_keymap_add_item(keymap, "TEXT_OT_properties", PKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_properties", TKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_jump", JKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_find", GKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index ba61399f6d5..eaba537c0a8 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -361,6 +361,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
}
break;
case RETKEY:
+ case PADENTER:
if (event->val == KM_PRESS) {
if (tools & TOOL_SUGG_LIST) {
confirm_suggestion(st->text);
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 2c2a8b255da..c078e612d68 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -1943,7 +1943,7 @@ void TEXT_OT_move_select(wmOperatorType *ot)
/* identifiers */
ot->name = "Move Select";
ot->idname = "TEXT_OT_move_select";
- ot->description = "Make selection from current cursor position to new cursor position type";
+ ot->description = "Move the cursor while selecting";
/* api callbacks */
ot->exec = text_move_select_exec;
@@ -2291,7 +2291,7 @@ void TEXT_OT_scroll(wmOperatorType *ot)
* scroll_bar. Both do basically the same thing (aside
* from keymaps).*/
ot->idname = "TEXT_OT_scroll";
- ot->description = "Scroll text screen";
+ ot->description = "";
/* api callbacks */
ot->exec = text_scroll_exec;
@@ -2301,7 +2301,7 @@ void TEXT_OT_scroll(wmOperatorType *ot)
ot->poll = text_scroll_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_INTERNAL;
/* properties */
RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
@@ -2385,7 +2385,7 @@ void TEXT_OT_scroll_bar(wmOperatorType *ot)
* scroll. Both do basically the same thing (aside
* from keymaps).*/
ot->idname = "TEXT_OT_scroll_bar";
- ot->description = "Scroll text screen";
+ ot->description = "";
/* api callbacks */
ot->invoke = text_scroll_bar_invoke;
@@ -2394,7 +2394,7 @@ void TEXT_OT_scroll_bar(wmOperatorType *ot)
ot->poll = text_region_scroll_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
/* properties */
RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 2634dd3ec08..de6fafb2cd8 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -304,7 +304,7 @@ static void set_ebone_glColor(const unsigned int boneflag)
/* *************** Armature drawing, helper calls for parts ******************* */
/* half the cube, in Y */
-static float cube[8][3] = {
+static const float cube[8][3] = {
{-1.0, 0.0, -1.0},
{-1.0, 0.0, 1.0},
{-1.0, 1.0, 1.0},
@@ -440,7 +440,7 @@ static void draw_bonevert_solid(void)
glCallList(displist);
}
-static float bone_octahedral_verts[6][3] = {
+static const float bone_octahedral_verts[6][3] = {
{ 0.0f, 0.0f, 0.0f},
{ 0.1f, 0.1f, 0.1f},
{ 0.1f, 0.1f, -0.1f},
@@ -449,10 +449,10 @@ static float bone_octahedral_verts[6][3] = {
{ 0.0f, 1.0f, 0.0f}
};
-static unsigned int bone_octahedral_wire_sides[8] = {0, 1, 5, 3, 0, 4, 5, 2};
-static unsigned int bone_octahedral_wire_square[8] = {1, 2, 3, 4, 1};
+static const unsigned int bone_octahedral_wire_sides[8] = {0, 1, 5, 3, 0, 4, 5, 2};
+static const unsigned int bone_octahedral_wire_square[8] = {1, 2, 3, 4, 1};
-static unsigned int bone_octahedral_solid_tris[8][3] = {
+static const unsigned int bone_octahedral_solid_tris[8][3] = {
{2, 1, 0}, /* bottom */
{3, 2, 0},
{4, 3, 0},
@@ -465,7 +465,7 @@ static unsigned int bone_octahedral_solid_tris[8][3] = {
};
/* aligned with bone_octahedral_solid_tris */
-static float bone_octahedral_solid_normals[8][3] = {
+static const float bone_octahedral_solid_normals[8][3] = {
{ 0.70710683f, -0.70710683f, 0.00000000f},
{-0.00000000f, -0.70710683f, -0.70710683f},
{-0.70710683f, -0.70710683f, 0.00000000f},
@@ -599,7 +599,7 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag,
}
/* 16 values of sin function (still same result!) */
-static float si[16] = {
+static const float si[16] = {
0.00000000f,
0.20129852f, 0.39435585f,
0.57126821f, 0.72479278f,
@@ -611,7 +611,7 @@ static float si[16] = {
0.10116832f
};
/* 16 values of cos function (still same result!) */
-static float co[16] = {
+static const float co[16] = {
1.00000000f,
0.97952994f, 0.91895781f,
0.82076344f, 0.68896691f,
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 82bc0dfb00d..1ea1dcfb33d 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -2043,7 +2043,7 @@ static void draw_dm_face_normals__mapFunc(void *userData, int index, const float
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
if (!data->uniform_scale) {
- mul_v3_m3v3(n, data->tmat, (float *) no);
+ mul_v3_m3v3(n, data->tmat, no);
normalize_v3(n);
mul_m3_v3(data->imat, n);
}
@@ -2108,7 +2108,7 @@ static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float
}
if (!data->uniform_scale) {
- mul_v3_m3v3(n, data->tmat, (float *) no);
+ mul_v3_m3v3(n, data->tmat, no);
normalize_v3(n);
mul_m3_v3(data->imat, n);
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 6c61c2af816..58c0df6b6bd 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -44,6 +44,7 @@
#include "BKE_context.h"
#include "BKE_icons.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_screen.h"
@@ -258,6 +259,25 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d)
}
#endif
+void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
+{
+ wmWindowManager *wm = bmain->wm.first;
+
+ if (v3d->drawtype != OB_RENDER) {
+ ARegion *ar;
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d && rv3d->render_engine) {
+ WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW);
+ RE_engine_free(rv3d->render_engine);
+ rv3d->render_engine = NULL;
+ }
+ }
+ }
+}
+
/* ******************** default callbacks for view3d space ***************** */
static SpaceLink *view3d_new(const bContext *C)
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 75e7605df6b..eea084b4750 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -682,7 +682,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
}
BKE_nurb_test2D(nu);
- BKE_nurb_handles_test(nu); /* test for bezier too */
+ BKE_nurb_handles_test(nu, true); /* test for bezier too */
nu = nu->next;
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index e808869abc7..e8e4e75472f 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -113,9 +113,9 @@ static void star_stuff_init_func(void)
glPointSize(1.0);
glBegin(GL_POINTS);
}
-static void star_stuff_vertex_func(float *i)
+static void star_stuff_vertex_func(const float vec[3])
{
- glVertex3fv(i);
+ glVertex3fv(vec);
}
static void star_stuff_term_func(void)
{
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 005bb5940bc..67c9ea4599c 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -1257,7 +1257,7 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Orbit View";
- ot->description = "Explore every angle of an object using the 3D mouse";
+ ot->description = "Orbit the view using the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_orbit";
/* api callbacks */
@@ -1355,7 +1355,7 @@ void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Orbit View with Zoom";
- ot->description = "Explore every angle of an object using the 3D mouse";
+ ot->description = "Orbit and zoom the view using the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_orbit_zoom";
/* api callbacks */
@@ -1452,7 +1452,7 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Pan View";
- ot->description = "Position your viewpoint with the 3D mouse";
+ ot->description = "Pan the view with the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_pan";
/* api callbacks */
@@ -1543,7 +1543,7 @@ void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Move View";
- ot->description = "Position your viewpoint with the 3D mouse";
+ ot->description = "Pan and rotate the view with the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_all";
/* api callbacks */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index c812f1084e2..c48ce8a2343 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -160,7 +160,7 @@ static void edbm_backbuf_check_and_select_edges(BMEditMesh *em, const bool selec
{
BMEdge *eed;
BMIter iter;
- int index = bm_solidoffs;
+ unsigned int index = bm_solidoffs;
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
@@ -288,12 +288,12 @@ static int view3d_selectable_data(bContext *C)
/* helper also for borderselect */
-static int edge_fully_inside_rect(const rctf *rect, const float v1[2], const float v2[2])
+static bool edge_fully_inside_rect(const rctf *rect, const float v1[2], const float v2[2])
{
return BLI_rctf_isect_pt_v(rect, v1) && BLI_rctf_isect_pt_v(rect, v2);
}
-static int edge_inside_rect(const rctf *rect, const float v1[2], const float v2[2])
+static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2[2])
{
int d1, d2, d3, d4;
@@ -725,7 +725,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh
{
const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
Object *ob = vc->obact;
- Mesh *me = ob ? ob->data : NULL;
+ Mesh *me = ob->data;
rcti rect;
if (me == NULL || me->totvert == 0)
@@ -764,7 +764,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh
static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
{
Object *ob = vc->obact;
- Mesh *me = ob ? ob->data : NULL;
+ Mesh *me = ob->data;
rcti rect;
if (me == NULL || me->totpoly == 0)
@@ -2405,13 +2405,13 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva
static void paint_facesel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
{
Object *ob = vc->obact;
- Mesh *me = ob ? ob->data : NULL;
- /* int bbsel; */ /* UNUSED */
+ Mesh *me = ob->data;
+ bool bbsel;
- if (me) {
- bm_vertoffs = me->totpoly + 1; /* max index array */
+ bm_vertoffs = me->totpoly + 1; /* max index array */
- /* bbsel = */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ if (bbsel) {
edbm_backbuf_check_and_select_tfaces(me, select);
EDBM_backbuf_free();
paintface_flush_flags(ob);
@@ -2431,15 +2431,17 @@ static void paint_vertsel_circle_select(ViewContext *vc, const bool select, cons
const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
Object *ob = vc->obact;
Mesh *me = ob->data;
- /* int bbsel; */ /* UNUSED */
+ bool bbsel;
/* CircleSelectUserData data = {NULL}; */ /* UNUSED */
if (use_zbuf) {
bm_vertoffs = me->totvert + 1; /* max index array */
- /* bbsel = */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
- edbm_backbuf_check_and_select_verts_obmode(me, select);
- EDBM_backbuf_free();
+ bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ if (bbsel) {
+ edbm_backbuf_check_and_select_verts_obmode(me, select);
+ EDBM_backbuf_free();
+ }
}
else {
CircleSelectUserData data;
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 5f988edb950..7c29ab01c24 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -143,7 +143,7 @@ static void special_transvert_update(Object *obedit)
}
BKE_nurb_test2D(nu);
- BKE_nurb_handles_test(nu); /* test for bezier too */
+ BKE_nurb_handles_test(nu, true); /* test for bezier too */
nu = nu->next;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 7e39c0b6be0..74d72061995 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -378,12 +378,15 @@ void VIEW3D_OT_smoothview(wmOperatorType *ot)
/* identifiers */
ot->name = "Smooth View";
+ ot->description = "";
ot->idname = "VIEW3D_OT_smoothview";
- ot->description = "The time to animate the change of view (in milliseconds)";
/* api callbacks */
ot->invoke = view3d_smoothview_invoke;
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
+
ot->poll = ED_operator_view3d_active;
}
@@ -1177,7 +1180,7 @@ static bool view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, Report
return ok;
}
-static void restore_localviewdata(ScrArea *sa, int free)
+static void restore_localviewdata(Main *bmain, ScrArea *sa, int free)
{
ARegion *ar;
View3D *v3d = sa->spacedata.first;
@@ -1214,12 +1217,7 @@ static void restore_localviewdata(ScrArea *sa, int free)
}
}
- if (v3d->drawtype != OB_RENDER) {
- if (rv3d->render_engine) {
- RE_engine_free(rv3d->render_engine);
- rv3d->render_engine = NULL;
- }
- }
+ ED_view3d_shade_update(bmain, v3d, sa);
}
}
}
@@ -1234,7 +1232,7 @@ static bool view3d_localview_exit(Main *bmain, Scene *scene, ScrArea *sa)
locallay = v3d->lay & 0xFF000000;
- restore_localviewdata(sa, 1); /* 1 = free */
+ restore_localviewdata(bmain, sa, 1); /* 1 = free */
/* for when in other window the layers have changed */
if (v3d->scenelock) v3d->lay = scene->lay;
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 87ef3d6742a..ea039c15be4 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -105,6 +105,8 @@ static int doVertSlide(TransInfo *t, float perc);
static void drawEdgeSlide(const struct bContext *C, TransInfo *t);
static void drawVertSlide(const struct bContext *C, TransInfo *t);
+static void len_v3_ensure(float v[3], const float length);
+static void postInputRotation(TransInfo *t, float values[3]);
static bool transdata_check_local_center(TransInfo *t)
{
@@ -1360,7 +1362,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
}
}
-int calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], int cent2d[2])
+int calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], float cent2d[2])
{
TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data");
int success;
@@ -1390,7 +1392,7 @@ int calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], int c
calculateCenter(t);
if (cent2d) {
- copy_v2_v2_int(cent2d, t->center2d);
+ copy_v2_v2(cent2d, t->center2d);
}
if (cent3d) {
@@ -2576,58 +2578,67 @@ static void constraintSizeLim(TransInfo *t, TransData *td)
/* ************************** WARP *************************** */
-static void postInputWarp(TransInfo *t, float values[3])
-{
- mul_v3_fl(values, (float)(M_PI * 2));
+struct WarpCustomData {
+ float warp_sta[3];
+ float warp_end[3];
- if (t->customData) { /* non-null value indicates reversed input */
- negate_v3(values);
- }
-}
+ float warp_nor[3];
+ float warp_tan[3];
+
+ /* for applying the mouse distance */
+ float warp_init_dist;
+};
void initWarp(TransInfo *t)
{
- float max[3], min[3];
- int i;
+ const float mval_fl[2] = {UNPACK2(t->mval)};
+ const float *curs;
+ float tvec[3];
+ struct WarpCustomData *data;
t->mode = TFM_WARP;
t->transform = Warp;
t->handleEvent = handleEventWarp;
- setInputPostFct(&t->mouse, postInputWarp);
- initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
+ setInputPostFct(&t->mouse, postInputRotation);
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE_SPRING);
- t->idx_max = 0;
- t->num.idx_max = 0;
+ t->idx_max = 1;
+ t->num.idx_max = 1;
t->snap[0] = 0.0f;
- t->snap[1] = 5.0f / 180.0f * (float)M_PI;
- t->snap[2] = 1.0f / 180.0f * (float)M_PI;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
t->num.increment = 1.0f;
t->flag |= T_NO_CONSTRAINT;
-
- /* we need min/max in view space */
- for (i = 0; i < t->total; i++) {
- float center[3];
- copy_v3_v3(center, t->data[i].center);
- mul_m3_v3(t->data[i].mtx, center);
- mul_m4_v3(t->viewmat, center);
- sub_v3_v3(center, t->viewmat[3]);
- if (i) {
- minmax_v3v3_v3(min, max, center);
- }
- else {
- copy_v3_v3(max, center);
- copy_v3_v3(min, center);
- }
+
+ //copy_v3_v3(t->center, give_cursor(t->scene, t->view));
+ calculateCenterCursor(t);
+
+ t->val = 0.0f;
+
+ data = MEM_callocN(sizeof(*data), __func__);
+
+ curs = give_cursor(t->scene, t->view);
+ copy_v3_v3(data->warp_sta, curs);
+ ED_view3d_win_to_3d(t->ar, curs, mval_fl, data->warp_end);
+
+ copy_v3_v3(data->warp_nor, t->viewinv[2]);
+ if (t->flag & T_EDIT) {
+ sub_v3_v3(data->warp_sta, t->obedit->obmat[3]);
+ sub_v3_v3(data->warp_end, t->obedit->obmat[3]);
}
+ normalize_v3(data->warp_nor);
+
+ /* tangent */
+ sub_v3_v3v3(tvec, data->warp_end, data->warp_sta);
+ cross_v3_v3v3(data->warp_tan, tvec, data->warp_nor);
+ normalize_v3(data->warp_tan);
- mid_v3_v3v3(t->center, min, max);
+ data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta);
- if (max[0] == min[0])
- max[0] += 0.1f; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */
- t->val = (max[0] - min[0]) / 2.0f; /* t->val is X dimension projected boundbox */
+ t->customData = data;
}
int handleEventWarp(TransInfo *t, const wmEvent *event)
@@ -2635,11 +2646,7 @@ int handleEventWarp(TransInfo *t, const wmEvent *event)
int status = 0;
if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
- // Use customData pointer to signal warp direction
- if (t->customData == NULL)
- t->customData = (void *)1;
- else
- t->customData = NULL;
+ (void)t;
status = 1;
}
@@ -2650,91 +2657,115 @@ int handleEventWarp(TransInfo *t, const wmEvent *event)
int Warp(TransInfo *t, const int UNUSED(mval[2]))
{
TransData *td = t->data;
- float vec[3], circumfac, dist, phi0, co, si, cursor[3], gcursor[3];
- const float *curs;
+ float vec[3];
+ float pivot[3];
+ float warp_end_radius[3];
int i;
char str[MAX_INFO_LEN];
-
- curs = give_cursor(t->scene, t->view);
- /*
- * gcursor is the one used for helpline.
- * It has to be in the same space as the drawing loop
- * (that means it needs to be in the object's space when in edit mode and
- * in global space in object mode)
- *
- * cursor is used for calculations.
- * It needs to be in view space, but we need to take object's offset
- * into account if in Edit mode.
- */
- copy_v3_v3(cursor, curs);
- copy_v3_v3(gcursor, cursor);
- if (t->flag & T_EDIT) {
- sub_v3_v3(cursor, t->obedit->obmat[3]);
- sub_v3_v3(gcursor, t->obedit->obmat[3]);
- mul_m3_v3(t->data->smtx, gcursor);
- }
- mul_m4_v3(t->viewmat, cursor);
- sub_v3_v3(cursor, t->viewmat[3]);
-
+ const struct WarpCustomData *data = t->customData;
+ const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0;
+
+ union {
+ struct { float angle, scale; };
+ float vector[2];
+ } values;
+
/* amount of radians for warp */
- circumfac = t->values[0];
-
- snapGrid(t, &circumfac);
- applyNumInput(&t->num, &circumfac);
+ copy_v2_v2(values.vector, t->values);
+
+#if 0
+ snapGrid(t, angle_rad);
+#else
+ /* hrmf, snapping radius is using 'angle' steps, need to convert to something else
+ * this isnt essential but nicer to give reasonable snapping values for radius */
+ if (t->tsnap.mode == SCE_SNAP_MODE_INCREMENT) {
+ const float radius_snap = 0.1f;
+ const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap;
+ values.scale *= snap_hack;
+ snapGrid(t, values.vector);
+ values.scale /= snap_hack;
+ }
+#endif
/* header print for NumInput */
if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ char c[NUM_STR_REP_LEN * 2];
+ applyNumInput(&t->num, values.vector);
+
outputNumInput(&(t->num), c);
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %s"), c);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp Angle: %s Radius: %s Alt, Clamp %s"),
+ &c[0], &c[NUM_STR_REP_LEN],
+ WM_bool_as_string(is_clamp));
- circumfac = DEG2RADF(circumfac);
+ values.angle = DEG2RADF(values.angle);
+ values.scale = values.scale / data->warp_init_dist;
}
else {
/* default header print */
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %.3f"), RAD2DEGF(circumfac));
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp Angle: %.3f Radius: %.4f, Alt, Clamp %s"),
+ RAD2DEGF(values.angle), values.scale * data->warp_init_dist,
+ WM_bool_as_string(is_clamp));
}
- t->values[0] = circumfac;
+ copy_v2_v2(t->values, values.vector);
- circumfac /= 2; /* only need 180 on each side to make 360 */
+ values.angle *= -1.0f;
+ values.scale *= data->warp_init_dist;
+ /* calc 'data->warp_end' from 'data->warp_end_init' */
+ copy_v3_v3(warp_end_radius, data->warp_end);
+ dist_ensure_v3_v3fl(warp_end_radius, data->warp_sta, values.scale);
+ /* done */
+
+ /* calculate pivot */
+ copy_v3_v3(pivot, data->warp_sta);
+ if (values.angle > 0.0f) {
+ madd_v3_v3fl(pivot, data->warp_tan, -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle));
+ }
+ else {
+ madd_v3_v3fl(pivot, data->warp_tan, +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle));
+ }
+
for (i = 0; i < t->total; i++, td++) {
- float loc[3];
+ float mat[3][3];
+ float delta[3];
+ float fac, fac_scaled;
+
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
-
- /* translate point to center, rotate in such a way that outline==distance */
+
+ if (UNLIKELY(values.angle == 0.0f)) {
+ copy_v3_v3(td->loc, td->iloc);
+ continue;
+ }
+
copy_v3_v3(vec, td->iloc);
mul_m3_v3(td->mtx, vec);
- mul_m4_v3(t->viewmat, vec);
- sub_v3_v3(vec, t->viewmat[3]);
-
- dist = vec[0] - cursor[0];
-
- /* t->val is X dimension projected boundbox */
- phi0 = (circumfac * dist / t->val);
-
- vec[1] = (vec[1] - cursor[1]);
-
- co = cosf(phi0);
- si = sinf(phi0);
- loc[0] = -si * vec[1] + cursor[0];
- loc[1] = co * vec[1] + cursor[1];
- loc[2] = vec[2];
-
- mul_m4_v3(t->viewinv, loc);
- sub_v3_v3(loc, t->viewinv[3]);
- mul_m3_v3(td->smtx, loc);
-
- sub_v3_v3(loc, td->iloc);
- mul_v3_fl(loc, td->factor);
- add_v3_v3v3(td->loc, td->iloc, loc);
+
+ fac = line_point_factor_v3(vec, data->warp_sta, warp_end_radius);
+ if (is_clamp) {
+ CLAMP(fac, 0.0f, 1.0f);
+ }
+
+ fac_scaled = fac * td->factor;
+ axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled);
+ interp_v3_v3v3(delta, data->warp_sta, warp_end_radius, fac_scaled);
+ sub_v3_v3(delta, data->warp_sta);
+
+ /* delta is subtracted, rotation adds back this offset */
+ sub_v3_v3(vec, delta);
+
+ sub_v3_v3(vec, pivot);
+ mul_m3_v3(mat, vec);
+ add_v3_v3(vec, pivot);
+
+ mul_m3_v3(td->smtx, vec);
+ copy_v3_v3(td->loc, vec);
}
recalcData(t);
@@ -3369,8 +3400,8 @@ void initRotation(TransInfo *t)
t->idx_max = 0;
t->num.idx_max = 0;
t->snap[0] = 0.0f;
- t->snap[1] = (float)((5.0 / 180) * M_PI);
- t->snap[2] = t->snap[1] * 0.2f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
t->num.increment = 1.0f;
@@ -3701,8 +3732,8 @@ void initTrackball(TransInfo *t)
t->idx_max = 1;
t->num.idx_max = 1;
t->snap[0] = 0.0f;
- t->snap[1] = (float)((5.0 / 180) * M_PI);
- t->snap[2] = t->snap[1] * 0.2f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
t->num.increment = 1.0f;
@@ -4107,7 +4138,7 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
}
}
BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Even Thickness %s"),
- (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF"));
+ WM_bool_as_string(t->flag & T_ALT_TRANSFORM));
/* done with header string */
@@ -4149,8 +4180,8 @@ void initTilt(TransInfo *t)
t->idx_max = 0;
t->num.idx_max = 0;
t->snap[0] = 0.0f;
- t->snap[1] = (float)((5.0 / 180) * M_PI);
- t->snap[2] = t->snap[1] * 0.2f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
t->num.increment = t->snap[1];
@@ -4804,6 +4835,26 @@ static BMEdge *get_other_edge(BMVert *v, BMEdge *e)
return NULL;
}
+/* interpoaltes along a line made up of 2 segments (used for edge slide) */
+static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float t)
+{
+ float t_mid, t_delta;
+
+ /* could be pre-calculated */
+ t_mid = line_point_factor_v3(v2, v1, v3);
+
+ t_delta = t - t_mid;
+ if (fabsf(t_delta) < FLT_EPSILON) {
+ copy_v3_v3(p, v2);
+ }
+ else if (t_delta < 0.0f) {
+ interp_v3_v3v3(p, v1, v2, t / t_mid);
+ }
+ else {
+ interp_v3_v3v3(p, v2, v3, (t - t_mid) / (1.0f - t_mid));
+ }
+}
+
static void len_v3_ensure(float v[3], const float length)
{
normalize_v3(v);
@@ -5716,20 +5767,16 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t)
/* Non-Prop mode */
if (sld && sld->is_proportional == FALSE) {
View3D *v3d = CTX_wm_view3d(C);
- float marker[3];
- float v1[3], v2[3];
- float interp_v;
+ float co_a[3], co_b[3], co_mark[3];
TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
+ const float fac = (sld->perc + 1.0f) / 2.0f;
const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
const float guide_size = ctrl_size - 0.5f;
const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
const int alpha_shade = -30;
- add_v3_v3v3(v1, curr_sv->v_co_orig, curr_sv->dir_a);
- add_v3_v3v3(v2, curr_sv->v_co_orig, curr_sv->dir_b);
-
- interp_v = (sld->perc + 1.0f) / 2.0f;
- interp_v3_v3v3(marker, v2, v1, interp_v);
+ add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_a);
+ add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_b);
if (v3d && v3d->zbuf)
glDisable(GL_DEPTH_TEST);
@@ -5770,7 +5817,12 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t)
UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
glPointSize(guide_size);
bglBegin(GL_POINTS);
- bglVertex3fv(marker);
+#if 0
+ interp_v3_v3v3(co_mark, co_b, co_a, fac);
+ bglVertex3fv(co_mark);
+#endif
+ interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
+ bglVertex3fv(co_mark);
bglEnd();
@@ -5832,10 +5884,10 @@ static int doEdgeSlide(TransInfo *t, float perc)
add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_b);
if (sld->flipped_vtx) {
- interp_v3_v3v3(sv->v->co, co_b, co_a, fac);
+ interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac);
}
else {
- interp_v3_v3v3(sv->v->co, co_a, co_b, fac);
+ interp_line_v3_v3v3v3(sv->v->co, co_a, sv->v_co_orig, co_b, fac);
}
}
}
@@ -5854,9 +5906,6 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
bool flipped = sld->flipped_vtx;
bool is_proportional = sld->is_proportional;
- const char *on_str = IFACE_("ON");
- const char *off_str = IFACE_("OFF");
-
final = t->values[0];
snapGrid(t, &final);
@@ -5872,11 +5921,11 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s, (F)lipped: %s"),
- &c[0], !is_proportional ? on_str : off_str, flipped ? on_str : off_str);
+ &c[0], WM_bool_as_string(!is_proportional), WM_bool_as_string(flipped));
}
else {
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %.4f (E)ven: %s, (F)lipped: %s"),
- final, !is_proportional ? on_str : off_str, flipped ? on_str : off_str);
+ final, WM_bool_as_string(!is_proportional), WM_bool_as_string(flipped));
}
CLAMP(final, -1.0f, 1.0f);
@@ -6361,9 +6410,6 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2]))
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num));
- const char *on_str = IFACE_("ON");
- const char *off_str = IFACE_("OFF");
-
final = t->values[0];
snapGrid(t, &final);
@@ -6384,11 +6430,11 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2]))
else {
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "%.4f ", final);
}
- ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), !is_proportional ? on_str : off_str);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(!is_proportional));
if (!is_proportional) {
- ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), flipped ? on_str : off_str);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
}
- ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), is_clamp ? on_str : off_str);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
/* done with header string */
/* do stuff here */
@@ -6414,8 +6460,8 @@ void initBoneRoll(TransInfo *t)
t->idx_max = 0;
t->num.idx_max = 0;
t->snap[0] = 0.0f;
- t->snap[1] = (float)((5.0 / 180) * M_PI);
- t->snap[2] = t->snap[1] * 0.2f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
t->num.increment = 1.0f;
@@ -6720,7 +6766,7 @@ static void headerSeqSlide(TransInfo *t, float val[2], char *str)
}
}
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Expand to fit %s"),
- (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF"));
+ WM_bool_as_string(t->flag & T_ALT_TRANSFORM));
}
static void applySeqSlide(TransInfo *t, const float val[2])
@@ -7217,7 +7263,7 @@ int TimeSlide(TransInfo *t, const int mval[2])
void initTimeScale(TransInfo *t)
{
- int center[2];
+ float center[2];
/* this tool is only really available in the Action Editor
* AND NLA Editor (for strip scaling)
@@ -7232,7 +7278,7 @@ void initTimeScale(TransInfo *t)
/* recalculate center2d to use CFRA and mouse Y, since that's
* what is used in time scale */
t->center[0] = t->scene->r.cfra;
- projectIntView(t, t->center, center);
+ projectFloatView(t, t->center, center);
center[1] = t->imval[1];
/* force a reinit with the center2d used here */
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index a4828317604..b32ba5ad527 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -271,7 +271,7 @@ typedef struct MouseInput {
int imval[2]; /* initial mouse position */
char precision;
int precision_mval[2]; /* mouse position when precision key was pressed */
- int center[2];
+ float center[2];
float factor;
void *data; /* additional data, if needed by the particular function */
} MouseInput;
@@ -300,7 +300,7 @@ typedef struct TransInfo {
float prop_size; /* proportional circle radius */
char proptext[20]; /* proportional falloff text */
float center[3]; /* center of transformation */
- int center2d[2]; /* center in screen coordinates */
+ float center2d[2]; /* center in screen coordinates */
int imval[2]; /* initial mouse position */
short event_type; /* event->type used to invoke transform */
short idx_max; /* maximum index on the input vector */
@@ -678,6 +678,7 @@ typedef enum {
INPUT_SPRING,
INPUT_SPRING_FLIP,
INPUT_ANGLE,
+ INPUT_ANGLE_SPRING,
INPUT_TRACKBALL,
INPUT_HORIZONTAL_RATIO,
INPUT_HORIZONTAL_ABSOLUTE,
@@ -687,7 +688,7 @@ typedef enum {
INPUT_CUSTOM_RATIO_FLIP
} MouseInputMode;
-void initMouseInput(TransInfo *t, MouseInput *mi, const int center[2], const int mval[2]);
+void initMouseInput(TransInfo *t, MouseInput *mi, const float center[2], const int mval[2]);
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode);
int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, const struct wmEvent *event);
void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index a4299fe688c..f5a12fed076 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -123,6 +123,20 @@
#include "transform.h"
#include "bmesh.h"
+/**
+ * Transforming around ourselves is no use, fallback to individual origins,
+ * useful for curve/armatures.
+ */
+static void transform_around_single_fallback(TransInfo *t)
+{
+ if ((t->total == 1) &&
+ (ELEM3(t->around, V3D_CENTER, V3D_CENTROID, V3D_ACTIVE)) &&
+ (ELEM3(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL)))
+ {
+ t->around = V3D_LOCAL;
+ }
+}
+
/* when transforming islands */
struct TransIslandData {
float co[3];
@@ -1084,6 +1098,8 @@ static void createTransArmatureVerts(TransInfo *t)
if (!t->total) return;
+ transform_around_single_fallback(t);
+
copy_m3_m4(mtx, t->obedit->obmat);
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
@@ -1408,6 +1424,8 @@ static void createTransCurveVerts(TransInfo *t)
else t->total = countsel;
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)");
+ transform_around_single_fallback(t);
+
copy_m3_m4(mtx, t->obedit->obmat);
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
@@ -1443,7 +1461,9 @@ static void createTransCurveVerts(TransInfo *t)
{
copy_v3_v3(td->iloc, bezt->vec[0]);
td->loc = bezt->vec[0];
- copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1 : 0]);
+ copy_v3_v3(td->center, bezt->vec[(hide_handles ||
+ (t->around == V3D_LOCAL) ||
+ (bezt->f2 & SELECT)) ? 1 : 0]);
if (hide_handles) {
if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
else td->flag = 0;
@@ -1511,7 +1531,9 @@ static void createTransCurveVerts(TransInfo *t)
{
copy_v3_v3(td->iloc, bezt->vec[2]);
td->loc = bezt->vec[2];
- copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1 : 2]);
+ copy_v3_v3(td->center, bezt->vec[(hide_handles ||
+ (t->around == V3D_LOCAL) ||
+ (bezt->f2 & SELECT)) ? 1 : 2]);
if (hide_handles) {
if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
else td->flag = 0;
@@ -1552,7 +1574,7 @@ static void createTransCurveVerts(TransInfo *t)
* but for now just don't change handle types */
if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0) {
/* sets the handles based on their selection, do this after the data is copied to the TransData */
- BKE_nurb_handles_test(nu);
+ BKE_nurb_handles_test(nu, !hide_handles);
}
}
else {
@@ -3872,7 +3894,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
}
/* if handles were not selected, store their selection status */
- if (!(sel1) && !(sel3)) {
+ if (!(sel1) || !(sel3)) {
if (hdata == NULL)
hdata = initTransDataCurveHandles(td, bezt);
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 233ef1d18a5..94f481d8dfc 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1145,6 +1145,11 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even
if (v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN;
t->around = v3d->around;
+ /* warp always uses the cursor */
+ if (t->mode == TFM_WARP) {
+ t->around = V3D_CURSOR;
+ }
+
if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) &&
RNA_property_is_set(op->ptr, prop)))
{
@@ -1484,10 +1489,10 @@ void calculateCenter2D(TransInfo *t)
copy_v3_v3(vec, t->center);
mul_m4_v3(ob->obmat, vec);
- projectIntView(t, vec, t->center2d);
+ projectFloatView(t, vec, t->center2d);
}
else {
- projectIntView(t, t->center, t->center2d);
+ projectFloatView(t, t->center, t->center2d);
}
}
@@ -1691,7 +1696,7 @@ void calculateCenter(TransInfo *t)
Object *ob = OBACT;
if (ob) {
copy_v3_v3(t->center, ob->obmat[3]);
- projectIntView(t, t->center, t->center2d);
+ projectFloatView(t, t->center, t->center2d);
}
}
break;
@@ -1723,7 +1728,7 @@ void calculateCenter(TransInfo *t)
axis[1] = t->center[1] - 6.0f * axis[1];
axis[2] = t->center[2] - 6.0f * axis[2];
- projectIntView(t, axis, t->center2d);
+ projectFloatView(t, axis, t->center2d);
/* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
if (t->mode == TFM_TRANSLATION) {
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index c035b6173c8..ee993129303 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -279,7 +279,17 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2],
output[0] = *angle;
}
-void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const int center[2], const int mval[2])
+static void InputAngleSpring(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
+{
+ float toutput[3];
+
+ InputAngle(t, mi, mval, output);
+ InputSpring(t, mi, mval, toutput);
+
+ output[1] = toutput[0];
+}
+
+void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const float center[2], const int mval[2])
{
mi->factor = 0;
mi->precision = 0;
@@ -328,6 +338,12 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
mi->apply = InputAngle;
t->helpline = HLP_ANGLE;
break;
+ case INPUT_ANGLE_SPRING:
+ calcSpringFactor(mi);
+ mi->data = MEM_callocN(sizeof(double), "angle accumulator");
+ mi->apply = InputAngleSpring;
+ t->helpline = HLP_ANGLE;
+ break;
case INPUT_TRACKBALL:
/* factor has to become setting or so */
mi->factor = 0.01f;
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 6fecf0d6642..f667a98812b 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -428,12 +428,12 @@ int calc_manipulator_stats(const bContext *C)
totsel++;
}
else {
- if (bezt->f1) {
- calc_tw_center(scene, bezt->vec[0]);
+ if (bezt->f1 & SELECT) {
+ calc_tw_center(scene, bezt->vec[(v3d->around == V3D_LOCAL) ? 1 : 0]);
totsel++;
}
- if (bezt->f3) {
- calc_tw_center(scene, bezt->vec[2]);
+ if (bezt->f3 & SELECT) {
+ calc_tw_center(scene, bezt->vec[(v3d->around == V3D_LOCAL) ? 1 : 2]);
totsel++;
}
}
@@ -1858,11 +1858,12 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op)
* See [#34621], it's a miracle it did not cause more problems!!! */
/* However, we need to copy the "release_confirm" property... */
PointerRNA props_ptr;
- WM_operator_properties_create(&props_ptr, "TRANSFORM_OT_trackball");
+ wmOperatorType *ot = WM_operatortype_find("TRANSFORM_OT_trackball", true);
+ WM_operator_properties_create_ptr(&props_ptr, ot);
RNA_boolean_set(&props_ptr, "release_confirm", RNA_boolean_get(op->ptr, "release_confirm"));
-
- WM_operator_name_call(C, "TRANSFORM_OT_trackball", WM_OP_INVOKE_DEFAULT, &props_ptr);
- //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_trackball", 0), event, NULL, NULL, FALSE);
+ WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ //wm_operator_invoke(C, WM_operatortype_find(ot->idname, 0), event, NULL, NULL, FALSE);
+ WM_operator_properties_free(&props_ptr);
}
else if (drawflags & MAN_ROT_C) {
switch (drawflags) {
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index e7c22fc0899..2904b37c2e5 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -60,7 +60,7 @@ typedef struct TransformModeItem {
void (*opfunc)(wmOperatorType *);
} TransformModeItem;
-static float VecOne[3] = {1, 1, 1};
+static const float VecOne[3] = {1, 1, 1};
static char OP_TRANSLATION[] = "TRANSFORM_OT_translate";
static char OP_ROTATION[] = "TRANSFORM_OT_rotate";
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 55d80d63234..cd6a2e6712e 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -728,31 +728,46 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
}
else {
+ const bool use_handle = (cu->drawflag & CU_HIDE_HANDLES) == 0;
+
for (nu = nurbs->first; nu; nu = nu->next) {
/* only bezier has a normal */
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
a = nu->pntsu;
while (a--) {
+ short flag = 0;
+
+#define SEL_F1 (1 << 0)
+#define SEL_F2 (1 << 1)
+#define SEL_F3 (1 << 2)
+
+ if (use_handle) {
+ if (bezt->f1 & SELECT) flag |= SEL_F1;
+ if (bezt->f2 & SELECT) flag |= SEL_F2;
+ if (bezt->f3 & SELECT) flag |= SEL_F3;
+ }
+ else {
+ flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
+ }
+
/* exception */
- if ((bezt->f1 | bezt->f2 | bezt->f3) & SELECT) {
+ if (flag) {
float tvec[3];
- if ((bezt->f1 & SELECT) + (bezt->f2 & SELECT) + (bezt->f3 & SELECT) > SELECT) {
+ if ((v3d->around == V3D_LOCAL) ||
+ ELEM3(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
+ {
BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
add_v3_v3(normal, tvec);
}
else {
- if (bezt->f1 & SELECT) {
+ /* ignore bezt->f2 in this case */
+ if (flag & SEL_F1) {
sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[1]);
normalize_v3(tvec);
add_v3_v3(normal, tvec);
}
- if (bezt->f2 & SELECT) {
- sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[2]);
- normalize_v3(tvec);
- add_v3_v3(normal, tvec);
- }
- if (bezt->f3 & SELECT) {
+ if (flag & SEL_F3) {
sub_v3_v3v3(tvec, bezt->vec[1], bezt->vec[2]);
normalize_v3(tvec);
add_v3_v3(normal, tvec);
@@ -762,6 +777,11 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
BKE_nurb_bezt_calc_plane(nu, bezt, tvec);
add_v3_v3(plane, tvec);
}
+
+#undef SEL_F1
+#undef SEL_F2
+#undef SEL_F3
+
bezt++;
}
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 4a208f6eee1..04bccac2a15 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -134,7 +134,8 @@ bool validSnap(TransInfo *t)
bool activeSnap(TransInfo *t)
{
- return (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP || (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT;
+ return ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP) ||
+ ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT);
}
void drawSnapping(const struct bContext *C, TransInfo *t)
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 35e6c40c36b..7424acd752f 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -258,7 +258,7 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info)
{
wmWindow *win = CTX_wm_window(C);
- const int *mval_src = (int *)arg_info;
+ const float *mval_src = (float *)arg_info;
const int mval_dst[2] = {win->eventstate->x - ar->winrct.xmin,
win->eventstate->y - ar->winrct.ymin};
@@ -266,7 +266,7 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
setlinestyle(3);
glBegin(GL_LINE_STRIP);
glVertex2iv(mval_dst);
- glVertex2iv(mval_src);
+ glVertex2fv(mval_src);
glEnd();
setlinestyle(0);
}
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index b8a54c56c63..2d33a2d3937 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -4123,7 +4123,7 @@ static void p_smooth(PChart *chart)
MEM_freeN(nodesx);
MEM_freeN(nodesy);
- arena = BLI_memarena_new(1 << 16, "param smooth arena");
+ arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "param smooth arena");
root = p_node_new(arena, tri, esize * 2, minv, maxv, 0);
for (v = chart->verts; v; v = v->nextlink)
@@ -4143,7 +4143,7 @@ ParamHandle *param_construct_begin(void)
PHandle *handle = MEM_callocN(sizeof(*handle), "PHandle");
handle->construction_chart = p_chart_new(handle);
handle->state = PHANDLE_STATE_ALLOCATED;
- handle->arena = BLI_memarena_new((1 << 16), "param construct arena");
+ handle->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "param construct arena");
handle->aspx = 1.0f;
handle->aspy = 1.0f;
handle->do_aspect = FALSE;
diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
index 8cb44d05b84..7dc218c74df 100644
--- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
+++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
@@ -369,7 +369,7 @@ static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl)
if (lineset->flags & FREESTYLE_LINESET_ENABLED) {
if (G.debug & G_DEBUG_FREESTYLE) {
cout << " " << layer_count+1 << ": " << lineset->name << " - " <<
- lineset->linestyle->id.name + 2 << endl;
+ (lineset->linestyle ? (lineset->linestyle->id.name + 2) : "<NULL>") << endl;
}
Text *text = create_lineset_handler(bmain, srl->name, lineset->name);
controller->InsertStyleModule(layer_count, lineset->name, text);
@@ -680,9 +680,11 @@ void FRS_paste_active_lineset(FreestyleConfig *config)
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
if (lineset) {
- lineset->linestyle->id.us--;
+ if (lineset->linestyle)
+ lineset->linestyle->id.us--;
lineset->linestyle = lineset_buffer.linestyle;
- lineset->linestyle->id.us++;
+ if (lineset->linestyle)
+ lineset->linestyle->id.us++;
lineset->flags = lineset_buffer.flags;
lineset->selection = lineset_buffer.selection;
lineset->qi = lineset_buffer.qi;
@@ -711,10 +713,10 @@ void FRS_delete_active_lineset(FreestyleConfig *config)
if (lineset) {
if (lineset->group) {
lineset->group->id.us--;
- lineset->group = NULL;
}
- lineset->linestyle->id.us--;
- lineset->linestyle = NULL;
+ if (lineset->linestyle) {
+ lineset->linestyle->id.us--;
+ }
BLI_remlink(&config->linesets, lineset);
MEM_freeN(lineset);
BKE_freestyle_lineset_set_active_index(config, 0);
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 9319ac53db6..ed7a2f4ede0 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -1126,10 +1126,12 @@ static void do_material_tex(GPUShadeInput *shi)
else { /* otherwise use accumulated perturbations */
GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), shi->vn, tnor, &newnor);
}
- } else if (mtex->normapspace == MTEX_NSPACE_OBJECT) {
+ }
+ else if (mtex->normapspace == MTEX_NSPACE_OBJECT) {
/* transform normal by object then view matrix */
GPU_link(mat, "mtex_nspace_object", GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX), tnor, &newnor);
- } else if (mtex->normapspace == MTEX_NSPACE_WORLD) {
+ }
+ else if (mtex->normapspace == MTEX_NSPACE_WORLD) {
/* transform normal by view matrix */
GPU_link(mat, "mtex_nspace_world", GPU_builtin(GPU_VIEW_MATRIX), tnor, &newnor);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index bab677da842..633112095a7 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -2134,6 +2134,20 @@ void node_fresnel(float ior, vec3 N, vec3 I, out float result)
result = fresnel_dielectric(I, N, (gl_FrontFacing)? eta: 1.0/eta);
}
+/* gamma */
+
+void node_gamma(vec4 col, float gamma, out vec4 outcol)
+{
+ outcol = col;
+
+ if(col.r > 0.0)
+ outcol.r = compatible_pow(col.r, gamma);
+ if(col.g > 0.0)
+ outcol.g = compatible_pow(col.g, gamma);
+ if(col.b > 0.0)
+ outcol.b = compatible_pow(col.b, gamma);
+}
+
/* geometry */
void node_attribute(vec3 attr_uv, out vec4 outcol, out vec3 outvec, out float outf)
diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt
index 29ed8c95fc6..4025a41b6a7 100644
--- a/source/blender/imbuf/CMakeLists.txt
+++ b/source/blender/imbuf/CMakeLists.txt
@@ -105,6 +105,11 @@ if(WITH_IMAGE_TIFF)
add_definitions(-DWITH_TIFF)
endif()
+
+if(WITH_OPENIMAGEIO)
+ add_definitions(-DWITH_OPENIMAGEIO)
+endif()
+
if(WITH_IMAGE_OPENJPEG)
list(APPEND INC_SYS
${OPENJPEG_INCLUDE_DIRS}
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 64a2bbb72d9..8af86389db3 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -174,19 +174,16 @@ void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processo
/* ** OpenGL drawing routines using GLSL for color space transform ** */
/* Test if GLSL drawing is supported for combination of graphics card and this configuration */
-bool IMB_colormanagement_support_glsl_draw(const struct ColorManagedViewSettings *view_settings,
- bool skip_curves);
+bool IMB_colormanagement_support_glsl_draw(const struct ColorManagedViewSettings *view_settings);
/* Configures GLSL shader for conversion from scene linear to display space */
bool IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings,
- bool predivide,
- bool skip_curves);
+ bool predivide);
/* Same as above, but display space conversion happens from a specified space */
bool IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings,
struct ColorSpace *colorspace,
- bool predivide,
- bool skip_curves);
+ bool predivide);
/* Same as setup_glsl_draw, but color management settings are guessing from a given context */
bool IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, bool predivide);
/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 8c2e79ab7d8..c70ab5d7189 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -429,7 +429,7 @@ void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol
*
* \attention defined in readimage.c
*/
-struct ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr);
+struct ImBuf *IMB_loadifffile(int file, const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr);
/**
*
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 1734073dd6c..d20130805c0 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -180,6 +180,10 @@ typedef struct ImBuf {
*/
#define IB_CUSTOM_FLAGS_MASK 0x7ff
+#ifdef WITH_OPENIMAGEIO
+#define PSD (1 << 31)
+#endif
+
#define PNG (1 << 30)
#define TGA (1 << 28)
#define JPG (1 << 27)
@@ -273,6 +277,9 @@ extern const char *imb_ext_image_qt[];
extern const char *imb_ext_movie[];
extern const char *imb_ext_audio[];
+/* image formats that can only be loaded via filepath */
+extern const char *imb_ext_image_filepath_only[];
+
enum {
IMB_COLORMANAGE_IS_DATA = (1 << 0)
};
diff --git a/source/blender/imbuf/SConscript b/source/blender/imbuf/SConscript
index 03064df293d..ccee3ebcc85 100644
--- a/source/blender/imbuf/SConscript
+++ b/source/blender/imbuf/SConscript
@@ -55,6 +55,9 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', '
incs += ' ' + env['BF_PTHREADS_INC']
incs += ' ../../../intern/utfconv'
+if env['WITH_BF_OIIO']:
+ defs.append('WITH_OPENIMAGEIO')
+
if env['WITH_BF_OPENEXR']:
defs.append('WITH_OPENEXR')
else:
diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h
index 3c8b29cf68a..9327c15c415 100644
--- a/source/blender/imbuf/intern/IMB_filetype.h
+++ b/source/blender/imbuf/intern/IMB_filetype.h
@@ -39,8 +39,10 @@ typedef struct ImFileType {
void (*exit)(void);
int (*is_a)(unsigned char *buf);
+ int (*is_a_filepath)(const char *name);
int (*ftype)(struct ImFileType *type, struct ImBuf *ibuf);
struct ImBuf *(*load)(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+ struct ImBuf *(*load_filepath)(const char *name, int flags, char colorspace[IM_MAX_SPACE]);
int (*save)(struct ImBuf *ibuf, const char *name, int flags);
void (*load_tile)(struct ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect);
@@ -50,6 +52,7 @@ typedef struct ImFileType {
} ImFileType;
extern ImFileType IMB_FILE_TYPES[];
+extern ImFileType *IMB_FILE_TYPES_LAST;
void imb_filetypes_init(void);
void imb_filetypes_exit(void);
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 4c4c82a0bb4..cf9cc0c2e6f 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -119,6 +119,11 @@ static struct global_glsl_state {
char input[MAX_COLORSPACE_NAME];
float exposure, gamma;
+ CurveMapping *curve_mapping, *orig_curve_mapping;
+ bool use_curve_mapping;
+ int curve_mapping_timestamp;
+ OCIO_CurveMappingSettings curve_mapping_settings;
+
/* Container for GLSL state needed for OCIO module. */
struct OCIO_GLSLDrawState *ocio_glsl_state;
struct OCIO_GLSLDrawState *transform_ocio_glsl_state;
@@ -196,6 +201,7 @@ typedef struct ColormanageCacheViewSettings {
int view;
float exposure;
float gamma;
+ float dither;
CurveMapping *curve_mapping;
} ColormanageCacheViewSettings;
@@ -213,6 +219,7 @@ typedef struct ColormnaageCacheData {
int look; /* Additional artistics transform */
float exposure; /* exposure value cached buffer is calculated with */
float gamma; /* gamma value cached buffer is calculated with */
+ float dither; /* dither value cached buffer is calculated with */
CurveMapping *curve_mapping; /* curve mapping used for cached buffer */
int curve_mapping_timestamp; /* time stamp of curve mapping used for cached buffer */
} ColormnaageCacheData;
@@ -291,7 +298,8 @@ static void colormanage_cachedata_set(ImBuf *ibuf, ColormnaageCacheData *data)
ibuf->colormanage_cache->data = data;
}
-static void colormanage_view_settings_to_cache(ColormanageCacheViewSettings *cache_view_settings,
+static void colormanage_view_settings_to_cache(ImBuf *ibuf,
+ ColormanageCacheViewSettings *cache_view_settings,
const ColorManagedViewSettings *view_settings)
{
int look = IMB_colormanagement_look_get_named_index(view_settings->look);
@@ -301,6 +309,7 @@ static void colormanage_view_settings_to_cache(ColormanageCacheViewSettings *cac
cache_view_settings->view = view;
cache_view_settings->exposure = view_settings->exposure;
cache_view_settings->gamma = view_settings->gamma;
+ cache_view_settings->dither = ibuf->dither;
cache_view_settings->flag = view_settings->flag;
cache_view_settings->curve_mapping = view_settings->curve_mapping;
}
@@ -378,6 +387,7 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
if (cache_data->look != view_settings->look ||
cache_data->exposure != view_settings->exposure ||
cache_data->gamma != view_settings->gamma ||
+ cache_data->dither != view_settings->dither ||
cache_data->flag != view_settings->flag ||
cache_data->curve_mapping != curve_mapping ||
cache_data->curve_mapping_timestamp != curve_mapping_timestamp)
@@ -424,6 +434,7 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
cache_data->look = view_settings->look;
cache_data->exposure = view_settings->exposure;
cache_data->gamma = view_settings->gamma;
+ cache_data->dither = view_settings->dither;
cache_data->flag = view_settings->flag;
cache_data->curve_mapping = curve_mapping;
cache_data->curve_mapping_timestamp = curve_mapping_timestamp;
@@ -657,6 +668,12 @@ void colormanagement_exit(void)
if (global_glsl_state.processor)
OCIO_processorRelease(global_glsl_state.processor);
+ if (global_glsl_state.curve_mapping)
+ curvemapping_free(global_glsl_state.curve_mapping);
+
+ if (global_glsl_state.curve_mapping_settings.lut)
+ MEM_freeN(global_glsl_state.curve_mapping_settings.lut);
+
if (global_glsl_state.ocio_glsl_state)
OCIO_freeOGLState(global_glsl_state.ocio_glsl_state);
@@ -1909,7 +1926,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, boo
* we need to allocate byte buffer and store color managed
* image there
*/
- for (type = IMB_FILE_TYPES; type->is_a; type++) {
+ for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
if (type->save && type->ftype(type, colormanaged_ibuf)) {
if ((type->flag & IM_FTYPE_FLOAT) == 0)
make_byte = true;
@@ -2024,7 +2041,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
return (unsigned char *) ibuf->rect;
}
- colormanage_view_settings_to_cache(&cache_view_settings, applied_view_settings);
+ colormanage_view_settings_to_cache(ibuf, &cache_view_settings, applied_view_settings);
colormanage_display_settings_to_cache(&cache_display_settings, display_settings);
if (ibuf->invalid_rect.xmin != ibuf->invalid_rect.xmax) {
@@ -2445,7 +2462,7 @@ void IMB_colormanagment_colorspace_from_ibuf_ftype(ColorManagedColorspaceSetting
{
ImFileType *type;
- for (type = IMB_FILE_TYPES; type->is_a; type++) {
+ for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
if (type->save && type->ftype(type, ibuf)) {
const char *role_colorspace;
@@ -2735,7 +2752,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
unsigned char *display_buffer = NULL;
int view_flag, display_index, buffer_width;
- colormanage_view_settings_to_cache(&cache_view_settings, view_settings);
+ colormanage_view_settings_to_cache(ibuf, &cache_view_settings, view_settings);
colormanage_display_settings_to_cache(&cache_display_settings, display_settings);
view_flag = 1 << (cache_view_settings.view - 1);
@@ -2931,16 +2948,61 @@ static bool check_glsl_display_processor_changed(const ColorManagedViewSettings
STREQ(global_glsl_state.input, from_colorspace));
}
+static void curve_mapping_to_ocio_settings(CurveMapping *curve_mapping,
+ OCIO_CurveMappingSettings *curve_mapping_settings)
+{
+ int i;
+
+ curvemapping_initialize(curve_mapping);
+ curvemapping_premultiply(curve_mapping, false);
+ curvemapping_table_RGBA(curve_mapping,
+ &curve_mapping_settings->lut,
+ &curve_mapping_settings->lut_size);
+
+ for (i = 0; i < 4; i++) {
+ CurveMap *cuma = curve_mapping->cm + i;
+ curve_mapping_settings->use_extend_extrapolate[i] = (cuma->flag & CUMA_EXTEND_EXTRAPOLATE) != 0;
+ curve_mapping_settings->range[i] = cuma->range;
+ curve_mapping_settings->mintable[i] = cuma->mintable;
+ curve_mapping_settings->ext_in_x[i] = cuma->ext_in[0];
+ curve_mapping_settings->ext_in_y[i] = cuma->ext_in[1];
+ curve_mapping_settings->ext_out_x[i] = cuma->ext_out[0];
+ curve_mapping_settings->ext_out_y[i] = cuma->ext_out[1];
+ curve_mapping_settings->first_x[i] = cuma->table[0].x;
+ curve_mapping_settings->first_y[i] = cuma->table[0].y;
+ curve_mapping_settings->last_x[i] = cuma->table[CM_TABLE].x;
+ curve_mapping_settings->last_y[i] = cuma->table[CM_TABLE].y;
+ }
+
+ copy_v3_v3(curve_mapping_settings->black, curve_mapping->black);
+ copy_v3_v3(curve_mapping_settings->bwmul, curve_mapping->bwmul);
+
+ curve_mapping_settings->cache_id = (size_t) curve_mapping;
+}
+
static void update_glsl_display_processor(const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *from_colorspace)
{
+ bool use_curve_mapping = (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) != 0;
+ bool need_update = false;
+
+ need_update = global_glsl_state.processor == NULL ||
+ check_glsl_display_processor_changed(view_settings, display_settings, from_colorspace) ||
+ use_curve_mapping != global_glsl_state.use_curve_mapping;
+
+ if (use_curve_mapping && need_update == false) {
+ need_update |= view_settings->curve_mapping->changed_timestamp != global_glsl_state.curve_mapping_timestamp ||
+ view_settings->curve_mapping != global_glsl_state.orig_curve_mapping;
+ }
+
/* Update state if there's no processor yet or
* processor settings has been changed.
*/
- if (global_glsl_state.processor == NULL ||
- check_glsl_display_processor_changed(view_settings, display_settings, from_colorspace))
- {
+ if (need_update) {
+ OCIO_CurveMappingSettings *curve_mapping_settings = &global_glsl_state.curve_mapping_settings;
+ CurveMapping *new_curve_mapping = NULL;
+
/* Store settings of processor for further comparison. */
BLI_strncpy(global_glsl_state.look, view_settings->look, MAX_COLORSPACE_NAME);
BLI_strncpy(global_glsl_state.view, view_settings->view_transform, MAX_COLORSPACE_NAME);
@@ -2949,6 +3011,35 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s
global_glsl_state.exposure = view_settings->exposure;
global_glsl_state.gamma = view_settings->gamma;
+ /* We're using curve mapping's address as a acache ID,
+ * so we need to make sure re-allocation gives new address here.
+ * We do this by allocating new curve mapping before freeing ol one.
+ */
+ if (use_curve_mapping) {
+ new_curve_mapping = curvemapping_copy(view_settings->curve_mapping);
+ }
+
+ if (global_glsl_state.curve_mapping) {
+ curvemapping_free(global_glsl_state.curve_mapping);
+ MEM_freeN(curve_mapping_settings->lut);
+ global_glsl_state.curve_mapping = NULL;
+ curve_mapping_settings->lut = NULL;
+ }
+
+ /* Fill in OCIO's curve mapping settings. */
+ if (use_curve_mapping) {
+ curve_mapping_to_ocio_settings(new_curve_mapping, &global_glsl_state.curve_mapping_settings);
+
+ global_glsl_state.curve_mapping = new_curve_mapping;
+ global_glsl_state.curve_mapping_timestamp = view_settings->curve_mapping->changed_timestamp;
+ global_glsl_state.orig_curve_mapping = view_settings->curve_mapping;
+ global_glsl_state.use_curve_mapping = true;
+ }
+ else {
+ global_glsl_state.orig_curve_mapping = NULL;
+ global_glsl_state.use_curve_mapping = false;
+ }
+
/* Free old processor, if any. */
if (global_glsl_state.processor)
OCIO_processorRelease(global_glsl_state.processor);
@@ -2964,14 +3055,8 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s
}
}
-bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *view_settings,
- bool skip_curves)
+bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *UNUSED(view_settings))
{
- /* curves not supported yet */
- if (!skip_curves)
- if (view_settings && (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES))
- return 0;
-
return OCIO_supportGLSLDraw();
}
@@ -2990,8 +3075,7 @@ bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *view_
*/
bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
- struct ColorSpace *from_colorspace, bool predivide,
- bool skip_curves)
+ struct ColorSpace *from_colorspace, bool predivide)
{
ColorManagedViewSettings default_view_settings;
const ColorManagedViewSettings *applied_view_settings;
@@ -3008,25 +3092,22 @@ bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettin
applied_view_settings = &default_view_settings;
}
- /* RGB curves mapping is not supported on GPU yet. */
- if (!skip_curves)
- if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)
- return false;
-
/* Make sure OCIO processor is up-to-date. */
update_glsl_display_processor(applied_view_settings, display_settings,
from_colorspace ? from_colorspace->name : global_role_scene_linear);
- return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor, predivide);
+ return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor,
+ global_glsl_state.use_curve_mapping ? &global_glsl_state.curve_mapping_settings : NULL,
+ predivide);
}
/* Configures GLSL shader for conversion from scene linear to display space */
bool IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
- bool predivide, bool skip_curves)
+ bool predivide)
{
return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- NULL, predivide, skip_curves);
+ NULL, predivide);
}
/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */
@@ -3037,7 +3118,7 @@ bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C
IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
- return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide, false);
+ return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide);
}
/* Same as setup_glsl_draw, but color management settings are guessing from a given context */
@@ -3076,7 +3157,7 @@ bool IMB_colormanagement_setup_transform_from_role_glsl(int role, bool predivide
processor = colorspace_to_scene_linear_processor(colorspace);
- return OCIO_setupGLSLDraw(&global_glsl_state.transform_ocio_glsl_state, processor, predivide);
+ return OCIO_setupGLSLDraw(&global_glsl_state.transform_ocio_glsl_state, processor, NULL, predivide);
}
/* Finish GLSL-based color space conversion */
diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c
index 37070c7e2bf..f9e05dbd6d6 100644
--- a/source/blender/imbuf/intern/filetype.c
+++ b/source/blender/imbuf/intern/filetype.c
@@ -35,6 +35,10 @@
#include "IMB_colormanagement.h"
+#ifdef WITH_OPENIMAGEIO
+#include "oiio/openimageio_api.h"
+#endif
+
#ifdef WITH_OPENEXR
#include "openexr/openexr_api.h"
#endif
@@ -71,41 +75,46 @@ void quicktime_exit(void);
#endif
ImFileType IMB_FILE_TYPES[] = {
- {NULL, NULL, imb_is_a_jpeg, imb_ftype_default, imb_load_jpeg, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE},
- {NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE},
- {NULL, NULL, imb_is_a_bmp, imb_ftype_default, imb_bmp_decode, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE},
- {NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE},
- {NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_jpeg, NULL, imb_ftype_default, imb_load_jpeg, NULL, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_png, NULL, imb_ftype_default, imb_loadpng, NULL, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_bmp, NULL, imb_ftype_default, imb_bmp_decode, NULL, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_targa, NULL, imb_ftype_default, imb_loadtarga, NULL, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_iris, NULL, imb_ftype_iris, imb_loadiris, NULL, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE},
#ifdef WITH_CINEON
- {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_load_dpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT},
- {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_load_cineon, imb_save_cineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT},
+ {NULL, NULL, imb_is_dpx, NULL, imb_ftype_default, imb_load_dpx, NULL, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT},
+ {NULL, NULL, imb_is_cineon, NULL, imb_ftype_default, imb_load_cineon, NULL, imb_save_cineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT},
#endif
#ifdef WITH_TIFF
- {imb_inittiff, NULL, imb_is_a_tiff, imb_ftype_default, imb_loadtiff, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE},
+ {imb_inittiff, NULL, imb_is_a_tiff, NULL, imb_ftype_default, imb_loadtiff, NULL, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE},
#endif
#ifdef WITH_HDR
- {NULL, NULL, imb_is_a_hdr, imb_ftype_default, imb_loadhdr, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR, COLOR_ROLE_DEFAULT_FLOAT},
+ {NULL, NULL, imb_is_a_hdr, NULL, imb_ftype_default, imb_loadhdr, NULL, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR, COLOR_ROLE_DEFAULT_FLOAT},
#endif
#ifdef WITH_OPENEXR
- {imb_initopenexr, NULL, imb_is_a_openexr, imb_ftype_default, imb_load_openexr, imb_save_openexr, NULL, IM_FTYPE_FLOAT, OPENEXR, COLOR_ROLE_DEFAULT_FLOAT},
+ {imb_initopenexr, NULL, imb_is_a_openexr, NULL, imb_ftype_default, imb_load_openexr, NULL, imb_save_openexr, NULL, IM_FTYPE_FLOAT, OPENEXR, COLOR_ROLE_DEFAULT_FLOAT},
#endif
#ifdef WITH_OPENJPEG
- {NULL, NULL, imb_is_a_jp2, imb_ftype_default, imb_jp2_decode, imb_savejp2, NULL, IM_FTYPE_FLOAT, JP2, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_jp2, NULL, imb_ftype_default, imb_jp2_decode, NULL, imb_savejp2, NULL, IM_FTYPE_FLOAT, JP2, COLOR_ROLE_DEFAULT_BYTE},
#endif
#ifdef WITH_DDS
- {NULL, NULL, imb_is_a_dds, imb_ftype_default, imb_load_dds, NULL, NULL, 0, DDS, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_dds, NULL, imb_ftype_default, imb_load_dds, NULL, NULL, NULL, 0, DDS, COLOR_ROLE_DEFAULT_BYTE},
#endif
#ifdef WITH_QUICKTIME
- {quicktime_init, quicktime_exit, imb_is_a_quicktime, imb_ftype_quicktime, imb_quicktime_decode, NULL, NULL, 0, QUICKTIME, COLOR_ROLE_DEFAULT_BYTE},
+ {quicktime_init, quicktime_exit, imb_is_a_quicktime, NULL, imb_ftype_quicktime, imb_quicktime_decode, NULL, NULL, 0, QUICKTIME, COLOR_ROLE_DEFAULT_BYTE},
+#endif
+#ifdef WITH_OPENIMAGEIO
+ {NULL, NULL, NULL, imb_is_a_photoshop, imb_ftype_default, NULL, imb_load_photoshop, NULL, NULL, IM_FTYPE_FLOAT, PSD, COLOR_ROLE_DEFAULT_FLOAT},
#endif
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0}
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0}
};
-
+
+ImFileType *IMB_FILE_TYPES_LAST = &IMB_FILE_TYPES[sizeof(IMB_FILE_TYPES) / sizeof(ImFileType) - 1];
+
void imb_filetypes_init(void)
{
ImFileType *type;
- for (type = IMB_FILE_TYPES; type->is_a; type++)
+ for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++)
if (type->init)
type->init();
}
@@ -114,7 +123,7 @@ void imb_filetypes_exit(void)
{
ImFileType *type;
- for (type = IMB_FILE_TYPES; type->is_a; type++)
+ for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++)
if (type->exit)
type->exit();
}
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index dd0970a71f2..93324b94cdc 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -55,12 +55,12 @@
#endif
-static char magic[] = "BlenMIdx";
-static char temp_ext[] = "_part";
+static const char magic[] = "BlenMIdx";
+static const char temp_ext[] = "_part";
-static int proxy_sizes[] = { IMB_PROXY_25, IMB_PROXY_50, IMB_PROXY_75,
+static const int proxy_sizes[] = { IMB_PROXY_25, IMB_PROXY_50, IMB_PROXY_75,
IMB_PROXY_100 };
-static float proxy_fac[] = { 0.25, 0.50, 0.75, 1.00 };
+static const float proxy_fac[] = { 0.25, 0.50, 0.75, 1.00 };
#ifdef WITH_FFMPEG
static int tc_types[] = {IMB_TC_RECORD_RUN,
diff --git a/source/blender/imbuf/intern/oiio/CMakeLists.txt b/source/blender/imbuf/intern/oiio/CMakeLists.txt
new file mode 100644
index 00000000000..5fb8f11602e
--- /dev/null
+++ b/source/blender/imbuf/intern/oiio/CMakeLists.txt
@@ -0,0 +1,54 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2013, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s):
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ..
+ ../..
+ ../../../blenkernel
+ ../../../blenlib
+ ../../../makesdna
+ ../../../../../intern/guardedalloc
+ ../../../../../intern/utfconv
+)
+
+set(INC_SYS
+
+)
+
+set(SRC
+ openimageio_api.h
+
+ openimageio_api.cpp
+)
+
+if(WITH_OPENIMAGEIO)
+ list(APPEND INC_SYS
+ ${OPENIMAGEIO_INCLUDE_DIRS}
+ )
+ add_definitions(-DWITH_OPENIMAGEIO)
+endif()
+
+blender_add_lib(bf_imbuf_openimageio "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/imbuf/intern/oiio/SConscript b/source/blender/imbuf/intern/oiio/SConscript
new file mode 100644
index 00000000000..82b47e9c46b
--- /dev/null
+++ b/source/blender/imbuf/intern/oiio/SConscript
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2013, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s):
+#
+# ***** END GPL LICENSE BLOCK *****
+
+Import ('env')
+
+source_files = ['openimageio_api.cpp']
+
+incs = ['.',
+ '../../../blenkernel',
+ '../../',
+ '..',
+ '../../../blenlib',
+ 'intern/include',
+ '#/intern/guardedalloc',
+ '../../../makesdna',
+ '#/intern/utfconv']
+
+incs += Split(env['BF_OIIO_INC'])
+
+defs = ['WITH_OPENIMAGEIO']
+
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
+ incs.append(env['BF_PTHREADS_INC'])
+
+env.BlenderLib ('bf_imbuf_openimageio', source_files, incs, defs, libtype=['core','player'], priority = [225,180])
diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
new file mode 100644
index 00000000000..838343dce35
--- /dev/null
+++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
@@ -0,0 +1,256 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Dalai Felinto and Brecht van Lommel
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/imbuf/intern/oiio/openimageio_api.cpp
+ * \ingroup openimageio
+ */
+
+#include <set>
+
+#include <openimageio_api.h>
+#include <OpenImageIO/imageio.h>
+
+OIIO_NAMESPACE_USING
+
+#if defined(WIN32) && !defined(FREE_WINDOWS)
+#include "utfconv.h"
+#endif
+
+extern "C"
+{
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "IMB_allocimbuf.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+}
+
+using namespace std;
+
+typedef unsigned char uchar;
+
+template <class T, class Q>
+static void fill_all_channels(T *pixels, int width, int height, int components, Q alpha)
+{
+ if (components == 2) {
+ for (int i = width * height - 1; i >= 0; i--) {
+ pixels[i * 4 + 3] = pixels[i * 2 + 1];
+ pixels[i * 4 + 2] = pixels[i * 2 + 0];
+ pixels[i * 4 + 1] = pixels[i * 2 + 0];
+ pixels[i * 4 + 0] = pixels[i * 2 + 0];
+ }
+ }
+ else if (components == 3) {
+ for (int i = width * height - 1; i >= 0; i--) {
+ pixels[i * 4 + 3] = alpha;
+ pixels[i * 4 + 2] = pixels[i * 3 + 2];
+ pixels[i * 4 + 1] = pixels[i * 3 + 1];
+ pixels[i * 4 + 0] = pixels[i * 3 + 0];
+
+ }
+ }
+ else if (components == 1) {
+ for (int i = width * height - 1; i >= 0; i--) {
+ pixels[i * 4 + 3] = alpha;
+ pixels[i * 4 + 2] = pixels[i];
+ pixels[i * 4 + 1] = pixels[i];
+ pixels[i * 4 + 0] = pixels[i];
+ }
+ }
+
+}
+
+static ImBuf *imb_oiio_load_image(ImageInput *in, int width, int height, int components, int flags, bool is_alpha)
+{
+ ImBuf *ibuf;
+ int scanlinesize = width * components * sizeof(uchar);
+
+ /* allocate the memory for the image */
+ ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rect);
+
+ try
+ {
+ in->read_image(TypeDesc::UINT8,
+ (uchar *)ibuf->rect + (height - 1) * scanlinesize,
+ AutoStride,
+ -scanlinesize,
+ AutoStride);
+ }
+ catch (const std::exception &exc)
+ {
+ std::cerr << exc.what() << std::endl;
+ if (ibuf) IMB_freeImBuf(ibuf);
+
+ return NULL;
+ }
+
+ /* ImBuf always needs 4 channels */
+ fill_all_channels((uchar *)ibuf->rect, width, height, components, 0xFF);
+
+ return ibuf;
+}
+
+static ImBuf *imb_oiio_load_image_float(ImageInput *in, int width, int height, int components, int flags, bool is_alpha)
+{
+ ImBuf *ibuf;
+ int scanlinesize = width * components * sizeof(float);
+
+ /* allocate the memory for the image */
+ ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rectfloat);
+
+ try
+ {
+ in->read_image(TypeDesc::FLOAT,
+ (uchar *)ibuf->rect_float + (height - 1) * scanlinesize,
+ AutoStride,
+ -scanlinesize,
+ AutoStride);
+ }
+ catch (const std::exception &exc)
+ {
+ std::cerr << exc.what() << std::endl;
+ if (ibuf) IMB_freeImBuf(ibuf);
+
+ return NULL;
+ }
+
+ /* ImBuf always needs 4 channels */
+ fill_all_channels((float *)ibuf->rect_float, width, height, components, 1.0f);
+
+ /* note: Photoshop 16 bit files never has alpha with it, so no need to handle associated/unassociated alpha */
+ return ibuf;
+}
+
+extern "C"
+{
+
+int imb_is_a_photoshop(const char *filename)
+{
+ const char *photoshop_extension[] = {
+ ".psd",
+ ".pdd",
+ ".psb",
+ NULL
+ };
+
+ return BLI_testextensie_array(filename, photoshop_extension);
+}
+
+int imb_save_photoshop(struct ImBuf *ibuf, const char *name, int flags)
+{
+ if (flags & IB_mem) {
+ printf("Photoshop PSD-save: Create PSD in memory CURRENTLY NOT SUPPORTED !\n");
+ imb_addencodedbufferImBuf(ibuf);
+ ibuf->encodedsize = 0;
+ return(0);
+ }
+
+ return(0);
+}
+
+struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspace[IM_MAX_SPACE])
+{
+ ImageInput *in = NULL;
+ struct ImBuf *ibuf = NULL;
+ int width, height, components;
+ bool is_float, is_alpha;
+ TypeDesc typedesc;
+ int basesize;
+
+ /* load image from file through OIIO */
+ if (imb_is_a_photoshop(filename) == 0) return (NULL);
+
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+
+ in = ImageInput::create(filename);
+ if (!in) return NULL;
+
+ ImageSpec spec, config;
+ config.attribute("oiio:UnassociatedAlpha", (int) 1);
+
+ if (!in->open(filename, spec, config)) {
+ delete in;
+ return NULL;
+ }
+
+ string ics = spec.get_string_attribute("oiio:ColorSpace");
+ BLI_strncpy(colorspace, ics.c_str(), IM_MAX_SPACE);
+
+ width = spec.width;
+ height = spec.height;
+ components = spec.nchannels;
+ is_alpha = spec.alpha_channel != -1;
+ basesize = spec.format.basesize();
+ is_float = basesize > 1;
+
+ /* we only handle certain number of components */
+ if (!(components >= 1 && components <= 4)) {
+ if (in) {
+ in->close();
+ delete in;
+ }
+ return NULL;
+ }
+
+ if (is_float)
+ ibuf = imb_oiio_load_image_float(in, width, height, components, flags, is_alpha);
+ else
+ ibuf = imb_oiio_load_image(in, width, height, components, flags, is_alpha);
+
+ if (in) {
+ in->close();
+ delete in;
+ }
+
+ if (!ibuf)
+ return NULL;
+
+ /* ImBuf always needs 4 channels */
+ ibuf->ftype = PSD;
+ ibuf->channels = 4;
+ ibuf->planes = (3 + (is_alpha ? 1 : 0)) * 4 << basesize;
+
+ try
+ {
+ return ibuf;
+ }
+ catch (const std::exception &exc)
+ {
+ std::cerr << exc.what() << std::endl;
+ if (ibuf) IMB_freeImBuf(ibuf);
+
+ return NULL;
+ }
+}
+
+} // export "C"
+
+
diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.h b/source/blender/imbuf/intern/oiio/openimageio_api.h
new file mode 100644
index 00000000000..ad11f4bcfe3
--- /dev/null
+++ b/source/blender/imbuf/intern/oiio/openimageio_api.h
@@ -0,0 +1,53 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/imbuf/intern/oiio/openimageio_api.h
+ * \ingroup openimageio
+ */
+
+
+#ifndef __OPENIMAGEIO_API_H__
+#define __OPENIMAGEIO_API_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+
+int imb_is_a_photoshop (const char *name);
+
+int imb_save_photoshop (struct ImBuf *ibuf, const char *name, int flags);
+
+struct ImBuf *imb_load_photoshop (const char *name, int flags, char *colorspace);
+
+#ifdef __cplusplus
+}
+
+#endif
+
+#endif /* __OPENIMAGEIO_API_H__ */
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index d73fa9a7ab7..6988687e4ed 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -56,6 +56,53 @@
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
+static void imb_handle_alpha(ImBuf *ibuf, int flags, char colorspace[IM_MAX_SPACE], char effective_colorspace[IM_MAX_SPACE])
+{
+ int alpha_flags;
+
+ if (colorspace) {
+ if (ibuf->rect) {
+ /* byte buffer is never internally converted to some standard space,
+ * store pointer to it's color space descriptor instead
+ */
+ ibuf->rect_colorspace = colormanage_colorspace_get_named(effective_colorspace);
+ }
+
+ BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE);
+ }
+
+ if (flags & IB_alphamode_detect)
+ alpha_flags = ibuf->flags & IB_alphamode_premul;
+ else
+ alpha_flags = flags & IB_alphamode_premul;
+
+ if (flags & IB_ignore_alpha) {
+ IMB_rectfill_alpha(ibuf, 1.0f);
+ }
+ else {
+ if (alpha_flags & IB_alphamode_premul) {
+ if (ibuf->rect) {
+ IMB_unpremultiply_alpha(ibuf);
+ }
+ else {
+ /* pass, floats are expected to be premul */
+ }
+ }
+ else {
+ if (ibuf->rect_float) {
+ IMB_premultiply_alpha(ibuf);
+ }
+ else {
+ /* pass, bytes are expected to be straight */
+ }
+ }
+ }
+
+ /* OCIO_TODO: in some cases it's faster to do threaded conversion,
+ * but how to distinguish such cases */
+ colormanage_imbuf_make_linear(ibuf, effective_colorspace);
+}
+
ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
{
ImBuf *ibuf;
@@ -70,54 +117,36 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co
if (colorspace)
BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace));
- for (type = IMB_FILE_TYPES; type->is_a; type++) {
+ for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
if (type->load) {
ibuf = type->load(mem, size, flags, effective_colorspace);
if (ibuf) {
- int alpha_flags;
-
- if (colorspace) {
- if (ibuf->rect) {
- /* byte buffer is never internally converted to some standard space,
- * store pointer to it's color space descriptor instead
- */
- ibuf->rect_colorspace = colormanage_colorspace_get_named(effective_colorspace);
- }
-
- BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE);
- }
-
- if (flags & IB_alphamode_detect)
- alpha_flags = ibuf->flags & IB_alphamode_premul;
- else
- alpha_flags = flags & IB_alphamode_premul;
-
- if (flags & IB_ignore_alpha) {
- IMB_rectfill_alpha(ibuf, 1.0f);
- }
- else {
- if (alpha_flags & IB_alphamode_premul) {
- if (ibuf->rect) {
- IMB_unpremultiply_alpha(ibuf);
- }
- else {
- /* pass, floats are expected to be premul */
- }
- }
- else {
- if (ibuf->rect_float) {
- IMB_premultiply_alpha(ibuf);
- }
- else {
- /* pass, bytes are expected to be straight */
- }
- }
- }
-
- /* OCIO_TODO: in some cases it's faster to do threaded conversion,
- * but how to distinguish such cases */
- colormanage_imbuf_make_linear(ibuf, effective_colorspace);
+ imb_handle_alpha(ibuf, flags, colorspace, effective_colorspace);
+ return ibuf;
+ }
+ }
+ }
+
+ if ((flags & IB_test) == 0)
+ fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr);
+
+ return NULL;
+}
+
+static ImBuf *IMB_ibImageFromFile(const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
+{
+ ImBuf *ibuf;
+ ImFileType *type;
+ char effective_colorspace[IM_MAX_SPACE] = "";
+
+ if (colorspace)
+ BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace));
+ for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
+ if (type->load_filepath) {
+ ibuf = type->load_filepath(filepath, flags, effective_colorspace);
+ if (ibuf) {
+ imb_handle_alpha(ibuf, flags, colorspace, effective_colorspace);
return ibuf;
}
}
@@ -129,7 +158,13 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co
return NULL;
}
-ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
+static bool imb_is_filepath_format(const char *filepath)
+{
+ /* return true if this is one of the formats that can't be loaded from memory */
+ return BLI_testextensie_array(filepath, imb_ext_image_filepath_only);
+}
+
+ImBuf *IMB_loadifffile(int file, const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
{
ImBuf *ibuf;
unsigned char *mem;
@@ -137,6 +172,9 @@ ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const
if (file == -1) return NULL;
+ if (imb_is_filepath_format(filepath))
+ return IMB_ibImageFromFile(filepath, flags, colorspace, descr);
+
size = BLI_file_descriptor_size(file);
mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0);
@@ -179,7 +217,7 @@ ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_S
file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0);
if (file < 0) return NULL;
- ibuf = IMB_loadifffile(file, flags, colorspace, filepath_tx);
+ ibuf = IMB_loadifffile(file, filepath, flags, colorspace, filepath_tx);
if (ibuf) {
BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
@@ -206,7 +244,7 @@ ImBuf *IMB_testiffname(const char *filepath, int flags)
file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0);
if (file < 0) return NULL;
- ibuf = IMB_loadifffile(file, flags | IB_test | IB_multilayer, colorspace, filepath_tx);
+ ibuf = IMB_loadifffile(file, filepath, flags | IB_test | IB_multilayer, colorspace, filepath_tx);
if (ibuf) {
BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
@@ -234,7 +272,7 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int
return;
}
- for (type = IMB_FILE_TYPES; type->is_a; type++)
+ for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++)
if (type->load_tile && type->ftype(type, ibuf))
type->load_tile(ibuf, mem, size, tx, ty, rect);
diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c
index eaba04c9310..05e9a4fa134 100644
--- a/source/blender/imbuf/intern/tiff.c
+++ b/source/blender/imbuf/intern/tiff.c
@@ -315,7 +315,7 @@ int imb_is_a_tiff(unsigned char *mem)
(memcmp(lil_endian, mem, IMB_TIFF_NCB) == 0) );
}
-static void scanline_contig_16bit(float *rectf, unsigned short *sbuf, int scanline_w, int spp)
+static void scanline_contig_16bit(float *rectf, const unsigned short *sbuf, int scanline_w, int spp)
{
int i;
for (i = 0; i < scanline_w; i++) {
@@ -326,7 +326,7 @@ static void scanline_contig_16bit(float *rectf, unsigned short *sbuf, int scanli
}
}
-static void scanline_contig_32bit(float *rectf, float *fbuf, int scanline_w, int spp)
+static void scanline_contig_32bit(float *rectf, const float *fbuf, int scanline_w, int spp)
{
int i;
for (i = 0; i < scanline_w; i++) {
@@ -337,14 +337,14 @@ static void scanline_contig_32bit(float *rectf, float *fbuf, int scanline_w, int
}
}
-static void scanline_separate_16bit(float *rectf, unsigned short *sbuf, int scanline_w, int chan)
+static void scanline_separate_16bit(float *rectf, const unsigned short *sbuf, int scanline_w, int chan)
{
int i;
for (i = 0; i < scanline_w; i++)
rectf[i * 4 + chan] = sbuf[i] / 65535.0;
}
-static void scanline_separate_32bit(float *rectf, float *fbuf, int scanline_w, int chan)
+static void scanline_separate_32bit(float *rectf, const float *fbuf, int scanline_w, int chan)
{
int i;
for (i = 0; i < scanline_w; i++)
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index a4b0e61d544..ecf6458ac57 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -98,6 +98,16 @@ const char *imb_ext_image[] = {
#ifdef WITH_OPENEXR
".exr",
#endif
+#ifdef WITH_OPENIMAGEIO
+ ".psd", ".pdd", ".psb",
+#endif
+ NULL
+};
+
+const char *imb_ext_image_filepath_only[] = {
+#ifdef WITH_OPENIMAGEIO
+ ".psd", ".pdd", ".psb",
+#endif
NULL
};
@@ -188,9 +198,16 @@ static int IMB_ispic_name(const char *name)
if ((BIG_LONG(((int *)buf)[0]) & 0xfffffff0) == 0xffd8ffe0)
return JPG;
- for (type = IMB_FILE_TYPES; type->is_a; type++) {
- if (type->is_a(buf)) {
- return type->filetype;
+ for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
+ if (type->is_a) {
+ if (type->is_a(buf)) {
+ return type->filetype;
+ }
+ }
+ else if (type->is_a_filepath) {
+ if (type->is_a_filepath(name)) {
+ return type->filetype;
+ }
}
}
diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c
index 5d785e08212..1519fc1990d 100644
--- a/source/blender/imbuf/intern/writeimage.c
+++ b/source/blender/imbuf/intern/writeimage.c
@@ -67,7 +67,7 @@ short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags)
if (ibuf == NULL) return (FALSE);
ibuf->flags = flags;
- for (type = IMB_FILE_TYPES; type->is_a; type++) {
+ for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
if (type->save && type->ftype(type, ibuf)) {
ImBuf *write_ibuf;
short result = FALSE;
diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h
index 4307ea57f15..a72e287c16f 100644
--- a/source/blender/makesdna/DNA_mask_types.h
+++ b/source/blender/makesdna/DNA_mask_types.h
@@ -178,6 +178,7 @@ enum {
/* SpaceClip->mask_draw_flag */
#define MASK_DRAWFLAG_SMOOTH 1
+#define MASK_DRAWFLAG_OVERLAY 2
/* copy of eSpaceImage_UVDT */
/* SpaceClip->mask_draw_type */
@@ -188,6 +189,12 @@ enum {
MASK_DT_WHITE = 3
};
+/* MaskSpaceInfo->overlay_mode */
+enum {
+ MASK_OVERLAY_ALPHACHANNEL = 0,
+ MASK_OVERLAY_COMBINED = 1
+};
+
/* masklay->blend */
enum {
MASK_BLEND_ADD = 0,
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 5cfe3fd2082..75b9540f736 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -149,23 +149,16 @@ typedef enum eNodeSocketInOut {
} eNodeSocketInOut;
/* sock->flag, first bit is select */
- /* hidden is user defined, to hide unused */
-#define SOCK_HIDDEN 2
- /* for quick check if socket is linked */
-#define SOCK_IN_USE 4
- /* unavailable is for dynamic sockets */
-#define SOCK_UNAVAIL 8
- /* DEPRECATED dynamic socket (can be modified by user) */
-#define __SOCK_DYNAMIC 16
- /* DEPRECATED group socket should not be exposed */
-#define __SOCK_INTERNAL 32
- /* socket collapsed in UI */
-#define SOCK_COLLAPSED 64
- /* hide socket value, if it gets auto default */
-#define SOCK_HIDE_VALUE 128
- /* socket hidden automatically, to distinguish from manually hidden */
- /* DEPRECATED, only kept here to avoid reusing the flag */
-#define SOCK_AUTO_HIDDEN__DEPRECATED 256
+typedef enum eNodeSocketFlag {
+ SOCK_HIDDEN = 2, /* hidden is user defined, to hide unused */
+ SOCK_IN_USE = 4, /* for quick check if socket is linked */
+ SOCK_UNAVAIL = 8, /* unavailable is for dynamic sockets */
+ __SOCK_DYNAMIC = 16, /* DEPRECATED dynamic socket (can be modified by user) */
+ __SOCK_INTERNAL = 32, /* DEPRECATED group socket should not be exposed */
+ SOCK_COLLAPSED = 64, /* socket collapsed in UI */
+ SOCK_HIDE_VALUE = 128, /* hide socket value, if it gets auto default */
+ SOCK_AUTO_HIDDEN__DEPRECATED = 256 /* socket hidden automatically, to distinguish from manually hidden */
+} eNodeSocketFlag;
/* limit data in bNode to what we want to see saved? */
typedef struct bNode {
@@ -976,7 +969,7 @@ typedef struct NodeShaderNormalMap {
#define SHD_NORMAL_MAP_BLENDER_WORLD 4
/* subsurface */
-#define SHD_SUBSURFACE_COMPATIBLE 0
+#define SHD_SUBSURFACE_COMPATIBLE 0 // Deprecated
#define SHD_SUBSURFACE_CUBIC 1
#define SHD_SUBSURFACE_GAUSSIAN 2
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 002d77fb0e6..232fe62df31 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -316,6 +316,7 @@ typedef struct ImageFormatData {
#define R_IMF_IMTYPE_H264 31
#define R_IMF_IMTYPE_XVID 32
#define R_IMF_IMTYPE_THEORA 33
+#define R_IMF_IMTYPE_PSD 34
#define R_IMF_IMTYPE_INVALID 255
@@ -510,6 +511,7 @@ typedef struct RenderData {
short bake_normal_space, bake_quad_split;
float bake_maxdist, bake_biasdist;
short bake_samples, bake_pad;
+ float bake_user_scale, bake_pad1;
/* path to render output */
char pic[1024]; /* 1024 = FILE_MAX */
@@ -981,17 +983,6 @@ typedef struct ToolSettings {
* paint */
float vgroup_weight;
- /* Subdivide Settings */
- short cornertype;
- short pad1;
- /*Triangle to Quad conversion threshold*/
- float jointrilimit;
- /* Editmode Tools */
- float degr;
- short step;
- short turn;
-
- float extr_offs; /* extrude offset */
float doublimit; /* remove doubles limit */
float normalsize; /* size of normals */
short automerge;
@@ -999,30 +990,21 @@ typedef struct ToolSettings {
/* Selection Mode for Mesh */
short selectmode;
- /* Primitive Settings */
- /* UV Sphere */
- short segments;
- short rings;
-
- /* Cylinder - Tube - Circle */
- short vertices;
-
/* UV Calculation */
- short unwrapper;
- float uvcalc_radius;
- float uvcalc_cubesize;
+ char unwrapper;
+ char uvcalc_flag;
+ char uv_flag;
+ char uv_selectmode;
+
float uvcalc_margin;
- short uvcalc_mapdir;
- short uvcalc_mapalign;
- short uvcalc_flag;
- short uv_flag, uv_selectmode;
- short pad2;
-
- /* Grease Pencil */
- short gpencil_flags;
-
+
/* Auto-IK */
- short autoik_chainlen;
+ short autoik_chainlen; /* runtime only */
+
+ /* Grease Pencil */
+ char gpencil_flags;
+
+ char pad[5];
/* Image Paint (8 byttse aligned please!) */
struct ImagePaintSettings imapaint;
@@ -1035,16 +1017,13 @@ typedef struct ToolSettings {
/* Select Group Threshold */
float select_thresh;
-
- /* Graph Editor */
- float clean_thresh;
/* Auto-Keying Mode */
short autokey_mode, autokey_flag; /* defines in DNA_userdef_types.h */
/* Multires */
char multires_subdiv_type;
- char pad3[5];
+ char pad3[1];
/* Skeleton generation */
short skgen_resolution;
@@ -1375,6 +1354,7 @@ typedef struct Scene {
#define R_BAKE_MULTIRES 16
#define R_BAKE_LORES_MESH 32
#define R_BAKE_VCOL 64
+#define R_BAKE_USERSCALE 128
/* bake_normal_space */
#define R_BAKE_SPACE_CAMERA 0
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 0478ff567a0..5befaa87e7f 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -546,7 +546,8 @@ typedef struct MaskSpaceInfo
/* draw options */
char draw_flag;
char draw_type;
- char pad3[6];
+ char overlay_mode;
+ char pad3[5];
} MaskSpaceInfo;
/* sseq->mainb */
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index cae607949a9..317141b14e3 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -40,6 +40,8 @@ blender_include_dirs(
set(SRC
makesdna.c
../../../../intern/guardedalloc/intern/mallocn.c
+ ../../../../intern/guardedalloc/intern/mallocn_guarded_impl.c
+ ../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c
)
if(WIN32 AND NOT UNIX)
@@ -50,11 +52,6 @@ endif()
# SRC_DNA_INC is defined in the parent dir
-# for mallocn.c
-if (WITH_GUARDEDALLOC)
- add_definitions(-DWITH_GUARDEDALLOC)
-endif()
-
add_executable(makesdna ${SRC} ${SRC_DNA_INC})
# Output dna.c
diff --git a/source/blender/makesdna/intern/SConscript b/source/blender/makesdna/intern/SConscript
index 7c3af30ee83..35b4ff262ed 100644
--- a/source/blender/makesdna/intern/SConscript
+++ b/source/blender/makesdna/intern/SConscript
@@ -36,8 +36,6 @@ cflags = ''
defines = []
root_build_dir=normpath(env['BF_BUILDDIR'])
-defines.append('WITH_GUARDEDALLOC')
-
source_files = ['makesdna.c']
header_files = env.Glob('../*.h')
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 89ddb59aab5..2b1a5bc71ff 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -42,8 +42,8 @@ extern "C" {
BlenderRNA *RNA_create(void);
void RNA_define_free(BlenderRNA *brna);
void RNA_free(BlenderRNA *brna);
-void RNA_define_verify_sdna(int verify);
-void RNA_define_animate_sdna(int animate);
+void RNA_define_verify_sdna(bool verify);
+void RNA_define_animate_sdna(bool animate);
void RNA_init(void);
void RNA_exit(void);
@@ -225,6 +225,10 @@ const char *RNA_property_typename(PropertyType type);
void RNA_identifier_sanitize(char *identifier, int property);
+extern const int rna_matrix_dimsize_3x3[];
+extern const int rna_matrix_dimsize_4x4[];
+extern const int rna_matrix_dimsize_4x2[];
+
/* max size for dynamic defined type descriptors,
* this value is arbitrary */
#define RNA_DYN_DESCR_MAX 240
diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript
index dfe1ebb3385..5053c8082e9 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -66,6 +66,9 @@ if env['WITH_BF_BULLET']:
defs.append('WITH_BULLET')
incs += ' #/intern/rigidbody'
+if env['WITH_BF_OIIO']:
+ defs.append('WITH_OPENIMAGEIO')
+
if env['WITH_BF_OPENEXR']:
defs.append('WITH_OPENEXR')
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index d901897cbc4..9b2fc2c3c4d 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -137,6 +137,8 @@ set(SRC
${DEFSRC}
${APISRC}
../../../../intern/guardedalloc/intern/mallocn.c
+ ../../../../intern/guardedalloc/intern/mallocn_guarded_impl.c
+ ../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c
../../../../intern/guardedalloc/intern/mmap_win.c
)
@@ -164,6 +166,10 @@ if(WITH_IMAGE_OPENEXR)
add_definitions(-DWITH_OPENEXR)
endif()
+if(WITH_OPENIMAGEIO)
+ add_definitions(-DWITH_OPENIMAGEIO)
+endif()
+
if(WITH_IMAGE_TIFF)
add_definitions(-DWITH_TIFF)
endif()
@@ -249,11 +255,6 @@ if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()
-# for mallocn.c
-if (WITH_GUARDEDALLOC)
- add_definitions(-DWITH_GUARDEDALLOC)
-endif()
-
# Build makesrna executable
blender_include_dirs(
.
diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript
index 10b6a8c8d10..fe6950e62dd 100644
--- a/source/blender/makesrna/intern/SConscript
+++ b/source/blender/makesrna/intern/SConscript
@@ -82,6 +82,9 @@ if env['WITH_BF_BULLET']:
defs.append('WITH_BULLET')
incs += ' #/intern/rigidbody'
+if env['WITH_BF_OIIO']:
+ defs.append('WITH_OPENIMAGEIO')
+
if env['WITH_BF_OPENEXR']:
defs.append('WITH_OPENEXR')
@@ -150,8 +153,6 @@ if env['WITH_BF_INTERNATIONAL']:
if not env['BF_DEBUG']:
defs.append('NDEBUG')
-defs.append('WITH_GUARDEDALLOC')
-
makesrna_tool.Append(CPPDEFINES=defs)
makesrna_tool.Append (CPPPATH = Split(incs))
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index a908b403c03..8a4022de104 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -82,7 +82,7 @@ static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, F
fprintf(f, param); \
} (void)0
-static int replace_if_different(char *tmpfile, const char *dep_files[])
+static int replace_if_different(const char *tmpfile, const char *dep_files[])
{
/* return 0; *//* use for testing had edited rna */
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index b9cbbdb32f7..4b9f7ea32f6 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -471,9 +471,6 @@ static int rna_Armature_is_editmode_get(PointerRNA *ptr)
#else
-static int rna_matrix_dimsize_4x4[] = {4, 4};
-static int rna_matrix_dimsize_3x3[] = {3, 3};
-
static void rna_def_bone_common(StructRNA *srna, int editbone)
{
PropertyRNA *prop;
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index f8483d7b221..0c7c2ea1e49 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -505,7 +505,6 @@ static void rna_def_constrainttarget(BlenderRNA *brna)
static void rna_def_constraint_childof(BlenderRNA *brna)
{
- static int rna_matrix_dimsize_4x4[] = {4, 4};
StructRNA *srna;
PropertyRNA *prop;
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index b7cdc7a75b3..fe9e9573957 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -574,13 +574,13 @@ void RNA_define_free(BlenderRNA *UNUSED(brna))
DefRNA.error = 0;
}
-void RNA_define_verify_sdna(int verify)
+void RNA_define_verify_sdna(bool verify)
{
DefRNA.verify = verify;
}
#ifndef RNA_RUNTIME
-void RNA_define_animate_sdna(int animate)
+void RNA_define_animate_sdna(bool animate)
{
DefRNA.animate = animate;
}
@@ -1253,6 +1253,11 @@ void RNA_def_property_array(PropertyRNA *prop, int length)
}
}
+/* common args for length */
+const int rna_matrix_dimsize_3x3[] = {3, 3};
+const int rna_matrix_dimsize_4x4[] = {4, 4};
+const int rna_matrix_dimsize_4x2[] = {4, 2};
+
void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int length[])
{
StructRNA *srna = DefRNA.laststruct;
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 439bc51896f..6423763c49c 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -354,15 +354,15 @@ static void rna_def_gpencil_strokes_api(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_srna(cprop, "GPencilStrokes");
srna = RNA_def_struct(brna, "GPencilStrokes", NULL);
RNA_def_struct_sdna(srna, "bGPDframe");
- RNA_def_struct_ui_text(srna, "Grease Pencil Frames", "Collection of grease pencil frames");
+ RNA_def_struct_ui_text(srna, "Grease Pencil Frames", "Collection of grease pencil stroke");
func = RNA_def_function(srna, "new", "rna_GPencil_stroke_new");
- RNA_def_function_ui_description(func, "Add a new grease pencil frame");
+ RNA_def_function_ui_description(func, "Add a new grease pencil stroke");
parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "", "The newly created stroke");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_GPencil_stroke_remove");
- RNA_def_function_ui_description(func, "Remove a grease pencil frame");
+ RNA_def_function_ui_description(func, "Remove a grease pencil stroke");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "Stroke", "The stroke to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
@@ -390,7 +390,8 @@ static void rna_def_gpencil_frame(BlenderRNA *brna)
/* Frame Number */
prop = RNA_def_property(srna, "frame_number", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "framenum");
- RNA_def_property_range(prop, MINFRAME, MAXFRAME); /* XXX note: this cannot occur on the same frame as another sketch */
+ /* XXX note: this cannot occur on the same frame as another sketch */
+ RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
RNA_def_property_ui_text(prop, "Frame Number", "The frame on which this sketch appears");
/* Flags */
@@ -421,7 +422,8 @@ static void rna_def_gpencil_frames_api(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "new", "rna_GPencil_frame_new");
RNA_def_function_ui_description(func, "Add a new grease pencil frame");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_int(func, "frame_number", 1, MINFRAME, MAXFRAME, "Frame Number", "The frame on which this sketch appears", MINFRAME, MAXFRAME);
+ parm = RNA_def_int(func, "frame_number", 1, MINAFRAME, MAXFRAME, "Frame Number",
+ "The frame on which this sketch appears", MINAFRAME, MAXFRAME);
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_pointer(func, "frame", "GPencilFrame", "", "The newly created frame");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 3fa101a74e4..a25f56f2259 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -130,7 +130,7 @@ void RNA_api_mesh(StructRNA *srna)
parm = RNA_def_float(func, "split_angle", M_PI, 0.0f, M_PI, "",
"Angle between polys' normals above which an edge is always sharp (180° to disable)",
0.0f, M_PI);
- RNA_def_property_subtype(parm, PROP_UNIT_ROTATION);
+ RNA_def_property_subtype(parm, (PropertySubType)PROP_UNIT_ROTATION);
func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split");
RNA_def_function_ui_description(func, "Free split vertex normals");
diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c
index f01b5af7aaa..6bf7c8926e8 100644
--- a/source/blender/makesrna/intern/rna_meta.c
+++ b/source/blender/makesrna/intern/rna_meta.c
@@ -321,12 +321,14 @@ static void rna_def_metaball(BlenderRNA *brna)
prop = RNA_def_property(srna, "resolution", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "wiresize");
RNA_def_property_range(prop, 0.005f, 10000.0f);
+ RNA_def_property_ui_range(prop, 0.05f, 1000.0f, 2.5f, 3);
RNA_def_property_ui_text(prop, "Wire Size", "Polygonization resolution in the 3D viewport");
RNA_def_property_update(prop, 0, "rna_MetaBall_update_data");
prop = RNA_def_property(srna, "render_resolution", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "rendersize");
RNA_def_property_range(prop, 0.005f, 10000.0f);
+ RNA_def_property_ui_range(prop, 0.025f, 1000.0f, 2.5f, 3);
RNA_def_property_ui_text(prop, "Render Size", "Polygonization resolution in rendering");
RNA_def_property_update(prop, 0, "rna_MetaBall_update_data");
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 69addbae1e5..bb8e8d87252 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -1377,8 +1377,8 @@ static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, Struc
nt->initfunc_api = (have_function[3]) ? rna_Node_init : NULL;
nt->copyfunc_api = (have_function[4]) ? rna_Node_copy : NULL;
nt->freefunc_api = (have_function[5]) ? rna_Node_free : NULL;
- nt->uifunc = (have_function[6]) ? rna_Node_draw_buttons : NULL;
- nt->uifuncbut = (have_function[7]) ? rna_Node_draw_buttons_ext : NULL;
+ nt->draw_buttons = (have_function[6]) ? rna_Node_draw_buttons : NULL;
+ nt->draw_buttons_ex = (have_function[7]) ? rna_Node_draw_buttons_ext : NULL;
/* sanitize size values in case not all have been registered */
if (nt->maxwidth < nt->minwidth)
@@ -1889,6 +1889,12 @@ static void rna_NodeSocket_update(Main *bmain, Scene *UNUSED(scene), PointerRNA
ED_node_tag_update_nodetree(bmain, ntree);
}
+static int rna_NodeSocket_is_output_get(PointerRNA *ptr)
+{
+ bNodeSocket *sock = ptr->data;
+ return sock->in_out == SOCK_OUT;
+}
+
static void rna_NodeSocket_link_limit_set(PointerRNA *ptr, int value)
{
bNodeSocket *sock = ptr->data;
@@ -2336,24 +2342,24 @@ static void rna_NodeInternal_update(ID *id, bNode *node)
static void rna_NodeInternal_draw_buttons(ID *id, bNode *node, struct bContext *C, struct uiLayout *layout)
{
- if (node->typeinfo->uifunc) {
+ if (node->typeinfo->draw_buttons) {
PointerRNA ptr;
RNA_pointer_create(id, &RNA_Node, node, &ptr);
- node->typeinfo->uifunc(layout, C, &ptr);
+ node->typeinfo->draw_buttons(layout, C, &ptr);
}
}
static void rna_NodeInternal_draw_buttons_ext(ID *id, bNode *node, struct bContext *C, struct uiLayout *layout)
{
- if (node->typeinfo->uifuncbut) {
+ if (node->typeinfo->draw_buttons_ex) {
PointerRNA ptr;
RNA_pointer_create(id, &RNA_Node, node, &ptr);
- node->typeinfo->uifuncbut(layout, C, &ptr);
+ node->typeinfo->draw_buttons_ex(layout, C, &ptr);
}
- else if (node->typeinfo->uifunc) {
+ else if (node->typeinfo->draw_buttons) {
PointerRNA ptr;
RNA_pointer_create(id, &RNA_Node, node, &ptr);
- node->typeinfo->uifunc(layout, C, &ptr);
+ node->typeinfo->draw_buttons(layout, C, &ptr);
}
}
@@ -2847,6 +2853,15 @@ static void rna_ShaderNodeSubsurface_update(Main *bmain, Scene *scene, PointerRN
rna_Node_update(bmain, scene, ptr);
}
+static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
+
+ nodeUpdate(ntree, node);
+ rna_Node_update(bmain, scene, ptr);
+}
+
#else
static EnumPropertyItem prop_image_layer_items[] = {
@@ -3136,10 +3151,10 @@ static void def_sh_material(StructRNA *srna)
static void def_sh_mapping(StructRNA *srna)
{
static EnumPropertyItem prop_vect_type_items[] = {
- {TEXMAP_TYPE_TEXTURE, "TEXTURE", 0, "Texture", "Transforms a texture by inverse mapping the texture coordinate"},
- {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transforms a point"},
- {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transforms a direction vector"},
- {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transforms a normal vector with unit length"},
+ {TEXMAP_TYPE_TEXTURE, "TEXTURE", 0, "Texture", "Transform a texture by inverse mapping the texture coordinate"},
+ {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transform a point"},
+ {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transform a direction vector"},
+ {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transform a normal vector with unit length"},
{0, NULL, 0, NULL, NULL}
};
@@ -3147,7 +3162,7 @@ static void def_sh_mapping(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "TexMapping", "storage");
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, prop_vect_type_items);
RNA_def_property_ui_text(prop, "Type", "Type of vector that the mapping transforms");
@@ -3536,9 +3551,9 @@ static void def_sh_tex_coord(StructRNA *srna)
static void def_sh_vect_transform(StructRNA *srna)
{
static EnumPropertyItem prop_vect_type_items[] = {
- {SHD_VECT_TRANSFORM_TYPE_POINT, "POINT", 0, "Point", "Transforms a point"},
- {SHD_VECT_TRANSFORM_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transforms a direction vector"},
- {SHD_VECT_TRANSFORM_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transforms a normal vector with unit length"},
+ {SHD_VECT_TRANSFORM_TYPE_POINT, "POINT", 0, "Point", "Transform a point"},
+ {SHD_VECT_TRANSFORM_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transform a direction vector"},
+ {SHD_VECT_TRANSFORM_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transform a normal vector with unit length"},
{0, NULL, 0, NULL, NULL}
};
@@ -3553,7 +3568,8 @@ static void def_sh_vect_transform(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "NodeShaderVectTransform", "storage");
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, prop_vect_type_items);
RNA_def_property_ui_text(prop, "Type", "");
RNA_def_property_update(prop, 0, "rna_Node_update");
@@ -3689,7 +3705,6 @@ static void def_sh_tangent(StructRNA *srna)
static void def_sh_subsurface(StructRNA *srna)
{
static EnumPropertyItem prop_subsurface_falloff_items[] = {
- {SHD_SUBSURFACE_COMPATIBLE, "COMPATIBLE", 0, "Compatible", "Subsurface scattering falloff compatible with previous versions"},
{SHD_SUBSURFACE_CUBIC, "CUBIC", 0, "Cubic", "Simple cubic falloff function"},
{SHD_SUBSURFACE_GAUSSIAN, "GAUSSIAN", 0, "Gaussian", "Normal distribution, multiple can be combined to fit more complex profiles"},
{0, NULL, 0, NULL, NULL}
@@ -4359,7 +4374,7 @@ static void def_cmp_scale(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, space_items);
RNA_def_property_ui_text(prop, "Space", "Coordinate space to scale relative to");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_CompositorNodeScale_update");
/* expose 2 flags as a enum of 3 items */
prop = RNA_def_property(srna, "frame_method", PROP_ENUM, PROP_NONE);
@@ -6172,12 +6187,10 @@ static void rna_def_node_socket(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Identifier", "Unique identifier for mapping sockets");
- prop = RNA_def_property(srna, "in_out", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "in_out");
- RNA_def_property_enum_items(prop, node_socket_in_out_items);
- RNA_def_property_enum_default(prop, SOCK_IN);
+ prop = RNA_def_property(srna, "is_output", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_NodeSocket_is_output_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Input or Output", "Input or Output type");
+ RNA_def_property_ui_text(prop, "Is Output", "True if the socket is an output, otherwise input");
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_HIDDEN);
@@ -6299,12 +6312,10 @@ static void rna_def_node_socket_interface(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Identifier", "Unique identifier for mapping sockets");
- prop = RNA_def_property(srna, "in_out", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "in_out");
- RNA_def_property_enum_items(prop, node_socket_in_out_items);
- RNA_def_property_enum_default(prop, SOCK_IN);
+ prop = RNA_def_property(srna, "is_output", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_NodeSocket_is_output_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Input or Output", "Input or Output type");
+ RNA_def_property_ui_text(prop, "Is Output", "True if the socket is an output, otherwise input");
/* registration */
prop = RNA_def_property(srna, "bl_socket_idname", PROP_STRING, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 3589610214b..3f366dfbcfa 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -908,6 +908,15 @@ static void rna_MaterialSlot_update(Main *bmain, Scene *scene, PointerRNA *ptr)
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL);
}
+static char *rna_MaterialSlot_path(PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->id.data;
+ int index = (Material **)ptr->data - ob->mat;
+
+ /* from armature... */
+ return BLI_sprintfN("material_slots[%d]", index);
+}
+
/* why does this have to be so complicated?, can't all this crap be
* moved to in BGE conversion function? - Campbell *
*
@@ -1451,8 +1460,6 @@ int rna_Object_use_dynamic_topology_sculpting_get(PointerRNA *ptr)
#else
-static int rna_matrix_dimsize_4x4[] = {4, 4};
-
static void rna_def_vertex_group(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1553,6 +1560,8 @@ static void rna_def_material_slot(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Name", "Material slot name");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_name_property(srna, prop);
+
+ RNA_def_struct_path_func(srna, "rna_MaterialSlot_path");
}
static void rna_def_object_game_settings(BlenderRNA *brna)
@@ -2766,11 +2775,14 @@ static void rna_def_object_base(BlenderRNA *brna)
void RNA_def_object(BlenderRNA *brna)
{
rna_def_object(brna);
+
+ RNA_define_animate_sdna(false);
rna_def_object_game_settings(brna);
rna_def_object_base(brna);
rna_def_vertex_group(brna);
rna_def_material_slot(brna);
rna_def_dupli_object(brna);
+ RNA_define_animate_sdna(true);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 25ca231e58d..0f71e26b687 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -430,8 +430,6 @@ void RNA_api_object(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
- static int rna_matrix_dimsize_4x4[] = {4, 4};
-
#ifndef NDEBUG
static EnumPropertyItem mesh_dm_info_items[] = {
{0, "SOURCE", 0, "Source", "Source mesh"},
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 146ba6e4b7d..33ae256c042 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -1540,8 +1540,6 @@ static void rna_def_softbody(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- const int matrix_dimsize[] = {3, 3};
-
static EnumPropertyItem collision_type_items[] = {
{SBC_MODE_MANUAL, "MANUAL", 0, "Manual", "Manual adjust"},
@@ -1784,12 +1782,12 @@ static void rna_def_softbody(BlenderRNA *brna)
/* matrix */
prop = RNA_def_property(srna, "rotation_estimate", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "lrot");
- RNA_def_property_multi_array(prop, 2, matrix_dimsize);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_3x3);
RNA_def_property_ui_text(prop, "Rot Matrix", "Estimated rotation matrix");
prop = RNA_def_property(srna, "scale_estimate", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "lscale");
- RNA_def_property_multi_array(prop, 2, matrix_dimsize);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_3x3);
RNA_def_property_ui_text(prop, "Scale Matrix", "Estimated scale matrix");
/***********************************************************************************/
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 58217206add..9c4e7f034cb 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -742,9 +742,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
static float default_quat[4] = {1, 0, 0, 0}; /* default quaternion values */
static float default_axisAngle[4] = {0, 0, 1, 0}; /* default axis-angle rotation values */
static float default_scale[3] = {1, 1, 1}; /* default scale values */
-
- const int matrix_dimsize[] = {4, 4};
-
+
StructRNA *srna;
PropertyRNA *prop;
@@ -841,13 +839,13 @@ static void rna_def_pose_channel(BlenderRNA *brna)
/* transform matrices - should be read-only since these are set directly by AnimSys evaluation */
prop = RNA_def_property(srna, "matrix_channel", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "chan_mat");
- RNA_def_property_multi_array(prop, 2, matrix_dimsize);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Channel Matrix", "4x4 matrix, before constraints");
/* writable because it touches loc/scale/rot directly */
prop = RNA_def_property(srna, "matrix_basis", PROP_FLOAT, PROP_MATRIX);
- RNA_def_property_multi_array(prop, 2, matrix_dimsize);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_ui_text(prop, "Basis Matrix",
"Alternative access to location/scale/rotation relative to the parent and own rest bone");
RNA_def_property_float_funcs(prop, "rna_PoseChannel_matrix_basis_get", "rna_PoseChannel_matrix_basis_set", NULL);
@@ -857,7 +855,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
/* final matrix */
prop = RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "pose_mat");
- RNA_def_property_multi_array(prop, 2, matrix_dimsize);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_float_funcs(prop, NULL, "rna_PoseChannel_matrix_set", NULL);
RNA_def_property_ui_text(prop, "Pose Matrix",
"Final 4x4 matrix after constraints and drivers are applied (object space)");
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 5b809a51705..7ebbcf7b39b 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -66,14 +66,14 @@ static void engine_tag_update(RenderEngine *engine)
static int engine_support_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene)
{
- return IMB_colormanagement_support_glsl_draw(&scene->view_settings, true);
+ return IMB_colormanagement_support_glsl_draw(&scene->view_settings);
}
static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene)
{
IMB_colormanagement_setup_glsl_draw(&scene->view_settings,
&scene->display_settings,
- false, true);
+ false);
}
static void engine_unbind_display_space_shader(RenderEngine *UNUSED(engine))
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index fcaabaa3e65..4d35acc84a0 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -219,6 +219,13 @@ EnumPropertyItem snap_uv_element_items[] = {
# define R_IMF_ENUM_TIFF
#endif
+#ifdef WITH_OPENIMAGEIO
+# define R_IMF_ENUM_PSD {R_IMF_IMTYPE_PSD, "PSD", ICON_FILE_IMAGE, "Photosp PSD", \
+ "Output image in Photoshop PSD format"},
+#else
+# define R_IMF_ENUM_PSD
+#endif
+
#define IMAGE_TYPE_ITEMS_IMAGE_ONLY \
R_IMF_ENUM_BMP \
@@ -236,6 +243,7 @@ EnumPropertyItem snap_uv_element_items[] = {
R_IMF_ENUM_EXR \
R_IMF_ENUM_HDR \
R_IMF_ENUM_TIFF \
+ R_IMF_ENUM_PSD \
EnumPropertyItem image_only_type_items[] = {
@@ -932,7 +940,7 @@ static void rna_RenderSettings_qtcodecsettings_codecType_set(PointerRNA *ptr, in
settings->codecType = quicktime_videocodecType_from_rnatmpvalue(value);
}
-static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bContext *C, PointerRNA *ptr,
+static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), int *free)
{
EnumPropertyItem *item = NULL;
@@ -971,7 +979,7 @@ static void rna_RenderSettings_qtcodecsettings_audiocodecType_set(PointerRNA *pt
settings->audiocodecType = quicktime_audiocodecType_from_rnatmpvalue(value);
}
-static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_audiocodecType_itemf(bContext *C, PointerRNA *ptr,
+static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_audiocodecType_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), int *free)
{
EnumPropertyItem *item = NULL;
@@ -1541,7 +1549,8 @@ static void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value
{
FreestyleLineSet *lineset = (FreestyleLineSet *)ptr->data;
- lineset->linestyle->id.us--;
+ if (lineset->linestyle)
+ lineset->linestyle->id.us--;
lineset->linestyle = (FreestyleLineStyle *)value.data;
lineset->linestyle->id.us++;
}
@@ -1580,14 +1589,12 @@ static void rna_def_transform_orientation(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
- const int matrix_dimsize[] = {3, 3};
srna = RNA_def_struct(brna, "TransformOrientation", NULL);
prop = RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "mat");
- RNA_def_property_multi_array(prop, 2, matrix_dimsize);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_3x3);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
@@ -2072,8 +2079,8 @@ static void rna_def_statvis(BlenderRNA *brna)
{SCE_STATVIS_OVERHANG, "OVERHANG", 0, "Overhang", ""},
{SCE_STATVIS_THICKNESS, "THICKNESS", 0, "Thickness", ""},
{SCE_STATVIS_INTERSECT, "INTERSECT", 0, "Intersect", ""},
- {SCE_STATVIS_DISTORT, "DISTORT", 0, "Distort", ""},
- {SCE_STATVIS_SHARP, "SHARP", 0, "Sharp", ""},
+ {SCE_STATVIS_DISTORT, "DISTORT", 0, "Distortion", ""},
+ {SCE_STATVIS_SHARP, "SHARP", 0, "Sharp", ""},
{0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "MeshStatVis", NULL);
@@ -4079,6 +4086,8 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
{RE_BAKE_NORMALS, "NORMALS", 0, "Normals", "Bake normals"},
{RE_BAKE_TEXTURE, "TEXTURE", 0, "Textures", "Bake textures"},
{RE_BAKE_DISPLACEMENT, "DISPLACEMENT", 0, "Displacement", "Bake displacement"},
+ {RE_BAKE_DERIVATIVE, "DERIVATIVE", 0, "Derivative", "Bake derivative map"},
+ {RE_BAKE_VERTEX_COLORS, "VERTEX_COLORS", 0, "Vertex Colors", "Bake vertex colors"},
{RE_BAKE_EMIT, "EMIT", 0, "Emission", "Bake Emit values (glow)"},
{RE_BAKE_ALPHA, "ALPHA", 0, "Alpha", "Bake Alpha values (transparency)"},
{RE_BAKE_MIRROR_INTENSITY, "MIRROR_INTENSITY", 0, "Mirror Intensity", "Bake Mirror values"},
@@ -4665,6 +4674,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
"Bake to vertex colors instead of to a UV-mapped image");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ prop = RNA_def_property(srna, "use_bake_user_scale", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_USERSCALE);
+ RNA_def_property_ui_text(prop, "User scale", "Use a user scale for the derivative map");
+
+ prop = RNA_def_property(srna, "bake_user_scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "bake_user_scale");
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_text(prop, "Scale",
+ "Instead of automatically normalizing to 0..1, "
+ "apply a user scale to the derivative map");
+
/* stamp */
prop = RNA_def_property(srna, "use_stamp_time", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 375b31e0586..ae6c5e71e6e 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -142,12 +142,12 @@ static void rna_Scene_collada_export(
int use_object_instantiation,
int sort_by_name,
int export_transformation_type,
- int second_life)
+ int open_sim)
{
collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected,
include_children, include_armatures, include_shapekeys, deform_bones_only,
active_uv_only, include_uv_textures, include_material_textures,
- use_texture_copies, use_ngons, use_object_instantiation, sort_by_name, export_transformation_type, second_life);
+ use_texture_copies, use_ngons, use_object_instantiation, sort_by_name, export_transformation_type, open_sim);
}
#endif
@@ -218,7 +218,7 @@ void RNA_api_scene(StructRNA *srna)
parm = RNA_def_boolean(func, "use_ngons", 1, "Use NGons", "Keep NGons in Export");
parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data");
parm = RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name");
- parm = RNA_def_boolean(func, "second_life", 0, "Export for Second Life", "Compatibility mode for Second Life");
+ parm = RNA_def_boolean(func, "open_sim", 0, "Export for SL/OpenSim", "Compatibility mode for SL, OpenSim and similar online worlds");
parm = RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
"Transformation", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 0f55da236c9..73f0d33257c 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -406,23 +406,12 @@ static void rna_SpaceView3D_layer_update(Main *bmain, Scene *UNUSED(scene), Poin
DAG_on_visible_update(bmain, FALSE);
}
-static void rna_SpaceView3D_viewport_shade_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
View3D *v3d = (View3D *)(ptr->data);
ScrArea *sa = rna_area_from_space(ptr);
- if (v3d->drawtype != OB_RENDER) {
- ARegion *ar;
-
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d && rv3d->render_engine) {
- RE_engine_free(rv3d->render_engine);
- rv3d->render_engine = NULL;
- }
- }
- }
+ ED_view3d_shade_update(bmain, v3d, sa);
}
static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -1347,6 +1336,12 @@ static void rna_def_space_mask_info(StructRNA *srna, int noteflag, const char *m
{
PropertyRNA *prop;
+ static EnumPropertyItem overlay_mode_items[] = {
+ {MASK_OVERLAY_ALPHACHANNEL, "ALPHACHANNEL", ICON_NONE, "Alpha Channel", "Show alpha channel of the mask"},
+ {MASK_OVERLAY_COMBINED, "COMBINED", ICON_NONE, "Combined", "Combine space background image with the mask"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
prop = RNA_def_property(srna, "mask", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "mask_info.mask");
RNA_def_property_flag(prop, PROP_EDITABLE);
@@ -1365,6 +1360,17 @@ static void rna_def_space_mask_info(StructRNA *srna, int noteflag, const char *m
RNA_def_property_boolean_sdna(prop, NULL, "mask_info.draw_flag", MASK_DRAWFLAG_SMOOTH);
RNA_def_property_ui_text(prop, "Draw Smooth Splines", "");
RNA_def_property_update(prop, noteflag, NULL);
+
+ prop = RNA_def_property(srna, "show_mask_overlay", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mask_info.draw_flag", MASK_DRAWFLAG_OVERLAY);
+ RNA_def_property_ui_text(prop, "Show Mask Overlay", "");
+ RNA_def_property_update(prop, noteflag, NULL);
+
+ prop = RNA_def_property(srna, "mask_overlay_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mask_info.overlay_mode");
+ RNA_def_property_enum_items(prop, overlay_mode_items);
+ RNA_def_property_ui_text(prop, "Overlay Mode", "Overlay mode of rasterized mask");
+ RNA_def_property_update(prop, noteflag, NULL);
}
static void rna_def_space_image_uv(BlenderRNA *brna)
@@ -1695,7 +1701,6 @@ static void rna_def_space_view3d(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- const int matrix_dimsize[] = {4, 4};
static EnumPropertyItem pivot_items[] = {
{V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
@@ -2120,12 +2125,12 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop = RNA_def_property(srna, "perspective_matrix", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "persmat");
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* XXX: for now, it's too risky for users to do this */
- RNA_def_property_multi_array(prop, 2, matrix_dimsize);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_ui_text(prop, "Perspective Matrix", "Current perspective matrix of the 3D region");
prop = RNA_def_property(srna, "view_matrix", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "viewmat");
- RNA_def_property_multi_array(prop, 2, matrix_dimsize);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_float_funcs(prop, NULL, "rna_RegionView3D_view_matrix_set", NULL);
RNA_def_property_ui_text(prop, "View Matrix", "Current view matrix of the 3D region");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index 6aee4486cf5..a26272b34ce 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -496,10 +496,10 @@ static void rna_def_texmapping(BlenderRNA *brna)
};
static EnumPropertyItem prop_vect_type_items[] = {
- {TEXMAP_TYPE_TEXTURE, "TEXTURE", 0, "Texture", "Transforms a texture by inverse mapping the texture coordinate"},
- {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transforms a point"},
- {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transforms a direction vector"},
- {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transforms a normal vector with unit length"},
+ {TEXMAP_TYPE_TEXTURE, "TEXTURE", 0, "Texture", "Transform a texture by inverse mapping the texture coordinate"},
+ {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transform a point"},
+ {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transform a direction vector"},
+ {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transform a normal vector with unit length"},
{0, NULL, 0, NULL, NULL}
};
@@ -517,7 +517,7 @@ static void rna_def_texmapping(BlenderRNA *brna)
srna = RNA_def_struct(brna, "TexMapping", NULL);
RNA_def_struct_ui_text(srna, "Texture Mapping", "Texture coordinate mapping settings");
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, prop_vect_type_items);
RNA_def_property_ui_text(prop, "Type", "Type of vector that the mapping transforms");
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index 2b3cf58d452..97f5c24dc56 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -711,9 +711,6 @@ static EnumPropertyItem pattern_match_items[] = {
{0, NULL, 0, NULL, NULL}
};
-static int rna_matrix_dimsize_4x4[] = {4, 4};
-static int rna_matrix_dimsize_4x2[] = {4, 2};
-
static void rna_def_trackingSettings(BlenderRNA *brna)
{
StructRNA *srna;
diff --git a/source/blender/nodes/composite/nodes/node_composite_scale.c b/source/blender/nodes/composite/nodes/node_composite_scale.c
index 134402c00e1..8041a2e56e9 100644
--- a/source/blender/nodes/composite/nodes/node_composite_scale.c
+++ b/source/blender/nodes/composite/nodes/node_composite_scale.c
@@ -45,12 +45,31 @@ static bNodeSocketTemplate cmp_node_scale_out[] = {
{ -1, 0, "" }
};
+static void node_composite_update_scale(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sock;
+ bool use_xy_scale = ELEM(node->custom1, CMP_SCALE_RELATIVE, CMP_SCALE_ABSOLUTE);
+
+ /* Only show X/Y scale factor inputs for modes using them! */
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "X") || STREQ(sock->name, "Y")) {
+ if (use_xy_scale) {
+ sock->flag &= ~SOCK_UNAVAIL;
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
+ }
+ }
+ }
+}
+
void register_node_type_cmp_scale(void)
{
static bNodeType ntype;
cmp_node_type_base(&ntype, CMP_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, 0);
node_type_socket_templates(&ntype, cmp_node_scale_in, cmp_node_scale_out);
+ node_type_update(&ntype, node_composite_update_scale, NULL);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c
index fad1a69d364..9956fd712c8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_gamma.c
+++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c
@@ -41,6 +41,11 @@ static bNodeSocketTemplate sh_node_gamma_out[] = {
{ -1, 0, "" }
};
+static int node_shader_gpu_gamma(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "node_gamma", in, out);
+}
+
void register_node_type_sh_gamma(void)
{
static bNodeType ntype;
@@ -50,6 +55,7 @@ void register_node_type_sh_gamma(void)
node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_gamma);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c
index 82444caadb8..cff4a039602 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mapping.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c
@@ -71,7 +71,7 @@ static void node_shader_exec_mapping(void *UNUSED(data), int UNUSED(thread), bNo
static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node)
{
- node->storage = add_tex_mapping(TEXMAP_TYPE_TEXTURE);
+ node->storage = add_tex_mapping(TEXMAP_TYPE_POINT);
}
static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
index 480d285af6c..12da301d090 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
@@ -51,7 +51,7 @@ static bNodeSocketTemplate sh_node_tex_brick_out[] = {
static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexBrick *tex = MEM_callocN(sizeof(NodeTexBrick), "NodeTexBrick");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->offset = 0.5f;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
index 82125f3ea02..725b5654523 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
@@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_tex_checker_out[] = {
static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexChecker *tex = MEM_callocN(sizeof(NodeTexChecker), "NodeTexChecker");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
node->storage = tex;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index 923684304bf..5e6471eab77 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_tex_environment_out[] = {
static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->color_space = SHD_COLORSPACE_COLOR;
tex->projection = SHD_PROJ_EQUIRECTANGULAR;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
index 00dd45df7b0..c3ef897b1ad 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_tex_gradient_out[] = {
static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexGradient *tex = MEM_callocN(sizeof(NodeTexGradient), "NodeTexGradient");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->gradient_type = SHD_BLEND_LINEAR;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index 935c0c618c7..1b705e12daf 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_tex_image_out[] = {
static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->color_space = SHD_COLORSPACE_COLOR;
tex->iuser.frames = 1;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
index c043484d550..b9339bc483f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_tex_magic_out[] = {
static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexMagic *tex = MEM_callocN(sizeof(NodeTexMagic), "NodeTexMagic");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->depth = 2;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
index 33ae2dbc8c2..2b5d5e12420 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
@@ -49,7 +49,7 @@ static bNodeSocketTemplate sh_node_tex_musgrave_out[] = {
static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexMusgrave *tex = MEM_callocN(sizeof(NodeTexMusgrave), "NodeTexMusgrave");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->musgrave_type = SHD_MUSGRAVE_FBM;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
index 9e63e0278e6..36e26925501 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
@@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_tex_noise_out[] = {
static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexNoise *tex = MEM_callocN(sizeof(NodeTexNoise), "NodeTexNoise");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
node->storage = tex;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
index 0c842207c05..22061979b12 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_sky_out[] = {
static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexSky *tex = MEM_callocN(sizeof(NodeTexSky), "NodeTexSky");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->sun_direction[0] = 0.0f;
tex->sun_direction[1] = 0.0f;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
index 5ace85506a6..f75c05601aa 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_tex_voronoi_out[] = {
static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexVoronoi *tex = MEM_callocN(sizeof(NodeTexVoronoi), "NodeTexVoronoi");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->coloring = SHD_VORONOI_INTENSITY;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
index a189d927673..be7df85fbee 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
@@ -47,7 +47,7 @@ static bNodeSocketTemplate sh_node_tex_wave_out[] = {
static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexWave *tex = MEM_callocN(sizeof(NodeTexWave), "NodeTexWave");
- default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->wave_type = SHD_WAVE_BANDS;
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index aae0f926e81..ef5d26dccdc 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -174,6 +174,10 @@ if(WITH_IMAGE_OPENEXR)
add_definitions(-DWITH_OPENEXR)
endif()
+if(WITH_OPENIMAGEIO)
+ add_definitions(-DWITH_OPENIMAGEIO)
+endif()
+
if(WITH_IMAGE_OPENJPEG)
add_definitions(-DWITH_OPENJPEG)
endif()
diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c
index 65b7bf62032..efee9b13d58 100644
--- a/source/blender/python/intern/bpy_operator_wrap.c
+++ b/source/blender/python/intern/bpy_operator_wrap.c
@@ -177,14 +177,17 @@ PyObject *PYOP_wrap_macro_define(PyObject *UNUSED(self), PyObject *args)
}
/* identifiers */
- srna = srna_from_self(macro, "Macro Define:");
- macroname = RNA_struct_identifier(srna);
+ srna = pyrna_struct_as_srna((PyObject *)macro, false, "Macro Define:");
+ if (srna == NULL) {
+ return NULL;
+ }
+ macroname = RNA_struct_identifier(srna);
ot = WM_operatortype_find(macroname, true);
if (!ot) {
PyErr_Format(PyExc_ValueError,
- "Macro Define: '%s' is not a valid macro or hasn't been registered yet",
+ "Macro Define: '%s' is not a valid macro",
macroname);
return NULL;
}
diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c
index 6bb3031f0a3..2a874f51fd4 100644
--- a/source/blender/python/mathutils/mathutils_Euler.c
+++ b/source/blender/python/mathutils/mathutils_Euler.c
@@ -707,7 +707,7 @@ PyTypeObject euler_Type = {
* (i.e. it was allocated elsewhere by MEM_mallocN())
* pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
* (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *Euler_CreatePyObject(float *eul, const short order, int type, PyTypeObject *base_type)
+PyObject *Euler_CreatePyObject(float eul[3], const short order, int type, PyTypeObject *base_type)
{
EulerObject *self;
diff --git a/source/blender/python/mathutils/mathutils_Euler.h b/source/blender/python/mathutils/mathutils_Euler.h
index 355d0ed1810..62fb83ef234 100644
--- a/source/blender/python/mathutils/mathutils_Euler.h
+++ b/source/blender/python/mathutils/mathutils_Euler.h
@@ -43,7 +43,7 @@ typedef struct {
* blender (stored in blend_data). This is an either/or struct not both */
/* prototypes */
-PyObject *Euler_CreatePyObject(float *eul, const short order, int type, PyTypeObject *base_type);
+PyObject *Euler_CreatePyObject(float eul[3], const short order, int type, PyTypeObject *base_type);
PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, const short order,
unsigned char cb_type, unsigned char cb_subtype);
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index b0b818faaa0..e13136057c8 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -1246,7 +1246,7 @@ PyTypeObject quaternion_Type = {
* (i.e. it was allocated elsewhere by MEM_mallocN())
* pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
* (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *Quaternion_CreatePyObject(float *quat, int type, PyTypeObject *base_type)
+PyObject *Quaternion_CreatePyObject(float quat[4], int type, PyTypeObject *base_type)
{
QuaternionObject *self;
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.h b/source/blender/python/mathutils/mathutils_Quaternion.h
index be3566934a4..36036c6d3fa 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.h
+++ b/source/blender/python/mathutils/mathutils_Quaternion.h
@@ -40,7 +40,7 @@ typedef struct {
* blender (stored in blend_data). This is an either/or struct not both */
/* prototypes */
-PyObject *Quaternion_CreatePyObject(float *quat, int type, PyTypeObject *base_type);
+PyObject *Quaternion_CreatePyObject(float quat[4], int type, PyTypeObject *base_type);
PyObject *Quaternion_CreatePyObject_cb(PyObject *cb_user,
unsigned char cb_type, unsigned char cb_subtype);
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index 8a5a8446ac6..6b2da9ca593 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -1853,7 +1853,7 @@ static PyObject *Vector_neg(VectorObject *self)
}
/*------------------------vec_magnitude_nosqrt (internal) - for comparing only */
-static double vec_magnitude_nosqrt(float *data, int size)
+static double vec_magnitude_nosqrt(const float *data, int size)
{
/* return (double)sqrt(dot);*/
/* warning, line above removed because we are not using the length,
@@ -2940,10 +2940,10 @@ PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, unsigned char cb
return (PyObject *)self;
}
-PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type)
+PyObject *Vector_CreatePyObject_alloc(const float *vec, const int size, PyTypeObject *base_type)
{
VectorObject *vect_ob;
- vect_ob = (VectorObject *)Vector_CreatePyObject(vec, size, Py_WRAP, base_type);
+ vect_ob = (VectorObject *)Vector_CreatePyObject((float *)vec, size, Py_WRAP, base_type);
vect_ob->wrapped = Py_NEW;
return (PyObject *)vect_ob;
diff --git a/source/blender/python/mathutils/mathutils_Vector.h b/source/blender/python/mathutils/mathutils_Vector.h
index 18d89e73734..2074270670a 100644
--- a/source/blender/python/mathutils/mathutils_Vector.h
+++ b/source/blender/python/mathutils/mathutils_Vector.h
@@ -41,6 +41,6 @@ typedef struct {
PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTypeObject *base_type);
PyObject *Vector_CreatePyObject_cb(PyObject *user, int size,
unsigned char cb_type, unsigned char subtype);
-PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type);
+PyObject *Vector_CreatePyObject_alloc(const float *vec, const int size, PyTypeObject *base_type);
-#endif /* __MATHUTILS_VECTOR_H__ */
+#endif /* __MATHUTILS_VECTOR_H__ */
diff --git a/source/blender/render/extern/include/RE_multires_bake.h b/source/blender/render/extern/include/RE_multires_bake.h
index 04cfe55e3a3..c1c5fc4a04d 100644
--- a/source/blender/render/extern/include/RE_multires_bake.h
+++ b/source/blender/render/extern/include/RE_multires_bake.h
@@ -37,21 +37,26 @@ struct MultiresBakeRender;
typedef struct MultiresBakeRender {
DerivedMesh *lores_dm, *hires_dm;
- int simple, lvl, tot_lvl, bake_filter;
- short mode, use_lores_mesh;
+ bool simple;
+ int bake_filter; /* Bake-filter, aka margin */
+ int lvl, tot_lvl;
+ short mode;
+ bool use_lores_mesh; /* Use low-resolution mesh when baking displacement maps */
- int number_of_rays;
- float bias;
+ int number_of_rays; /* Number of rays to be cast when doing AO baking */
+ float bias; /* Bias between object and start ray point when doing AO baking */
int tot_obj, tot_image;
ListBase image;
int baked_objects, baked_faces;
- int raytrace_structure;
- int octree_resolution;
- int threads;
-
+ int raytrace_structure; /* Optimization structure to be used for AO baking */
+ int octree_resolution; /* Reslution of octotree when using octotree optimization structure */
+ int threads; /* Number of threads to be used for baking */
+
+ float user_scale; /* User scale used to scale displacement when baking derivative map. */
+
short *stop;
short *do_update;
float *progress;
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 73a89ad884f..79826a63690 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -249,7 +249,7 @@ void RE_MergeFullSample(struct Render *re, struct Main *bmain, struct Scene *sce
/* ancient stars function... go away! */
void RE_make_stars(struct Render *re, struct Scene *scenev3d, void (*initfunc)(void),
- void (*vertexfunc)(float *), void (*termfunc)(void));
+ void (*vertexfunc)(const float *), void (*termfunc)(void));
/* display and event callbacks */
void RE_display_init_cb (struct Render *re, void *handle, void (*f)(void *handle, RenderResult *rr));
@@ -281,6 +281,8 @@ int RE_seq_render_active(struct Scene *scene, struct RenderData *rd);
#define RE_BAKE_MIRROR_INTENSITY 10
#define RE_BAKE_ALPHA 11
#define RE_BAKE_EMIT 12
+#define RE_BAKE_DERIVATIVE 13
+#define RE_BAKE_VERTEX_COLORS 14
void RE_Database_Baking(struct Render *re, struct Main *bmain, struct Scene *scene, unsigned int lay, const int type, struct Object *actob);
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 19ddfb7a13d..baec1a74721 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -213,6 +213,9 @@ int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob
struct Image *RE_bake_shade_get_image(void);
void RE_bake_ibuf_filter(struct ImBuf *ibuf, char *mask, const int filter);
void RE_bake_ibuf_normalize_displacement(struct ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max);
+float RE_bake_make_derivative(struct ImBuf *ibuf, float *heights_buffer, const char *mask,
+ const float height_min, const float height_max,
+ const float fmult);
#define BAKE_RESULT_OK 0
#define BAKE_RESULT_NO_OBJECTS 1
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 42dc9bcdfb2..3d97eda50d9 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -236,7 +236,6 @@ struct Render
struct Object *excludeob;
ListBase render_volumes_inside;
ListBase volumes;
- ListBase volume_precache_parts;
#ifdef WITH_FREESTYLE
struct Main freestyle_bmain;
@@ -621,6 +620,7 @@ typedef struct LampRen {
#define R_BAKE_TRACE 32
#define R_BAKING 64
#define R_ANIMATION 128
+#define R_NEED_VCOL 256
/* vlakren->flag (vlak = face in dutch) char!!! */
#define R_SMOOTH 1
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
index 6e70e670ff8..72e47f89bb2 100644
--- a/source/blender/render/intern/source/bake.c
+++ b/source/blender/render/intern/source/bake.c
@@ -168,7 +168,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
else {
if (bs->type == RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */
shi->r = shi->g = shi->b = 1.0f;
-
+
shade_input_set_shade_texco(shi);
/* only do AO for a full bake (and obviously AO bakes)
@@ -260,12 +260,16 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
copy_v3_fl(shr.combined, shi->emit);
shr.alpha = 1.0f;
}
+ else if (bs->type == RE_BAKE_VERTEX_COLORS) {
+ copy_v3_v3(shr.combined, shi->vcol);
+ shr.alpha = shi->vcol[3];
+ }
}
if (bs->rect_float && !bs->vcol) {
float *col = bs->rect_float + 4 * (bs->rectx * y + x);
copy_v3_v3(col, shr.combined);
- if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE) {
+ if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE || bs->type == RE_BAKE_VERTEX_COLORS) {
col[3] = shr.alpha;
}
else {
@@ -294,7 +298,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
rgb_float_to_uchar(col, shr.combined);
}
- if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
+ if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) {
col[3] = FTOCHAR(shr.alpha);
}
else {
@@ -553,7 +557,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
}
}
- if (bs->type == RE_BAKE_DISPLACEMENT) {
+ if (ELEM(bs->type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) {
if (hit)
bake_displacement(handle, shi, (dir == -1) ? mindist : -mindist, x, y);
else
@@ -688,7 +692,7 @@ static int get_next_bake_face(BakeShade *bs)
if (R.r.bake_flag & R_BAKE_CLEAR) {
if (R.r.bake_mode == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT)
IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
- else if (R.r.bake_mode == RE_BAKE_DISPLACEMENT)
+ else if (ELEM(R.r.bake_mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE))
IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
else
IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
@@ -984,8 +988,10 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
use_mask = true;
/* do we need buffer to store displacements */
- if (type == RE_BAKE_DISPLACEMENT) {
- if ((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) {
+ if (ELEM(type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) {
+ if (((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) ||
+ (type == RE_BAKE_DERIVATIVE))
+ {
use_displacement_buffer = true;
use_mask = true;
}
@@ -1089,8 +1095,15 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
userdata = (BakeImBufuserData *)ibuf->userdata;
if (userdata) {
if (use_displacement_buffer) {
- RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
- displacement_min, displacement_max);
+ if (type == RE_BAKE_DERIVATIVE) {
+ float user_scale = (R.r.bake_flag & R_BAKE_USERSCALE) ? R.r.bake_user_scale : -1.0f;
+ RE_bake_make_derivative(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
+ displacement_min, displacement_max, user_scale);
+ }
+ else {
+ RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
+ displacement_min, displacement_max);
+ }
}
RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter);
@@ -1124,3 +1137,176 @@ struct Image *RE_bake_shade_get_image(void)
return R.bakebuf;
}
+/* **************** Derivative Maps Baker **************** */
+
+static void add_single_heights_margin(const ImBuf *ibuf, const char *mask, float *heights_buffer)
+{
+ int x ,y;
+
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ int index = ibuf->x * y + x;
+
+ /* If unassigned pixel, look for neighbors. */
+ if (mask[index] != FILTER_MASK_USED) {
+ float height_acc = 0;
+ int denom = 0;
+ int i, j;
+
+ for (j = -1; j <= 1; j++)
+ for (i = -1; i <= 1; i++) {
+ int w = (i == 0 ? 1 : 0) + (j == 0 ? 1 : 0) + 1;
+
+ if (i != 0 || j != 0) {
+ int index2 = 0;
+ int x0 = x + i;
+ int y0 = y + j;
+
+ CLAMP(x0, 0, ibuf->x - 1);
+ CLAMP(y0, 0, ibuf->y - 1);
+
+ index2 = ibuf->x * y0 + x0;
+
+ if (mask[index2] == FILTER_MASK_USED) {
+ height_acc += w * heights_buffer[index2];
+ denom += w;
+ }
+ }
+ }
+
+ /* Insert final value. */
+ if (denom > 0) {
+ heights_buffer[index] = height_acc / denom;
+ }
+ }
+ }
+ }
+}
+
+/* returns user-scale */
+float RE_bake_make_derivative(ImBuf *ibuf, float *heights_buffer, const char *mask,
+ const float height_min, const float height_max,
+ const float fmult)
+{
+ const float delta_height = height_max - height_min;
+ const float denom = delta_height > 0.0f ? (8 * delta_height) : 1.0f;
+ bool auto_range_fit = fmult <= 0.0f;
+ float max_num_deriv = -1.0f;
+ int x, y, index;
+
+ /* Need a single margin to calculate good derivatives. */
+ add_single_heights_margin(ibuf, mask, heights_buffer);
+
+ if (auto_range_fit) {
+ /* If automatic range fitting is enabled. */
+ for (y = 0; y < ibuf->y; y++) {
+ const int Yu = y == (ibuf->y - 1) ? (ibuf->y - 1) : (y+1);
+ const int Yc = y;
+ const int Yd = y == 0 ? 0 : (y - 1);
+
+ for (x= 0; x < ibuf->x; x++) {
+ const int Xl = x == 0 ? 0 : (x - 1);
+ const int Xc = x;
+ const int Xr = x == (ibuf->x - 1) ? (ibuf->x - 1) : (x + 1);
+
+ const float Hcy = heights_buffer[Yc * ibuf->x + Xr] - heights_buffer[Yc * ibuf->x + Xl];
+ const float Hu = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yu * ibuf->x + Xl];
+ const float Hd = heights_buffer[Yd * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xl];
+
+ const float Hl = heights_buffer[Yu * ibuf->x + Xl] - heights_buffer[Yd * ibuf->x + Xl];
+ const float Hcx = heights_buffer[Yu * ibuf->x + Xc] - heights_buffer[Yd * ibuf->x + Xc];
+ const float Hr = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xr];
+
+ /* This corresponds to using the sobel kernel on the heights buffer
+ * to obtain the derivative multiplied by 8.
+ */
+ const float deriv_x = Hu + 2 * Hcy + Hd;
+ const float deriv_y = Hr + 2 * Hcx + Hl;
+
+ /* early out */
+ index = ibuf->x * y + x;
+ if (mask[index] != FILTER_MASK_USED) {
+ continue;
+ }
+
+ /* Widen bound. */
+ if (fabsf(deriv_x) > max_num_deriv) {
+ max_num_deriv = fabsf(deriv_x);
+ }
+
+ if (fabsf(deriv_y) > max_num_deriv) {
+ max_num_deriv = fabsf(deriv_y);
+ }
+ }
+ }
+ }
+
+ /* Output derivatives. */
+ auto_range_fit &= (max_num_deriv > 0);
+ for (y = 0; y < ibuf->y; y++) {
+ const int Yu= y==(ibuf->y-1) ? (ibuf->y-1) : (y+1);
+ const int Yc= y;
+ const int Yd= y==0 ? 0 : (y-1);
+
+ for(x= 0; x<ibuf->x; x++) {
+ const int Xl = x == 0 ? 0 : (x - 1);
+ const int Xc = x;
+ const int Xr = x == (ibuf->x - 1) ? (ibuf->x - 1) : (x + 1);
+
+ const float Hcy = heights_buffer[Yc * ibuf->x + Xr] - heights_buffer[Yc * ibuf->x + Xl];
+ const float Hu = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yu * ibuf->x + Xl];
+ const float Hd = heights_buffer[Yd * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xl];
+
+ const float Hl = heights_buffer[Yu * ibuf->x + Xl] - heights_buffer[Yd * ibuf->x + Xl];
+ const float Hcx = heights_buffer[Yu * ibuf->x + Xc] - heights_buffer[Yd * ibuf->x + Xc];
+ const float Hr = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xr];
+
+ /* This corresponds to using the sobel kernel on the heights buffer
+ * to obtain the derivative multiplied by 8.
+ */
+ float deriv_x = Hu + 2 * Hcy + Hd;
+ float deriv_y = Hr + 2 * Hcx + Hl;
+
+ /* Early out. */
+ index = ibuf->x * y + x;
+ if (mask[index] != FILTER_MASK_USED){
+ continue;
+ }
+
+ if (auto_range_fit) {
+ deriv_x /= max_num_deriv;
+ deriv_y /= max_num_deriv;
+ } else {
+ deriv_x *= (fmult / denom);
+ deriv_y *= (fmult / denom);
+ }
+
+ deriv_x = deriv_x * 0.5f + 0.5f;
+ deriv_y = deriv_y * 0.5f + 0.5f;
+
+ /* Clamp. */
+ CLAMP(deriv_x, 0.0f, 1.0f);
+ CLAMP(deriv_y, 0.0f, 1.0f);
+
+ /* Write out derivatives. */
+ if (ibuf->rect_float) {
+ float *rrgbf = ibuf->rect_float + index * 4;
+
+ rrgbf[0] = deriv_x;
+ rrgbf[1] = deriv_y;
+ rrgbf[2] = 0.0f;
+ rrgbf[3] = 1.0f;
+ } else {
+ char *rrgb = (char*)ibuf->rect + index * 4;
+
+ rrgb[0] = FTOCHAR(deriv_x);
+ rrgb[1] = FTOCHAR(deriv_y);
+ rrgb[2] = 0;
+ rrgb[3] = 255;
+ }
+ }
+ }
+
+ /* Eeturn user-scale (for rendering). */
+ return auto_range_fit ? (max_num_deriv / denom) : (fmult > 0.0f ? (1.0f / fmult) : 0.0f);
+}
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index a0104a30d0e..18f658fb169 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -167,7 +167,7 @@ static HaloRen *initstar(Render *re, ObjectRen *obr, const float vec[3], float h
*/
void RE_make_stars(Render *re, Scene *scenev3d, void (*initfunc)(void),
- void (*vertexfunc)(float *), void (*termfunc)(void))
+ void (*vertexfunc)(const float *), void (*termfunc)(void))
{
extern unsigned char hash[512];
ObjectRen *obr= NULL;
@@ -5982,7 +5982,9 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned
* RE_BAKE_NORMALS:for baking, no lamps and only selected objects
* RE_BAKE_AO: for baking, no lamps, but all objects
* RE_BAKE_TEXTURE:for baking, no lamps, only selected objects
+ * RE_BAKE_VERTEX_COLORS:for baking, no lamps, only selected objects
* RE_BAKE_DISPLACEMENT:for baking, no lamps, only selected objects
+ * RE_BAKE_DERIVATIVE:for baking, no lamps, only selected objects
* RE_BAKE_SHADOW: for baking, only shadows, but all objects
*/
void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, const int type, Object *actob)
@@ -5990,8 +5992,8 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
Object *camera;
float mat[4][4];
float amb[3];
- const short onlyselected= !ELEM4(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO);
- const short nolamps= ELEM3(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT);
+ const short onlyselected= !ELEM5(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO, RE_BAKE_VERTEX_COLORS);
+ const short nolamps= ELEM5(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS);
re->main= bmain;
re->scene= scene;
@@ -6009,8 +6011,11 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
if (type==RE_BAKE_NORMALS && re->r.bake_normal_space==R_BAKE_SPACE_TANGENT)
re->flag |= R_NEED_TANGENT;
-
- if (!actob && ELEM4(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT)) {
+
+ if (type==RE_BAKE_VERTEX_COLORS)
+ re->flag |= R_NEED_VCOL;
+
+ if (!actob && ELEM6(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS)) {
re->r.mode &= ~R_SHADOW;
re->r.mode &= ~R_RAYTRACE;
}
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index c5e4f97c6bc..bfc13bf6151 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -799,7 +799,7 @@ static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata
/* table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2
* used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible */
#define EWA_MAXIDX 255
-static float EWA_WTS[EWA_MAXIDX + 1] = {
+static const float EWA_WTS[EWA_MAXIDX + 1] = {
1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f,
0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f,
0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f,
diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
index a2fa37fd7ea..3259608c18f 100644
--- a/source/blender/render/intern/source/multires_bake.c
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -124,7 +124,7 @@ typedef struct {
const int *orig_index_mp_to_orig;
} MAOBakeData;
-static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], const int face_num, const int vert_index)
+static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int face_num, const int vert_index)
{
unsigned int indices[] = {data->mface[face_num].v1, data->mface[face_num].v2,
data->mface[face_num].v3, data->mface[face_num].v4};
@@ -1231,6 +1231,7 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
do_multires_bake(bkr, ima, TRUE, apply_tangmat_callback, init_normal_data, free_normal_data, result);
break;
case RE_BAKE_DISPLACEMENT:
+ case RE_BAKE_DERIVATIVE:
do_multires_bake(bkr, ima, FALSE, apply_heights_callback, init_heights_data, free_heights_data, result);
break;
case RE_BAKE_AO:
@@ -1248,7 +1249,7 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
{
LinkData *link;
- int use_displacement_buffer = bkr->mode == RE_BAKE_DISPLACEMENT;
+ bool use_displacement_buffer = ELEM(bkr->mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE);
for (link = bkr->image.first; link; link = link->next) {
Image *ima = (Image *)link->data;
@@ -1259,8 +1260,14 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
continue;
if (use_displacement_buffer) {
- RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
- result->height_min, result->height_max);
+ if (bkr->mode == RE_BAKE_DERIVATIVE) {
+ RE_bake_make_derivative(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
+ result->height_min, result->height_max, bkr->user_scale);
+ }
+ else {
+ RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
+ result->height_min, result->height_max);
+ }
}
RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter);
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 6118d479cab..fa05f8dd18d 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -1309,6 +1309,10 @@ static void do_render_blur_3d(Render *re)
re->mblur_offs = 0.0f;
re->i.curblur = 0; /* stats */
+ /* make sure motion blur changes get reset to current frame */
+ if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0)
+ BKE_scene_update_for_newframe(re->main, re->scene, re->lay);
+
/* weak... the display callback wants an active renderlayer pointer... */
re->result->renlay = render_get_active_layer(re, re->result);
re->display_draw(re->ddh, re->result, NULL);
diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c
index 8a023a2c009..43e052a6efc 100644
--- a/source/blender/render/intern/source/pixelshading.c
+++ b/source/blender/render/intern/source/pixelshading.c
@@ -73,7 +73,7 @@ extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-extern float hashvectf[];
+extern const float hashvectf[];
static void render_lighting_halo(HaloRen *har, float col_r[3])
{
@@ -341,7 +341,8 @@ int shadeHaloFloat(HaloRen *har, float col[4], int zz,
if (flarec) har->pixels+= (int)(har->rad-radist);
if (har->ringc) {
- float *rc, fac;
+ const float *rc;
+ float fac;
int ofs;
/* per ring an antialised circle */
@@ -393,7 +394,8 @@ int shadeHaloFloat(HaloRen *har, float col[4], int zz,
dist= 0.0f;
if (har->linec) {
- float *rc, fac;
+ const float *rc;
+ float fac;
int ofs;
/* per starpoint an antialiased line */
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 982e9b1a410..89d8345a0d7 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -1875,10 +1875,11 @@ static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har) /* pos
static void renderflare(RenderResult *rr, float *rectf, HaloRen *har)
{
- extern float hashvectf[];
+ extern const float hashvectf[];
HaloRen fla;
Material *ma;
- float *rc, rad, alfa, visifac, vec[3];
+ const float *rc;
+ float rad, alfa, visifac, vec[3];
int b, type;
fla= *har;
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 0d85cfe78b7..0c3bf85cd24 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -1373,7 +1373,7 @@ float shadow_halo(LampRen *lar, const float p1[3], const float p2[3])
/* printf("start %x %x \n", (int)(0x7FFFFFFF*zf1), (int)(0x7FFFFFFF*zf2)); */
- while (1) {
+ do {
lambda_o= lambda;
if (lambda_x==lambda_y) {
@@ -1394,7 +1394,13 @@ float shadow_halo(LampRen *lar, const float p1[3], const float p2[3])
}
lambda = min_ff(lambda_x, lambda_y);
-
+
+ /* not making any progress? */
+ if (lambda==lambda_o) break;
+
+ /* clip to end of volume */
+ lambda = min_ff(lambda, 1.0f);
+
zf= zf1 + lambda*(zf2-zf1);
count+= (float)shb->totbuf;
@@ -1409,10 +1415,9 @@ float shadow_halo(LampRen *lar, const float p1[3], const float p2[3])
lightcount+= readshadowbuf_halo(shb, shsample, x, y, z);
}
- /* break after sample, so it takes at least one */
- if (lambda==lambda_o || lambda>=1.0f) break;
}
-
+ while (lambda < 1.0f);
+
if (count!=0.0f) return (lightcount/count);
return 0.0f;
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 2dcb55f1f5d..bc9ba348c62 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -1002,7 +1002,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
}
/* pass option forces UV calc */
- if (shi->passflag & SCE_PASS_UV)
+ if ((shi->passflag & SCE_PASS_UV) || (R.flag & R_NEED_VCOL))
texco |= (NEED_UV | TEXCO_UV);
/* texture coordinates. shi->dxuv shi->dyuv have been set */
@@ -1056,7 +1056,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
}
}
- if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE))) {
+ if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) || (R.flag & R_NEED_VCOL)) {
VlakRen *vlr = shi->vlr;
MTFace *tface;
MCol *mcol;
@@ -1071,7 +1071,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
shi->actuv = obr->actmtface;
shi->actcol = obr->actmcol;
- if (mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) {
+ if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) || (R.flag & R_NEED_VCOL)) {
for (i = 0; (mcol = RE_vlakren_get_mcol(obr, vlr, i, &name, 0)); i++) {
ShadeInputCol *scol = &shi->col[i];
char *cp1, *cp2, *cp3;
@@ -1213,7 +1213,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
}
if ((mode & MA_FACETEXTURE) && i == obr->actmtface) {
- if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) {
+ if (((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) && ((R.flag & R_NEED_VCOL) == 0)) {
shi->vcol[0] = 1.0f;
shi->vcol[1] = 1.0f;
shi->vcol[2] = 1.0f;
@@ -1299,7 +1299,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
* else un-initialized values are used
*/
if (shi->do_manage) {
- if (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) {
+ if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) || (R.flag & R_NEED_VCOL)) {
srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol);
}
}
diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c
index f86942f7918..732892ed357 100644
--- a/source/blender/render/intern/source/sss.c
+++ b/source/blender/render/intern/source/sss.c
@@ -309,7 +309,7 @@ ScatterSettings *scatter_settings_new(float refl, float radius, float ior, float
ss->Fdr= -1.440f/ior*ior + 0.710f/ior + 0.668f + 0.0636f*ior;
ss->A= (1.0f + ss->Fdr)/(1.0f - ss->Fdr);
ss->ld= radius;
- ss->ro= min_ff(refl, 0.999f);
+ ss->ro= min_ff(refl, 0.99f);
ss->color= ss->ro*reflfac + (1.0f-reflfac);
ss->alpha_= compute_reduced_albedo(ss);
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
index 028217b8609..6912f998e7a 100644
--- a/source/blender/render/intern/source/volume_precache.c
+++ b/source/blender/render/intern/source/volume_precache.c
@@ -39,6 +39,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "BLI_voxel.h"
#include "BLI_utildefines.h"
@@ -483,82 +484,96 @@ static void *vol_precache_part_test(void *data)
}
#endif
-typedef struct VolPrecacheQueue {
- ThreadQueue *work;
- ThreadQueue *done;
-} VolPrecacheQueue;
-
/* Iterate over the 3d voxel grid, and fill the voxels with scattering information
*
* It's stored in memory as 3 big float grids next to each other, one for each RGB channel.
* I'm guessing the memory alignment may work out better this way for the purposes
* of doing linear interpolation, but I haven't actually tested this theory! :)
*/
-static void *vol_precache_part(void *data)
+typedef struct VolPrecacheState {
+ double lasttime;
+ int totparts;
+} VolPrecacheState;
+
+static void vol_precache_part(TaskPool *pool, void *taskdata, int threadid)
{
- VolPrecacheQueue *queue = (VolPrecacheQueue *)data;
- VolPrecachePart *pa;
-
- while ((pa = BLI_thread_queue_pop(queue->work))) {
- ObjectInstanceRen *obi = pa->obi;
- RayObject *tree = pa->tree;
- ShadeInput *shi = pa->shi;
- float scatter_col[3] = {0.f, 0.f, 0.f};
- float co[3], cco[3], view[3];
- int x, y, z, i;
- int res[3];
-
- if (pa->re->test_break && pa->re->test_break(pa->re->tbh))
- break;
-
- res[0]= pa->res[0];
- res[1]= pa->res[1];
- res[2]= pa->res[2];
-
- for (z= pa->minz; z < pa->maxz; z++) {
- co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f));
+ VolPrecacheState *state = (VolPrecacheState *)BLI_task_pool_userdata(pool);
+ VolPrecachePart *pa = (VolPrecachePart *)taskdata;
+ Render *re = pa->re;
+
+ ObjectInstanceRen *obi = pa->obi;
+ RayObject *tree = pa->tree;
+ ShadeInput *shi = pa->shi;
+ float scatter_col[3] = {0.f, 0.f, 0.f};
+ float co[3], cco[3], view[3];
+ int x, y, z, i;
+ int res[3];
+ double time;
+
+ if (re->test_break && re->test_break(re->tbh))
+ return;
+
+ printf("thread id %d\n", threadid);
+
+ res[0]= pa->res[0];
+ res[1]= pa->res[1];
+ res[2]= pa->res[2];
+
+ for (z= pa->minz; z < pa->maxz; z++) {
+ co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f));
+
+ for (y= pa->miny; y < pa->maxy; y++) {
+ co[1] = pa->bbmin[1] + (pa->voxel[1] * (y + 0.5f));
- for (y= pa->miny; y < pa->maxy; y++) {
- co[1] = pa->bbmin[1] + (pa->voxel[1] * (y + 0.5f));
+ for (x=pa->minx; x < pa->maxx; x++) {
+ co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f));
- for (x=pa->minx; x < pa->maxx; x++) {
- co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f));
-
- if (pa->re->test_break && pa->re->test_break(pa->re->tbh))
- break;
-
- /* convert from world->camera space for shading */
- mul_v3_m4v3(cco, pa->viewmat, co);
+ if (re->test_break && re->test_break(re->tbh))
+ break;
+
+ /* convert from world->camera space for shading */
+ mul_v3_m4v3(cco, pa->viewmat, co);
- i = BLI_VOXEL_INDEX(x, y, z, res);
+ i = BLI_VOXEL_INDEX(x, y, z, res);
- /* don't bother if the point is not inside the volume mesh */
- if (!point_inside_obi(tree, obi, cco)) {
- obi->volume_precache->data_r[i] = -1.0f;
- obi->volume_precache->data_g[i] = -1.0f;
- obi->volume_precache->data_b[i] = -1.0f;
- continue;
- }
-
- copy_v3_v3(view, cco);
- normalize_v3(view);
- vol_get_scattering(shi, scatter_col, cco, view);
-
- obi->volume_precache->data_r[i] = scatter_col[0];
- obi->volume_precache->data_g[i] = scatter_col[1];
- obi->volume_precache->data_b[i] = scatter_col[2];
-
+ /* don't bother if the point is not inside the volume mesh */
+ if (!point_inside_obi(tree, obi, cco)) {
+ obi->volume_precache->data_r[i] = -1.0f;
+ obi->volume_precache->data_g[i] = -1.0f;
+ obi->volume_precache->data_b[i] = -1.0f;
+ continue;
}
+
+ copy_v3_v3(view, cco);
+ normalize_v3(view);
+ vol_get_scattering(shi, scatter_col, cco, view);
+
+ obi->volume_precache->data_r[i] = scatter_col[0];
+ obi->volume_precache->data_g[i] = scatter_col[1];
+ obi->volume_precache->data_b[i] = scatter_col[2];
+
}
}
+ }
+
+ time = PIL_check_seconds_timer();
+ if (time - state->lasttime > 1.0) {
+ ThreadMutex *mutex = BLI_task_pool_user_mutex(pool);
- BLI_thread_queue_push(queue->done, pa);
+ if (BLI_mutex_trylock(mutex)) {
+ char str[64];
+ float ratio = (float)BLI_task_pool_tasks_done(pool)/(float)state->totparts;
+ BLI_snprintf(str, sizeof(str), IFACE_("Precaching volume: %d%%"), (int)(100.0f * ratio));
+ re->i.infostr = str;
+ re->stats_draw(re->sdh, &re->i);
+ re->i.infostr = NULL;
+ state->lasttime = time;
+
+ BLI_mutex_unlock(mutex);
+ }
}
-
- return NULL;
}
-
static void precache_setup_shadeinput(Render *re, ObjectInstanceRen *obi, Material *ma, ShadeInput *shi)
{
memset(shi, 0, sizeof(ShadeInput));
@@ -573,9 +588,12 @@ static void precache_setup_shadeinput(Render *re, ObjectInstanceRen *obi, Materi
shi->lay = re->lay;
}
-static void precache_init_parts(Render *re, RayObject *tree, ShadeInput *shi, ObjectInstanceRen *obi, int totthread, int *parts)
+static void precache_launch_parts(Render *re, RayObject *tree, ShadeInput *shi, ObjectInstanceRen *obi)
{
+ TaskScheduler *task_scheduler;
+ TaskPool *task_pool;
VolumePrecache *vp = obi->volume_precache;
+ VolPrecacheState state;
int i=0, x, y, z;
float voxel[3];
int sizex, sizey, sizez;
@@ -584,15 +602,23 @@ static void precache_init_parts(Render *re, RayObject *tree, ShadeInput *shi, Ob
int minx, maxx;
int miny, maxy;
int minz, maxz;
+ int totthread = re->r.threads;
+ int parts[3];
if (!vp) return;
- BLI_freelistN(&re->volume_precache_parts);
-
/* currently we just subdivide the box, number of threads per side */
parts[0] = parts[1] = parts[2] = totthread;
res = vp->res;
+ /* setup task scheduler */
+ memset(&state, 0, sizeof(state));
+ state.totparts = parts[0]*parts[1]*parts[2];
+ state.lasttime = PIL_check_seconds_timer();
+
+ task_scheduler = BLI_task_scheduler_create(totthread);
+ task_pool = BLI_task_pool_create(task_scheduler, &state);
+
/* using boundbox in worldspace */
global_bounds_obi(re, obi, bbmin, bbmax);
sub_v3_v3v3(voxel, bbmax, bbmin);
@@ -636,13 +662,19 @@ static void precache_init_parts(Render *re, RayObject *tree, ShadeInput *shi, Ob
pa->miny = miny; pa->maxy = maxy;
pa->minz = minz; pa->maxz = maxz;
-
- BLI_addtail(&re->volume_precache_parts, pa);
+ BLI_task_pool_push(task_pool, vol_precache_part, pa, true, TASK_PRIORITY_HIGH);
i++;
}
}
}
+
+ /* work and wait until tasks are done */
+ BLI_task_pool_work_and_wait(task_pool);
+
+ /* free */
+ BLI_task_pool_free(task_pool);
+ BLI_task_scheduler_free(task_scheduler);
}
/* calculate resolution from bounding box in world space */
@@ -678,17 +710,8 @@ static int precache_resolution(Render *re, VolumePrecache *vp, ObjectInstanceRen
static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Material *ma)
{
VolumePrecache *vp;
- VolPrecachePart *pa;
RayObject *tree;
ShadeInput shi;
- ListBase threads;
- VolPrecacheQueue queue;
- int parts[3] = {1, 1, 1}, totparts;
-
- int counter=0;
- int totthread = re->r.threads, thread;
-
- double time, lasttime= PIL_check_seconds_timer();
R = *re;
@@ -717,49 +740,8 @@ static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *o
/* Need a shadeinput to calculate scattering */
precache_setup_shadeinput(re, obi, ma, &shi);
- precache_init_parts(re, tree, &shi, obi, totthread, parts);
- totparts = parts[0] * parts[1] * parts[2];
-
- /* setup work and done queues */
- queue.work = BLI_thread_queue_init();
- queue.done = BLI_thread_queue_init();
- BLI_thread_queue_nowait(queue.work);
+ precache_launch_parts(re, tree, &shi, obi);
- for (pa= re->volume_precache_parts.first; pa; pa= pa->next)
- BLI_thread_queue_push(queue.work, pa);
-
- /* launch threads */
- BLI_init_threads(&threads, vol_precache_part, totthread);
-
- for (thread= 0; thread<totthread; thread++)
- BLI_insert_thread(&threads, &queue);
-
- /* loop waiting for work to be done */
- while (counter < totparts) {
- if (re->test_break && re->test_break(re->tbh))
- break;
-
- if (BLI_thread_queue_pop_timeout(queue.done, 50))
- counter++;
-
- time= PIL_check_seconds_timer();
- if (time-lasttime>1.0) {
- char str[64];
- BLI_snprintf(str, sizeof(str), IFACE_("Precaching volume: %d%%"),
- (int)(100.0f * ((float)counter / (float)totparts)));
- re->i.infostr = str;
- re->stats_draw(re->sdh, &re->i);
- re->i.infostr = NULL;
- lasttime = time;
- }
- }
-
- /* free */
- BLI_end_threads(&threads);
- BLI_thread_queue_free(queue.work);
- BLI_thread_queue_free(queue.done);
- BLI_freelistN(&re->volume_precache_parts);
-
if (tree) {
/* TODO: makeraytree_object creates a tree and saves it on OBI,
* if we free this tree we should also clear other pointers to it */
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 84b376edcd8..c338d49fe17 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -198,6 +198,7 @@ bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct I
/* poll callback, context checks */
int WM_operator_winactive (struct bContext *C);
/* invoke callback, exec + redo popup */
+int WM_operator_props_popup_confirm(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_operator_props_popup_call(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_operator_props_popup (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_operator_props_dialog_popup(struct bContext *C, struct wmOperator *op, int width, int height);
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index 121e5e401fa..eab27286709 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -98,6 +98,8 @@ const char *WM_key_event_string(short type);
int WM_key_event_operator_id(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, int hotkey, struct wmKeyMap **keymap_r);
char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, const bool strict, char *str, int len);
+const char *WM_bool_as_string(bool test);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 3e2d01d6e80..4c58089f4e7 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -226,13 +226,13 @@ static void wm_drop_operator_options(bContext *C, wmDrag *drag, wmEvent *event)
/* check buttons (XXX todo rna and value) */
if (UI_but_active_drop_name(C) ) {
- strcpy(drag->opname, IFACE_("Paste name"));
+ BLI_strncpy(drag->opname, IFACE_("Paste name"), sizeof(drag->opname));
}
else {
const char *opname = wm_dropbox_active(C, drag, event);
if (opname) {
- BLI_strncpy(drag->opname, opname, FILE_MAX);
+ BLI_strncpy(drag->opname, opname, sizeof(drag->opname));
// WM_cursor_modal_set(win, CURSOR_COPY);
}
// else
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 37bcfa4f591..825c1ca9252 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -2171,7 +2171,7 @@ void wm_event_do_handlers(bContext *C)
while ( (event = win->queue.first) ) {
int action = WM_HANDLER_CONTINUE;
-#ifdef DEBUG
+#ifndef NDEBUG
if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
printf("\n%s: Handling event\n", __func__);
WM_event_print(event);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index cc4d422331d..f7bbb84facc 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -865,9 +865,10 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *
/* first time saving */
/* XXX temp solution to solve bug, real fix coming (ton) */
- if (G.main->name[0] == 0)
+ if ((G.main->name[0] == '\0') && !(fileflags & G_FILE_SAVE_COPY)) {
BLI_strncpy(G.main->name, filepath, sizeof(G.main->name));
-
+ }
+
/* XXX temp solution to solve bug, real fix coming (ton) */
G.main->recovered = 0;
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index adf159bcfee..05ee23e2361 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -40,6 +40,7 @@
#include "BLI_math.h"
#include "BLI_scanfill.h" /* lasso tessellation */
#include "BLI_utildefines.h"
+#include "BLI_lasso.h"
#include "BKE_context.h"
@@ -231,56 +232,73 @@ static void wm_gesture_draw_circle(wmGesture *gt)
}
-static void draw_filled_lasso(wmGesture *gt)
+struct LassoFillData {
+ unsigned int *px;
+ int width;
+};
+
+static void draw_filled_lasso_px_cb(int x, int y, void *user_data)
+{
+ struct LassoFillData *data = user_data;
+ unsigned char *col = (unsigned char *)&(data->px[(y * data->width) + x]);
+ col[0] = col[1] = col[2] = 0xff;
+ col[3] = 0x10;
+}
+
+static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
{
- ScanFillContext sf_ctx;
- ScanFillVert *sf_vert = NULL, *sf_vert_last = NULL, *sf_vert_first = NULL;
- ScanFillFace *sf_tri;
short *lasso = (short *)gt->customdata;
+ const int tot = gt->points;
+ int (*moves)[2] = MEM_mallocN(sizeof(*moves) * (tot + 1), __func__);
int i;
-
- BLI_scanfill_begin(&sf_ctx);
- for (i = 0; i < gt->points; i++, lasso += 2) {
- float co[3];
-
- co[0] = (float)lasso[0];
- co[1] = (float)lasso[1];
- co[2] = 0.0f;
-
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, co);
- if (sf_vert_last)
- /* e = */ /* UNUSED */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
- sf_vert_last = sf_vert;
- if (sf_vert_first == NULL) sf_vert_first = sf_vert;
+ rcti rect;
+ rcti rect_win;
+
+ for (i = 0; i < tot; i++, lasso += 2) {
+ moves[i][0] = lasso[0];
+ moves[i][1] = lasso[1];
}
-
- /* highly unlikely this will fail, but could crash if (gt->points == 0) */
- if (sf_vert_first) {
- const float zvec[3] = {0.0f, 0.0f, 1.0f};
- BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
- BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_HOLES, zvec);
-
+
+ BLI_lasso_boundbox(&rect, (const int (*)[2])moves, tot);
+
+ wm_subwindow_getrect(win, gt->swinid, &rect_win);
+ BLI_rcti_translate(&rect, rect_win.xmin, rect_win.ymin);
+ BLI_rcti_isect(&rect_win, &rect, &rect);
+ BLI_rcti_translate(&rect, -rect_win.xmin, -rect_win.ymin);
+
+ /* highly unlikely this will fail, but could crash if (tot == 0) */
+ if (BLI_rcti_is_empty(&rect) == false) {
+ const int w = BLI_rcti_size_x(&rect);
+ const int h = BLI_rcti_size_y(&rect);
+ unsigned int *pixel_buf = MEM_callocN(sizeof(*pixel_buf) * w * h, __func__);
+ struct LassoFillData lasso_fill_data = {pixel_buf, w};
+
+ fill_poly_v2i_n(
+ rect.xmin, rect.ymin, rect.xmax, rect.ymax,
+ (const int (*)[2])moves, tot,
+ draw_filled_lasso_px_cb, &lasso_fill_data);
+
glEnable(GL_BLEND);
- glColor4f(1.0, 1.0, 1.0, 0.05);
- glBegin(GL_TRIANGLES);
- for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
- glVertex2fv(sf_tri->v1->co);
- glVertex2fv(sf_tri->v2->co);
- glVertex2fv(sf_tri->v3->co);
- }
- glEnd();
+ // glColor4f(1.0, 1.0, 1.0, 0.05);
+
+ glRasterPos2f(rect.xmin, rect.ymin);
+
+ glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixel_buf);
+
glDisable(GL_BLEND);
-
- BLI_scanfill_end(&sf_ctx);
+ MEM_freeN(pixel_buf);
}
+
+ MEM_freeN(moves);
}
-static void wm_gesture_draw_lasso(wmGesture *gt)
+
+static void wm_gesture_draw_lasso(wmWindow *win, wmGesture *gt)
{
short *lasso = (short *)gt->customdata;
int i;
- draw_filled_lasso(gt);
+ draw_filled_lasso(win, gt);
glEnable(GL_LINE_STIPPLE);
glColor3ub(96, 96, 96);
@@ -347,9 +365,9 @@ void wm_gesture_draw(wmWindow *win)
wm_gesture_draw_cross(win, gt);
}
else if (gt->type == WM_GESTURE_LINES)
- wm_gesture_draw_lasso(gt);
+ wm_gesture_draw_lasso(win, gt);
else if (gt->type == WM_GESTURE_LASSO)
- wm_gesture_draw_lasso(gt);
+ wm_gesture_draw_lasso(win, gt);
else if (gt->type == WM_GESTURE_STRAIGHTLINE)
wm_gesture_draw_line(gt);
}
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 43a98a4600b..f6ba3a29344 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -50,6 +50,7 @@
#include "BKE_main.h"
#include "BKE_screen.h"
+#include "BLF_translation.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
@@ -1479,3 +1480,7 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
return km;
}
+const char *WM_bool_as_string(bool test)
+{
+ return test ? IFACE_("ON") : IFACE_("OFF");
+}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 5e1e5890c6b..6091ec4a371 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1433,7 +1433,8 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height)
* For use by #WM_operator_props_popup_call, #WM_operator_props_popup only.
*
* \note operator menu needs undo flag enabled , for redo callback */
-static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_call)
+static int wm_operator_props_popup_ex(bContext *C, wmOperator *op,
+ const bool do_call, const bool do_redo)
{
if ((op->type->flag & OPTYPE_REGISTER) == 0) {
BKE_reportf(op->reports, RPT_ERROR,
@@ -1443,7 +1444,7 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_
/* if we don't have global undo, we can't do undo push for automatic redo,
* so we require manual OK clicking in this popup */
- if (!(U.uiflag & USER_GLOBALUNDO))
+ if (!do_redo || !(U.uiflag & USER_GLOBALUNDO))
return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, UI_UNIT_Y);
uiPupBlockEx(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op);
@@ -1454,18 +1455,26 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_
return OPERATOR_RUNNING_MODAL;
}
+/* Same as WM_operator_props_popup but don't use operator redo.
+ * just wraps WM_operator_props_dialog_popup.
+ */
+int WM_operator_props_popup_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return wm_operator_props_popup_ex(C, op, false, false);
+}
+
/* Same as WM_operator_props_popup but call the operator first,
* This way - the button values correspond to the result of the operator.
* Without this, first access to a button will make the result jump,
* see [#32452] */
int WM_operator_props_popup_call(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- return wm_operator_props_popup_ex(C, op, TRUE);
+ return wm_operator_props_popup_ex(C, op, true, true);
}
int WM_operator_props_popup(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- return wm_operator_props_popup_ex(C, op, FALSE);
+ return wm_operator_props_popup_ex(C, op, false, true);
}
int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int height)
@@ -2531,6 +2540,8 @@ static bool blend_save_check(bContext *UNUSED(C), wmOperator *op)
static void WM_OT_save_as_mainfile(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
ot->name = "Save As Blender File";
ot->idname = "WM_OT_save_as_mainfile";
ot->description = "Save the current file in the desired location";
@@ -2545,8 +2556,9 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file");
RNA_def_boolean(ot->srna, "relative_remap", 1, "Remap Relative",
"Remap relative paths when saving in a different directory");
- RNA_def_boolean(ot->srna, "copy", 0, "Save Copy",
+ prop = RNA_def_boolean(ot->srna, "copy", 0, "Save Copy",
"Save a copy of the actual working state but does not make saved file active");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
#ifdef USE_BMESH_SAVE_AS_COMPAT
RNA_def_boolean(ot->srna, "use_mesh_compat", 0, "Legacy Mesh Format",
"Save using legacy mesh format (no ngons) - WARNING: only saves tris and quads, other ngons will "
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 4ad4286b657..ae535ed45e8 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -148,6 +148,15 @@ void wm_subwindow_getmatrix(wmWindow *win, int swinid, float mat[4][4])
}
}
+void wm_subwindow_getrect(wmWindow *win, int swinid, rcti *r_rect)
+{
+ wmSubWindow *swin = swin_from_swinid(win, swinid);
+
+ if (swin) {
+ *r_rect = swin->winrct;
+ }
+}
+
/* always sets pixel-precise 2D window/view matrices */
/* coords is in whole pixels. xmin = 15, xmax = 16: means window is 2 pix big */
int wm_subwindow_open(wmWindow *win, rcti *winrct)
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 78a2ed9b05d..9e89c17e024 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -131,7 +131,7 @@ static void wm_window_check_position(rcti *rect)
{
int width, height, d;
- wm_get_desktopsize(&width, &height);
+ wm_get_screensize(&width, &height);
#if defined(__APPLE__) && !defined(GHOST_COCOA)
height -= 70;
@@ -359,7 +359,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
if (multisamples == -1)
multisamples = U.ogl_multisamples;
- wm_get_desktopsize(&scr_w, &scr_h);
+ wm_get_screensize(&scr_w, &scr_h);
posy = (scr_h - win->posy - win->sizey);
ghostwin = GHOST_CreateWindow(g_system, title,
@@ -378,12 +378,12 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
win->ghostwin = ghostwin;
GHOST_SetWindowUserData(ghostwin, win); /* pointer back */
- /* set the state*/
- GHOST_SetWindowState(ghostwin, (GHOST_TWindowState)win->windowstate);
-
if (win->eventstate == NULL)
win->eventstate = MEM_callocN(sizeof(wmEvent), "window event state");
+ /* set the state */
+ GHOST_SetWindowState(ghostwin, (GHOST_TWindowState)win->windowstate);
+
/* until screens get drawn, make it nice gray */
glClearColor(0.55, 0.55, 0.55, 0.0);
/* Crash on OSS ATI: bugs.launchpad.net/ubuntu/+source/mesa/+bug/656100 */
diff --git a/source/blender/windowmanager/wm_subwindow.h b/source/blender/windowmanager/wm_subwindow.h
index 064d00b0723..a70e7765ecf 100644
--- a/source/blender/windowmanager/wm_subwindow.h
+++ b/source/blender/windowmanager/wm_subwindow.h
@@ -45,6 +45,7 @@ void wm_subwindow_position(wmWindow *win, int swinid, rcti *winrct);
void wm_subwindow_getsize(wmWindow *win, int swinid, int *x, int *y);
void wm_subwindow_getorigin(wmWindow *win, int swinid, int *x, int *y);
void wm_subwindow_getmatrix(wmWindow *win, int swinid, float mat[4][4]);
+void wm_subwindow_getrect(wmWindow *win, int swinid, struct rcti *r_rect);
unsigned int index_to_framebuffer(int index);
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 1123e6e6ea6..529e2017989 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -130,6 +130,7 @@ endif()
bf_intern_utfconv
bf_imbuf_cineon
bf_imbuf_openexr
+ bf_imbuf_openimageio
extern_openjpeg
extern_redcode
bf_imbuf_dds
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 9e267d45424..f55f307e095 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -335,6 +335,7 @@ void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic)
void ED_view3D_background_image_clear(struct View3D *v3d) {STUB_ASSERT(0);}
void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]) {STUB_ASSERT(0);}
float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) {STUB_ASSERT(0); return 0.0f;}
+void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa) {STUB_ASSERT(0);}
void view3d_apply_mat4(float mat[4][4], float *ofs, float *quat, float *dist) {STUB_ASSERT(0);}
int text_file_modified(struct Text *text) {STUB_ASSERT(0); return 0;}
void ED_node_shader_default(struct bContext *C, struct ID *id) {STUB_ASSERT(0);}
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 397da79a493..921443d9ab9 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -912,6 +912,7 @@ endif()
bf_avi
bf_imbuf_cineon
bf_imbuf_openexr
+ bf_imbuf_openimageio
bf_imbuf_dds
bf_collada
bf_intern_bsp
diff --git a/source/creator/creator.c b/source/creator/creator.c
index b442194bd7d..1596fe5359c 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -76,13 +76,13 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BLI_callbacks.h"
+#include "BLI_blenlib.h"
+#include "BLI_mempool.h"
#include "DNA_ID.h"
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
-#include "BLI_blenlib.h"
-
#include "BKE_blender.h"
#include "BKE_brush.h"
#include "BKE_context.h"
@@ -300,6 +300,7 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
#ifdef WITH_LIBMV
BLI_argsPrintArgDoc(ba, "--debug-libmv");
#endif
+ BLI_argsPrintArgDoc(ba, "--debug-memory");
BLI_argsPrintArgDoc(ba, "--debug-jobs");
BLI_argsPrintArgDoc(ba, "--debug-python");
@@ -412,10 +413,13 @@ static int debug_mode(int UNUSED(argc), const char **UNUSED(argv), void *data)
G.debug |= G_DEBUG; /* std output printf's */
printf(BLEND_VERSION_STRING_FMT);
MEM_set_memory_debug();
+#ifdef DEBUG
+ BLI_mempool_set_memory_debug();
+#endif
#ifdef WITH_BUILDINFO
printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
-#endif // WITH_BUILDINFO
+#endif
BLI_argsPrint(data);
return 0;
@@ -436,6 +440,12 @@ static int debug_mode_libmv(int UNUSED(argc), const char **UNUSED(argv), void *U
}
#endif
+static int debug_mode_memory(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+{
+ MEM_set_memory_debug();
+ return 0;
+}
+
static int set_debug_value(int argc, const char **argv, void *UNUSED(data))
{
if (argc > 1) {
@@ -1381,6 +1391,7 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
#ifdef WITH_LIBMV
BLI_argsAdd(ba, 1, NULL, "--debug-libmv", "\n\tEnable debug messages from libmv library", debug_mode_libmv, NULL);
#endif
+ BLI_argsAdd(ba, 1, NULL, "--debug-memory", "\n\tEnable fully guarded memory allocation and debugging", debug_mode_memory, NULL);
BLI_argsAdd(ba, 1, NULL, "--debug-value", "<value>\n\tSet debug value of <value> on startup\n", set_debug_value, NULL);
BLI_argsAdd(ba, 1, NULL, "--debug-jobs", "\n\tEnable time profiling for background jobs.", debug_mode_generic, (void *)G_DEBUG_JOBS);
@@ -1451,23 +1462,50 @@ int main(int argc, const char **UNUSED(argv_c)) /* Do not mess with const */
int main(int argc, const char **argv)
#endif
{
- bContext *C = CTX_create();
+ bContext *C;
SYS_SystemHandle syshandle;
#ifndef WITH_PYTHON_MODULE
bArgs *ba;
#endif
-#ifdef WIN32
+#ifdef WIN32 /* Win32 Unicode Args */
+ /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialised
+ * (it depends on the args passed in, which is what we're getting here!)
+ */
wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
+ char **argv = malloc(argc * sizeof(char *));
int argci = 0;
- char **argv = MEM_mallocN(argc * sizeof(char *), "argv array");
+
for (argci = 0; argci < argc; argci++) {
argv[argci] = alloc_utf_8_from_16(argv_16[argci], 0);
}
+
LocalFree(argv_16);
#endif
+ /* NOTE: Special exception for guarded allocator type switch:
+ * we need to perform switch from lock-free to fully
+ * guarded allocator before any allocation happened.
+ */
+ {
+ int i;
+ for (i = 0; i < argc; i++) {
+ if (STREQ(argv[i], "--debug") || STREQ(argv[i], "-d") ||
+ STREQ(argv[i], "--debug-memory"))
+ {
+ printf("Switching to fully guarded memory allocator.\n");
+ MEM_use_guarded_allocator();
+ break;
+ }
+ else if (STREQ(argv[i], "--")) {
+ break;
+ }
+ }
+ }
+
+ C = CTX_create();
+
#ifdef WITH_PYTHON_MODULE
#ifdef __APPLE__
environ = *_NSGetEnviron();
@@ -1638,7 +1676,7 @@ int main(int argc, const char **argv)
while (argci) {
free(argv[--argci]);
}
- MEM_freeN(argv);
+ free(argv);
argv = NULL;
#endif
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
index a6b71e0bc43..bcc62a341f8 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
@@ -211,7 +211,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
MT_Vector3 dir = (campos - objpos).safe_normalized();
MT_Vector3 up(0,0,1.0);
- KX_GameObject* gameobj = (KX_GameObject*)m_clientobject;
+ KX_GameObject* gameobj = (KX_GameObject *)this->m_clientobject;
// get scaling of halo object
MT_Vector3 size = gameobj->GetSGNode()->GetWorldScaling();
@@ -225,7 +225,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
}
MT_Vector3 left = dir.normalized();
- dir = (up.cross(left)).normalized();
+ dir = (left.cross(up)).normalized();
// we have calculated the row vectors, now we keep
// local scaling into account:
@@ -241,14 +241,13 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
glTranslated(objpos[0],objpos[1],objpos[2]);
glMultMatrixd(maat);
-
}
else {
if (objectdrawmode & RAS_IPolyMaterial::SHADOW)
{
// shadow must be cast to the ground, physics system needed here!
MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
- KX_GameObject *gameobj = (KX_GameObject*)m_clientobject;
+ KX_GameObject *gameobj = (KX_GameObject *)this->m_clientobject;
MT_Vector3 direction = MT_Vector3(0,0,-1);
direction.normalize();
@@ -328,7 +327,7 @@ void KX_BlenderRenderTools::RenderText(
RAS_IPolyMaterial* polymat,
float v1[3], float v2[3], float v3[3], float v4[3], int glattrib)
{
- const STR_String& mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
+ const STR_String &mytext = ((CValue *)m_clientobject)->GetPropertyText("Text");
const unsigned int flag = polymat->GetFlag();
struct MTFace* tface = 0;
@@ -408,3 +407,4 @@ void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer)
}
}
}
+
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index dd9609968b0..b0555abbea4 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -2665,7 +2665,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
case PARBONE:
{
// parent this to a bone
- Bone *parent_bone = BKE_armature_find_bone_name( (bArmature *)(blenderchild->parent)->data, blenderchild->parsubstr);
+ Bone *parent_bone = BKE_armature_find_bone_name(BKE_armature_from_object(blenderchild->parent),
+ blenderchild->parsubstr);
if (parent_bone) {
KX_BoneParentRelation *bone_parent_relation = KX_BoneParentRelation::New(parent_bone);
diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
index e8c29d5aa4f..0d851c4f10d 100644
--- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
@@ -66,9 +66,7 @@ unsigned int GPC_RenderTools::m_numgllights;
GPC_RenderTools::GPC_RenderTools()
{
-// XXX m_font = BMF_GetFont(BMF_kHelvetica10);
-
- glGetIntegerv(GL_MAX_LIGHTS, (GLint*) &m_numgllights);
+ glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &m_numgllights);
if (m_numgllights < 8)
m_numgllights = 8;
}
@@ -220,7 +218,7 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in
MT_Vector3 dir = (campos - objpos).safe_normalized();
MT_Vector3 up(0,0,1.0);
- KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject;
+ KX_GameObject* gameobj = (KX_GameObject *)this->m_clientobject;
// get scaling of halo object
MT_Vector3 size = gameobj->GetSGNode()->GetWorldScaling();
@@ -256,7 +254,7 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in
{
// shadow must be cast to the ground, physics system needed here!
MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
- KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject;
+ KX_GameObject *gameobj = (KX_GameObject *)this->m_clientobject;
MT_Vector3 direction = MT_Vector3(0,0,-1);
direction.normalize();
@@ -280,6 +278,12 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in
// couldn't find something to cast the shadow on...
glMultMatrixd(oglmatrix);
}
+ else
+ { // we found the "ground", but the cast matrix doesn't take
+ // scaling in consideration, so we must apply the object scale
+ MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale();
+ glScalef(size[0], size[1], size[2]);
+ }
} else
{
@@ -490,7 +494,7 @@ void GPC_RenderTools::RenderText(
RAS_IPolyMaterial* polymat,
float v1[3], float v2[3], float v3[3], float v4[3], int glattrib)
{
- STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
+ const STR_String &mytext = ((CValue *)m_clientobject)->GetPropertyText("Text");
const unsigned int flag = polymat->GetFlag();
struct MTFace* tface = 0;
@@ -562,8 +566,7 @@ void GPC_RenderTools::MotionBlur(RAS_IRasterizer* rasterizer)
glAccum(GL_LOAD, 1.0);
rasterizer->SetMotionBlurState(2);
}
- else if (motionblurvalue>=0.0 && motionblurvalue<=1.0)
- {
+ else if (motionblurvalue >= 0.0f && motionblurvalue <= 1.0f) {
glAccum(GL_MULT, motionblurvalue);
glAccum(GL_ACCUM, 1-motionblurvalue);
glAccum(GL_RETURN, 1.0);
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index 0b1fbf977dd..5bed4fa40b6 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -58,11 +58,15 @@ extern "C"
#endif // __cplusplus
#include "MEM_guardedalloc.h"
#include "BLI_threads.h"
+#include "BLI_mempool.h"
#include "BLI_blenlib.h"
+
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
+
#include "BLO_readfile.h"
#include "BLO_runtime.h"
+
#include "BKE_blender.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
@@ -74,6 +78,7 @@ extern "C"
#include "BKE_modifier.h"
#include "BKE_text.h"
#include "BKE_sound.h"
+
#include "IMB_imbuf.h"
int GHOST_HACK_getFirstFile(char buf[]);
@@ -580,8 +585,11 @@ int main(int argc, char** argv)
case 'd':
i++;
- G.debug |= G_DEBUG; /* std output printf's */
+ G.debug |= G_DEBUG;
MEM_set_memory_debug();
+#ifdef DEBUG
+ BLI_mempool_set_memory_debug();
+#endif
break;
case 'f':
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index b3a38cb4f98..e5b8159753b 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -968,7 +968,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)")
return NULL;
}
-static unsigned int GL_array[11] = {
+static const unsigned int GL_array[11] = {
GL_ZERO,
GL_ONE,
GL_SRC_COLOR,