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:
authorMai Lavelle <mai.lavelle@gmail.com>2017-11-29 00:58:57 +0300
committerMai Lavelle <mai.lavelle@gmail.com>2017-11-29 00:58:57 +0300
commit137fd5ffcba7f049e50200114da8e231cc136189 (patch)
treeadeca4ed58480845bf8ef93783ca81eccef32522
parent1261f8eaa7d60554d8678ca2256f123951ed509d (diff)
parent0c7fbc435f4611d6f25a58b17f7f65318bef572d (diff)
Merge branch 'master' into split-kernel-faster-building
-rw-r--r--build_files/build_environment/patches/cmake/modules/FindBlosc.cmake1
-rw-r--r--build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake1
-rw-r--r--build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake1
-rw-r--r--build_files/build_environment/patches/cmake/modules/FindTBB.cmake1
-rw-r--r--build_files/cmake/Modules/FindAlembic.cmake1
-rw-r--r--build_files/cmake/Modules/FindAudaspace.cmake1
-rw-r--r--build_files/cmake/Modules/FindEigen3.cmake1
-rw-r--r--build_files/cmake/Modules/FindFftw3.cmake1
-rw-r--r--build_files/cmake/Modules/FindGflags.cmake2
-rw-r--r--build_files/cmake/Modules/FindGlog.cmake2
-rw-r--r--build_files/cmake/Modules/FindHDF5.cmake1
-rw-r--r--build_files/cmake/Modules/FindIcuLinux.cmake1
-rw-r--r--build_files/cmake/Modules/FindJack.cmake1
-rw-r--r--build_files/cmake/Modules/FindJeMalloc.cmake1
-rw-r--r--build_files/cmake/Modules/FindLZO.cmake1
-rw-r--r--build_files/cmake/Modules/FindOpenCOLLADA.cmake1
-rw-r--r--build_files/cmake/Modules/FindOpenColorIO.cmake1
-rw-r--r--build_files/cmake/Modules/FindOpenEXR.cmake1
-rw-r--r--build_files/cmake/Modules/FindOpenImageIO.cmake3
-rw-r--r--build_files/cmake/Modules/FindOpenJPEG.cmake1
-rw-r--r--build_files/cmake/Modules/FindOpenShadingLanguage.cmake1
-rw-r--r--build_files/cmake/Modules/FindOpenSubdiv.cmake1
-rw-r--r--build_files/cmake/Modules/FindOpenVDB.cmake1
-rw-r--r--build_files/cmake/Modules/FindPCRE.cmake1
-rw-r--r--build_files/cmake/Modules/FindPugiXML.cmake1
-rw-r--r--build_files/cmake/Modules/FindSDL2.cmake1
-rw-r--r--build_files/cmake/Modules/FindSndFile.cmake1
-rw-r--r--build_files/cmake/Modules/FindSpacenav.cmake1
-rw-r--r--build_files/cmake/Modules/FindTBB.cmake1
-rw-r--r--build_files/cmake/Modules/FindXML2.cmake1
-rw-r--r--intern/atomic/atomic_ops.h23
-rw-r--r--intern/atomic/intern/atomic_ops_ext.h45
-rw-r--r--intern/atomic/intern/atomic_ops_msvc.h81
-rw-r--r--intern/atomic/intern/atomic_ops_unix.h161
-rw-r--r--intern/atomic/intern/atomic_ops_utils.h27
-rw-r--r--intern/cycles/CMakeLists.txt4
-rw-r--r--intern/cycles/app/cycles_xml.cpp2
-rw-r--r--intern/cycles/blender/addon/engine.py11
-rw-r--r--intern/cycles/blender/addon/properties.py18
-rw-r--r--intern/cycles/blender/addon/ui.py7
-rw-r--r--intern/cycles/blender/blender_object.cpp10
-rw-r--r--intern/cycles/blender/blender_sync.cpp15
-rw-r--r--intern/cycles/blender/blender_sync.h1
-rw-r--r--intern/cycles/device/device_cpu.cpp2
-rw-r--r--intern/cycles/device/device_cuda.cpp8
-rw-r--r--intern/cycles/device/opencl/opencl_mega.cpp2
-rw-r--r--intern/cycles/device/opencl/opencl_split.cpp2
-rw-r--r--intern/cycles/kernel/closure/bsdf.h34
-rw-r--r--intern/cycles/kernel/closure/bssrdf.h2
-rw-r--r--intern/cycles/kernel/geom/geom_object.h11
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h1
-rw-r--r--intern/cycles/kernel/kernel_passes.h75
-rw-r--r--intern/cycles/kernel/kernel_path.h12
-rw-r--r--intern/cycles/kernel/kernel_shader.h6
-rw-r--r--intern/cycles/kernel/kernel_types.h88
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel_config.h8
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp4
-rw-r--r--intern/cycles/kernel/split/kernel_branched.h21
-rw-r--r--intern/cycles/kernel/split/kernel_next_iteration_setup.h4
-rw-r--r--intern/cycles/kernel/split/kernel_split_data.h5
-rw-r--r--intern/cycles/kernel/split/kernel_split_data_types.h6
-rw-r--r--intern/cycles/kernel/split/kernel_subsurface_scatter.h2
-rw-r--r--intern/cycles/kernel/svm/svm_bevel.h2
-rw-r--r--intern/cycles/kernel/svm/svm_brick.h4
-rw-r--r--intern/cycles/kernel/svm/svm_geometry.h10
-rw-r--r--intern/cycles/kernel/svm/svm_gradient.h5
-rw-r--r--intern/cycles/kernel/svm/svm_types.h9
-rw-r--r--intern/cycles/render/buffers.cpp13
-rw-r--r--intern/cycles/render/buffers.h1
-rw-r--r--intern/cycles/render/film.cpp166
-rw-r--r--intern/cycles/render/image.cpp6
-rw-r--r--intern/cycles/render/light.cpp4
-rw-r--r--intern/cycles/render/light.h1
-rw-r--r--intern/cycles/util/util_math.h5
-rw-r--r--intern/cycles/util/util_xml.h15
-rw-r--r--intern/eigen/intern/eigenvalues.cc2
-rw-r--r--intern/eigen/intern/svd.cc2
-rw-r--r--intern/mikktspace/mikktspace.c363
-rw-r--r--intern/smoke/intern/IMAGE.h10
-rw-r--r--intern/smoke/intern/WTURBULENCE.cpp8
-rw-r--r--intern/smoke/intern/WTURBULENCE.h2
m---------release/datafiles/locale0
m---------release/scripts/addons0
m---------release/scripts/addons_contrib0
-rw-r--r--release/scripts/modules/bpy_extras/anim_utils.py28
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py32
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py2
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py19
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py12
-rw-r--r--source/blender/alembic/intern/abc_mball.h2
-rw-r--r--source/blender/blenkernel/BKE_blender.h13
-rw-r--r--source/blender/blenkernel/BKE_blendfile.h4
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h18
-rw-r--r--source/blender/blenkernel/BKE_subsurf.h2
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h45
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/appdir.c46
-rw-r--r--source/blender/blenkernel/intern/blender.c84
-rw-r--r--source/blender/blenkernel/intern/blendfile.c45
-rw-r--r--source/blender/blenkernel/intern/bmfont.c5
-rw-r--r--source/blender/blenkernel/intern/collision.c16
-rw-r--r--source/blender/blenkernel/intern/fcurve.c2
-rw-r--r--source/blender/blenkernel/intern/freestyle.c8
-rw-r--r--source/blender/blenkernel/intern/library.c4
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c79
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c8
-rw-r--r--source/blender/blenkernel/intern/object.c4
-rw-r--r--source/blender/blenkernel/intern/outliner_treehash.c4
-rw-r--r--source/blender/blenkernel/intern/pbvh.c4
-rw-r--r--source/blender/blenkernel/intern/sequencer.c18
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c9
-rw-r--r--source/blender/blenkernel/intern/tracking_auto.c154
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c62
-rw-r--r--source/blender/blenlib/BLI_ghash.h4
-rw-r--r--source/blender/blenlib/BLI_listbase.h3
-rw-r--r--source/blender/blenlib/BLI_math_color.h4
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h1
-rw-r--r--source/blender/blenlib/BLI_math_vector.h3
-rw-r--r--source/blender/blenlib/BLI_mempool.h5
-rw-r--r--source/blender/blenlib/BLI_rand.h12
-rw-r--r--source/blender/blenlib/BLI_task.h11
-rw-r--r--source/blender/blenlib/BLI_threads.h4
-rw-r--r--source/blender/blenlib/BLI_utildefines.h36
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c221
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c74
-rw-r--r--source/blender/blenlib/intern/listbase.c68
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c8
-rw-r--r--source/blender/blenlib/intern/math_matrix.c10
-rw-r--r--source/blender/blenlib/intern/math_vector.c14
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c14
-rw-r--r--source/blender/blenlib/intern/rand.c101
-rw-r--r--source/blender/blenlib/intern/storage.c4
-rw-r--r--source/blender/blenlib/intern/system.c4
-rw-r--r--source/blender/blenlib/intern/task.c92
-rw-r--r--source/blender/blenlib/intern/threads.c25
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/blentranslation/msgfmt/msgfmt.c3
-rw-r--r--source/blender/bmesh/CMakeLists.txt3
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c115
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators_inline.h34
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c108
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c459
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c307
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c12
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h2
-rw-r--r--source/blender/bmesh/operators/bmo_rotate_edges.c272
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c54
-rw-r--r--source/blender/compositor/operations/COM_KeyingOperation.cpp17
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h10
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc280
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h25
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc96
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc472
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h56
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc98
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc4
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc10
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc20
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc1
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.cc126
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.h75
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c4
-rw-r--r--source/blender/editors/animation/anim_markers.c9
-rw-r--r--source/blender/editors/animation/keyframes_general.c16
-rw-r--r--source/blender/editors/armature/armature_add.c11
-rw-r--r--source/blender/editors/armature/armature_edit.c8
-rw-r--r--source/blender/editors/armature/armature_select.c31
-rw-r--r--source/blender/editors/armature/pose_edit.c21
-rw-r--r--source/blender/editors/armature/pose_transform.c13
-rw-r--r--source/blender/editors/curve/editcurve.c11
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c52
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c7
-rw-r--r--source/blender/editors/include/ED_mesh.h5
-rw-r--r--source/blender/editors/include/ED_uvedit.h3
-rw-r--r--source/blender/editors/include/ED_view3d.h20
-rw-r--r--source/blender/editors/mask/mask_draw.c77
-rw-r--r--source/blender/editors/mask/mask_ops.c7
-rw-r--r--source/blender/editors/mesh/editface.c9
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c4
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c3
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c13
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c24
-rw-r--r--source/blender/editors/metaball/mball_edit.c19
-rw-r--r--source/blender/editors/object/object_edit.c7
-rw-r--r--source/blender/editors/object/object_lattice.c3
-rw-r--r--source/blender/editors/object/object_ops.c7
-rw-r--r--source/blender/editors/physics/particle_edit.c13
-rw-r--r--source/blender/editors/render/render_opengl.c22
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c7
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c8
-rw-r--r--source/blender/editors/space_graph/graph_ops.c12
-rw-r--r--source/blender/editors/space_image/image_buttons.c2
-rw-r--r--source/blender/editors/space_image/image_ops.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h8
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c186
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c13
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c9
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c38
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c8
-rw-r--r--source/blender/editors/transform/transform_generics.c3
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c18
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c161
-rw-r--r--source/blender/freestyle/intern/system/StringUtils.h1
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl5
-rw-r--r--source/blender/imbuf/intern/indexer.c6
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp18
-rw-r--r--source/blender/makesdna/DNA_ID.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h9
-rw-r--r--source/blender/makesdna/DNA_space_types.h3
-rw-r--r--source/blender/makesdna/intern/makesdna.c6
-rw-r--r--source/blender/makesrna/RNA_enum_types.h1
-rw-r--r--source/blender/makesrna/intern/makesrna.c16
-rw-r--r--source/blender/makesrna/intern/rna_animviz.c7
-rw-r--r--source/blender/makesrna/intern/rna_cachefile.c4
-rw-r--r--source/blender/makesrna/intern/rna_camera.c15
-rw-r--r--source/blender/makesrna/intern/rna_image.c2
-rw-r--r--source/blender/makesrna/intern/rna_mask.c4
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c83
-rw-r--r--source/blender/makesrna/intern/rna_particle.c9
-rw-r--r--source/blender/makesrna/intern/rna_scene.c33
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c3
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c5
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c2
-rw-r--r--source/blender/physics/intern/eigen_utils.h2
-rw-r--r--source/blender/physics/intern/implicit_eigen.cpp2
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.c10
-rw-r--r--source/blender/python/intern/bpy_rna_array.c5
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h2
-rw-r--r--source/blender/render/intern/source/render_result.c16
-rw-r--r--source/blender/windowmanager/intern/wm_files.c94
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c47
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp2
m---------source/tools0
-rw-r--r--tests/gtests/blenlib/BLI_task_test.cc76
-rw-r--r--tests/gtests/blenlib/CMakeLists.txt2
242 files changed, 4191 insertions, 2695 deletions
diff --git a/build_files/build_environment/patches/cmake/modules/FindBlosc.cmake b/build_files/build_environment/patches/cmake/modules/FindBlosc.cmake
index d490b7a2ff3..8565ddc73ed 100644
--- a/build_files/build_environment/patches/cmake/modules/FindBlosc.cmake
+++ b/build_files/build_environment/patches/cmake/modules/FindBlosc.cmake
@@ -32,7 +32,6 @@ SET(_blosc_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/blosc
)
diff --git a/build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake b/build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake
index 3dd480356af..781ec0ce6c8 100644
--- a/build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake
+++ b/build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake
@@ -32,7 +32,6 @@ SET(_cppunit_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/cppunit
)
diff --git a/build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake b/build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake
index 2002419cc75..6575cd0c763 100644
--- a/build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake
+++ b/build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake
@@ -32,7 +32,6 @@ SET(_logc4plus_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/logc4plus
)
diff --git a/build_files/build_environment/patches/cmake/modules/FindTBB.cmake b/build_files/build_environment/patches/cmake/modules/FindTBB.cmake
index 8a821f8092e..c44e03b207d 100644
--- a/build_files/build_environment/patches/cmake/modules/FindTBB.cmake
+++ b/build_files/build_environment/patches/cmake/modules/FindTBB.cmake
@@ -32,7 +32,6 @@ SET(_tbb_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/tbb
)
diff --git a/build_files/cmake/Modules/FindAlembic.cmake b/build_files/cmake/Modules/FindAlembic.cmake
index 1f61b5ef462..9f975c08e1a 100644
--- a/build_files/cmake/Modules/FindAlembic.cmake
+++ b/build_files/cmake/Modules/FindAlembic.cmake
@@ -30,7 +30,6 @@ SET(_alembic_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/alembic
)
diff --git a/build_files/cmake/Modules/FindAudaspace.cmake b/build_files/cmake/Modules/FindAudaspace.cmake
index c332ef9a039..cd5116979e2 100644
--- a/build_files/cmake/Modules/FindAudaspace.cmake
+++ b/build_files/cmake/Modules/FindAudaspace.cmake
@@ -20,7 +20,6 @@ SET(_audaspace_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
# Use pkg-config to get hints about paths
diff --git a/build_files/cmake/Modules/FindEigen3.cmake b/build_files/cmake/Modules/FindEigen3.cmake
index 400e8eb047d..c1b25d4169c 100644
--- a/build_files/cmake/Modules/FindEigen3.cmake
+++ b/build_files/cmake/Modules/FindEigen3.cmake
@@ -28,7 +28,6 @@ SET(_eigen3_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
FIND_PATH(EIGEN3_INCLUDE_DIR
diff --git a/build_files/cmake/Modules/FindFftw3.cmake b/build_files/cmake/Modules/FindFftw3.cmake
index 197d4aab7b6..8917cc1c120 100644
--- a/build_files/cmake/Modules/FindFftw3.cmake
+++ b/build_files/cmake/Modules/FindFftw3.cmake
@@ -32,7 +32,6 @@ SET(_fftw3_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
FIND_PATH(FFTW3_INCLUDE_DIR
diff --git a/build_files/cmake/Modules/FindGflags.cmake b/build_files/cmake/Modules/FindGflags.cmake
index 0a138c02465..31d951318c8 100644
--- a/build_files/cmake/Modules/FindGflags.cmake
+++ b/build_files/cmake/Modules/FindGflags.cmake
@@ -445,7 +445,6 @@ if(NOT GFLAGS_FOUND)
/opt/local/include
/usr/include
/sw/include # Fink
- /opt/csw/include # Blastwave
/opt/lib/gflags/include)
list(APPEND GFLAGS_CHECK_PATH_SUFFIXES
@@ -459,7 +458,6 @@ if(NOT GFLAGS_FOUND)
/opt/local/lib
/usr/lib
/sw/lib # Fink
- /opt/csw/lib # Blastwave
/opt/lib/gflags/lib)
list(APPEND GFLAGS_CHECK_LIBRARY_SUFFIXES
gflags/lib # Windows (for C:/Program Files prefix).
diff --git a/build_files/cmake/Modules/FindGlog.cmake b/build_files/cmake/Modules/FindGlog.cmake
index 66c2aab2762..105d42875f6 100644
--- a/build_files/cmake/Modules/FindGlog.cmake
+++ b/build_files/cmake/Modules/FindGlog.cmake
@@ -129,7 +129,6 @@ list(APPEND GLOG_CHECK_INCLUDE_DIRS
/opt/local/include
/usr/include
/sw/include # Fink
- /opt/csw/include # Blastwave
/opt/lib/glog/include)
# Windows (for C:/Program Files prefix).
list(APPEND GLOG_CHECK_PATH_SUFFIXES
@@ -145,7 +144,6 @@ list(APPEND GLOG_CHECK_LIBRARY_DIRS
/opt/local/lib
/usr/lib
/sw/lib # Fink
- /opt/csw/lib # Blastwave
/opt/lib/gflags/lib)
# Windows (for C:/Program Files prefix).
list(APPEND GLOG_CHECK_LIBRARY_SUFFIXES
diff --git a/build_files/cmake/Modules/FindHDF5.cmake b/build_files/cmake/Modules/FindHDF5.cmake
index 56ceda8fb5e..ed140614aa2 100644
--- a/build_files/cmake/Modules/FindHDF5.cmake
+++ b/build_files/cmake/Modules/FindHDF5.cmake
@@ -29,7 +29,6 @@ SET(_hdf5_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/hdf5
)
diff --git a/build_files/cmake/Modules/FindIcuLinux.cmake b/build_files/cmake/Modules/FindIcuLinux.cmake
index e0e5873a4eb..5ccd327da16 100644
--- a/build_files/cmake/Modules/FindIcuLinux.cmake
+++ b/build_files/cmake/Modules/FindIcuLinux.cmake
@@ -35,7 +35,6 @@ SET(_icu_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
# We don't need includes, only libs to link against...
diff --git a/build_files/cmake/Modules/FindJack.cmake b/build_files/cmake/Modules/FindJack.cmake
index caafa3c34a1..ab4fdc99f25 100644
--- a/build_files/cmake/Modules/FindJack.cmake
+++ b/build_files/cmake/Modules/FindJack.cmake
@@ -32,7 +32,6 @@ SET(_jack_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
FIND_PATH(JACK_INCLUDE_DIR
diff --git a/build_files/cmake/Modules/FindJeMalloc.cmake b/build_files/cmake/Modules/FindJeMalloc.cmake
index 466456baf32..707739a3d98 100644
--- a/build_files/cmake/Modules/FindJeMalloc.cmake
+++ b/build_files/cmake/Modules/FindJeMalloc.cmake
@@ -32,7 +32,6 @@ SET(_jemalloc_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/jemalloc
)
diff --git a/build_files/cmake/Modules/FindLZO.cmake b/build_files/cmake/Modules/FindLZO.cmake
index a21aa0a03bb..7aa4adca777 100644
--- a/build_files/cmake/Modules/FindLZO.cmake
+++ b/build_files/cmake/Modules/FindLZO.cmake
@@ -32,7 +32,6 @@ SET(_lzo_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
FIND_PATH(LZO_INCLUDE_DIR lzo/lzo1x.h
diff --git a/build_files/cmake/Modules/FindOpenCOLLADA.cmake b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
index 63bc520ea15..ed9948b8a6c 100644
--- a/build_files/cmake/Modules/FindOpenCOLLADA.cmake
+++ b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
@@ -65,7 +65,6 @@ SET(_opencollada_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/opencollada
)
diff --git a/build_files/cmake/Modules/FindOpenColorIO.cmake b/build_files/cmake/Modules/FindOpenColorIO.cmake
index bd1ecac0a39..bcc22f55bcc 100644
--- a/build_files/cmake/Modules/FindOpenColorIO.cmake
+++ b/build_files/cmake/Modules/FindOpenColorIO.cmake
@@ -38,7 +38,6 @@ SET(_opencolorio_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/ocio
)
diff --git a/build_files/cmake/Modules/FindOpenEXR.cmake b/build_files/cmake/Modules/FindOpenEXR.cmake
index 41e60a75294..ef8d76ea3a5 100644
--- a/build_files/cmake/Modules/FindOpenEXR.cmake
+++ b/build_files/cmake/Modules/FindOpenEXR.cmake
@@ -50,7 +50,6 @@ SET(_openexr_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/openexr
)
diff --git a/build_files/cmake/Modules/FindOpenImageIO.cmake b/build_files/cmake/Modules/FindOpenImageIO.cmake
index d59f9cfcdfc..52b7856c79c 100644
--- a/build_files/cmake/Modules/FindOpenImageIO.cmake
+++ b/build_files/cmake/Modules/FindOpenImageIO.cmake
@@ -34,7 +34,6 @@ SET(_openimageio_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/oiio
)
@@ -76,6 +75,8 @@ IF(OPENIMAGEIO_FOUND)
SET(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO_INCLUDE_DIR})
IF(EXISTS ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO/pugixml.hpp)
SET(OPENIMAGEIO_PUGIXML_FOUND TRUE)
+ ELSE()
+ SET(OPENIMAGEIO_PUGIXML_FOUND FALSE)
ENDIF()
ELSE()
SET(OPENIMAGEIO_PUGIXML_FOUND FALSE)
diff --git a/build_files/cmake/Modules/FindOpenJPEG.cmake b/build_files/cmake/Modules/FindOpenJPEG.cmake
index d765103638b..4b021f13634 100644
--- a/build_files/cmake/Modules/FindOpenJPEG.cmake
+++ b/build_files/cmake/Modules/FindOpenJPEG.cmake
@@ -32,7 +32,6 @@ SET(_openjpeg_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
FIND_PATH(OPENJPEG_INCLUDE_DIR
diff --git a/build_files/cmake/Modules/FindOpenShadingLanguage.cmake b/build_files/cmake/Modules/FindOpenShadingLanguage.cmake
index 824d0f90597..9d9788b9900 100644
--- a/build_files/cmake/Modules/FindOpenShadingLanguage.cmake
+++ b/build_files/cmake/Modules/FindOpenShadingLanguage.cmake
@@ -38,7 +38,6 @@ SET(_osl_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/osl
)
diff --git a/build_files/cmake/Modules/FindOpenSubdiv.cmake b/build_files/cmake/Modules/FindOpenSubdiv.cmake
index 72025506c97..3fca453a7a0 100644
--- a/build_files/cmake/Modules/FindOpenSubdiv.cmake
+++ b/build_files/cmake/Modules/FindOpenSubdiv.cmake
@@ -37,7 +37,6 @@ SET(_opensubdiv_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/opensubdiv
/opt/lib/osd # install_deps.sh
)
diff --git a/build_files/cmake/Modules/FindOpenVDB.cmake b/build_files/cmake/Modules/FindOpenVDB.cmake
index a13feab8e0e..510a5fab261 100644
--- a/build_files/cmake/Modules/FindOpenVDB.cmake
+++ b/build_files/cmake/Modules/FindOpenVDB.cmake
@@ -32,7 +32,6 @@ SET(_openvdb_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/openvdb
/opt/lib/openvdb
)
diff --git a/build_files/cmake/Modules/FindPCRE.cmake b/build_files/cmake/Modules/FindPCRE.cmake
index ff4b7261555..1649a6cbb36 100644
--- a/build_files/cmake/Modules/FindPCRE.cmake
+++ b/build_files/cmake/Modules/FindPCRE.cmake
@@ -32,7 +32,6 @@ SET(_pcre_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
FIND_PATH(PCRE_INCLUDE_DIR pcre.h
diff --git a/build_files/cmake/Modules/FindPugiXML.cmake b/build_files/cmake/Modules/FindPugiXML.cmake
index f7104c16921..2a0dcf08c7e 100644
--- a/build_files/cmake/Modules/FindPugiXML.cmake
+++ b/build_files/cmake/Modules/FindPugiXML.cmake
@@ -32,7 +32,6 @@ SET(_pugixml_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/oiio
)
diff --git a/build_files/cmake/Modules/FindSDL2.cmake b/build_files/cmake/Modules/FindSDL2.cmake
index 2a835cf94fa..7c40a6ef6f3 100644
--- a/build_files/cmake/Modules/FindSDL2.cmake
+++ b/build_files/cmake/Modules/FindSDL2.cmake
@@ -34,7 +34,6 @@ SET(_sdl2_SEARCH_DIRS
/usr
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
FIND_PATH(SDL2_INCLUDE_DIR
diff --git a/build_files/cmake/Modules/FindSndFile.cmake b/build_files/cmake/Modules/FindSndFile.cmake
index 1b685eacfbd..4094b05adab 100644
--- a/build_files/cmake/Modules/FindSndFile.cmake
+++ b/build_files/cmake/Modules/FindSndFile.cmake
@@ -32,7 +32,6 @@ SET(_sndfile_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
FIND_PATH(SNDFILE_INCLUDE_DIR sndfile.h
diff --git a/build_files/cmake/Modules/FindSpacenav.cmake b/build_files/cmake/Modules/FindSpacenav.cmake
index 206f3611ed6..84599643c2d 100644
--- a/build_files/cmake/Modules/FindSpacenav.cmake
+++ b/build_files/cmake/Modules/FindSpacenav.cmake
@@ -32,7 +32,6 @@ SET(_spacenav_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
FIND_PATH(SPACENAV_INCLUDE_DIR
diff --git a/build_files/cmake/Modules/FindTBB.cmake b/build_files/cmake/Modules/FindTBB.cmake
index 8a821f8092e..c44e03b207d 100644
--- a/build_files/cmake/Modules/FindTBB.cmake
+++ b/build_files/cmake/Modules/FindTBB.cmake
@@ -32,7 +32,6 @@ SET(_tbb_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
/opt/lib/tbb
)
diff --git a/build_files/cmake/Modules/FindXML2.cmake b/build_files/cmake/Modules/FindXML2.cmake
index 40cc332fb88..d2df90fa2ec 100644
--- a/build_files/cmake/Modules/FindXML2.cmake
+++ b/build_files/cmake/Modules/FindXML2.cmake
@@ -32,7 +32,6 @@ SET(_xml2_SEARCH_DIRS
/usr/local
/sw # Fink
/opt/local # DarwinPorts
- /opt/csw # Blastwave
)
FIND_PATH(XML2_INCLUDE_DIR libxml2/libxml/xpath.h
diff --git a/intern/atomic/atomic_ops.h b/intern/atomic/atomic_ops.h
index 38670be56fd..e849bcf6cef 100644
--- a/intern/atomic/atomic_ops.h
+++ b/intern/atomic/atomic_ops.h
@@ -82,6 +82,12 @@ ATOMIC_INLINE uint64_t atomic_sub_and_fetch_uint64(uint64_t *p, uint64_t x);
ATOMIC_INLINE uint64_t atomic_fetch_and_add_uint64(uint64_t *p, uint64_t x);
ATOMIC_INLINE uint64_t atomic_fetch_and_sub_uint64(uint64_t *p, uint64_t x);
ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new);
+
+ATOMIC_INLINE int64_t atomic_add_and_fetch_int64(int64_t *p, int64_t x);
+ATOMIC_INLINE int64_t atomic_sub_and_fetch_int64(int64_t *p, int64_t x);
+ATOMIC_INLINE int64_t atomic_fetch_and_add_int64(int64_t *p, int64_t x);
+ATOMIC_INLINE int64_t atomic_fetch_and_sub_int64(int64_t *p, int64_t x);
+ATOMIC_INLINE int64_t atomic_cas_int64(int64_t *v, int64_t old, int64_t _new);
#endif
ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x);
@@ -92,9 +98,23 @@ ATOMIC_INLINE uint32_t atomic_fetch_and_add_uint32(uint32_t *p, uint32_t x);
ATOMIC_INLINE uint32_t atomic_fetch_and_or_uint32(uint32_t *p, uint32_t x);
ATOMIC_INLINE uint32_t atomic_fetch_and_and_uint32(uint32_t *p, uint32_t x);
+ATOMIC_INLINE int32_t atomic_add_and_fetch_int32(int32_t *p, int32_t x);
+ATOMIC_INLINE int32_t atomic_sub_and_fetch_int32(int32_t *p, int32_t x);
+ATOMIC_INLINE int32_t atomic_cas_int32(int32_t *v, int32_t old, int32_t _new);
+
+ATOMIC_INLINE int32_t atomic_fetch_and_add_int32(int32_t *p, int32_t x);
+ATOMIC_INLINE int32_t atomic_fetch_and_or_int32(int32_t *p, int32_t x);
+ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x);
+
ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b);
ATOMIC_INLINE uint8_t atomic_fetch_and_and_uint8(uint8_t *p, uint8_t b);
+ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b);
+ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b);
+
+ATOMIC_INLINE char atomic_fetch_and_or_char(char *p, char b);
+ATOMIC_INLINE char atomic_fetch_and_and_char(char *p, char b);
+
ATOMIC_INLINE size_t atomic_add_and_fetch_z(size_t *p, size_t x);
ATOMIC_INLINE size_t atomic_sub_and_fetch_z(size_t *p, size_t x);
ATOMIC_INLINE size_t atomic_fetch_and_add_z(size_t *p, size_t x);
@@ -110,6 +130,9 @@ ATOMIC_INLINE unsigned int atomic_cas_u(unsigned int *v, unsigned int old, unsig
ATOMIC_INLINE void *atomic_cas_ptr(void **v, void *old, void *_new);
+
+ATOMIC_INLINE float atomic_cas_float(float *v, float old, float _new);
+
/* WARNING! Float 'atomics' are really faked ones, those are actually closer to some kind of spinlock-sync'ed operation,
* which means they are only efficient if collisions are highly unlikely (i.e. if probability of two threads
* working on the same pointer at the same time is very low). */
diff --git a/intern/atomic/intern/atomic_ops_ext.h b/intern/atomic/intern/atomic_ops_ext.h
index 34158a0b45e..1b1fea9642d 100644
--- a/intern/atomic/intern/atomic_ops_ext.h
+++ b/intern/atomic/intern/atomic_ops_ext.h
@@ -56,10 +56,10 @@
/******************************************************************************/
/* size_t operations. */
+ATOMIC_STATIC_ASSERT(sizeof(size_t) == LG_SIZEOF_PTR, "sizeof(size_t) != LG_SIZEOF_PTR");
+
ATOMIC_INLINE size_t atomic_add_and_fetch_z(size_t *p, size_t x)
{
- assert(sizeof(size_t) == LG_SIZEOF_PTR);
-
#if (LG_SIZEOF_PTR == 8)
return (size_t)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)x);
#elif (LG_SIZEOF_PTR == 4)
@@ -69,8 +69,6 @@ ATOMIC_INLINE size_t atomic_add_and_fetch_z(size_t *p, size_t x)
ATOMIC_INLINE size_t atomic_sub_and_fetch_z(size_t *p, size_t x)
{
- assert(sizeof(size_t) == LG_SIZEOF_PTR);
-
#if (LG_SIZEOF_PTR == 8)
return (size_t)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)-((int64_t)x));
#elif (LG_SIZEOF_PTR == 4)
@@ -80,8 +78,6 @@ ATOMIC_INLINE size_t atomic_sub_and_fetch_z(size_t *p, size_t x)
ATOMIC_INLINE size_t atomic_fetch_and_add_z(size_t *p, size_t x)
{
- assert(sizeof(size_t) == LG_SIZEOF_PTR);
-
#if (LG_SIZEOF_PTR == 8)
return (size_t)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)x);
#elif (LG_SIZEOF_PTR == 4)
@@ -91,8 +87,6 @@ ATOMIC_INLINE size_t atomic_fetch_and_add_z(size_t *p, size_t x)
ATOMIC_INLINE size_t atomic_fetch_and_sub_z(size_t *p, size_t x)
{
- assert(sizeof(size_t) == LG_SIZEOF_PTR);
-
#if (LG_SIZEOF_PTR == 8)
return (size_t)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)-((int64_t)x));
#elif (LG_SIZEOF_PTR == 4)
@@ -102,8 +96,6 @@ ATOMIC_INLINE size_t atomic_fetch_and_sub_z(size_t *p, size_t x)
ATOMIC_INLINE size_t atomic_cas_z(size_t *v, size_t old, size_t _new)
{
- assert(sizeof(size_t) == LG_SIZEOF_PTR);
-
#if (LG_SIZEOF_PTR == 8)
return (size_t)atomic_cas_uint64((uint64_t *)v, (uint64_t)old, (uint64_t)_new);
#elif (LG_SIZEOF_PTR == 4)
@@ -124,10 +116,10 @@ ATOMIC_INLINE size_t atomic_fetch_and_update_max_z(size_t *p, size_t x)
/******************************************************************************/
/* unsigned operations. */
+ATOMIC_STATIC_ASSERT(sizeof(unsigned int) == LG_SIZEOF_INT, "sizeof(unsigned int) != LG_SIZEOF_INT");
+
ATOMIC_INLINE unsigned int atomic_add_and_fetch_u(unsigned int *p, unsigned int x)
{
- assert(sizeof(unsigned int) == LG_SIZEOF_INT);
-
#if (LG_SIZEOF_INT == 8)
return (unsigned int)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)x);
#elif (LG_SIZEOF_INT == 4)
@@ -137,8 +129,6 @@ ATOMIC_INLINE unsigned int atomic_add_and_fetch_u(unsigned int *p, unsigned int
ATOMIC_INLINE unsigned int atomic_sub_and_fetch_u(unsigned int *p, unsigned int x)
{
- assert(sizeof(unsigned int) == LG_SIZEOF_INT);
-
#if (LG_SIZEOF_INT == 8)
return (unsigned int)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)-((int64_t)x));
#elif (LG_SIZEOF_INT == 4)
@@ -148,8 +138,6 @@ ATOMIC_INLINE unsigned int atomic_sub_and_fetch_u(unsigned int *p, unsigned int
ATOMIC_INLINE unsigned int atomic_fetch_and_add_u(unsigned int *p, unsigned int x)
{
- assert(sizeof(unsigned int) == LG_SIZEOF_INT);
-
#if (LG_SIZEOF_INT == 8)
return (unsigned int)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)x);
#elif (LG_SIZEOF_INT == 4)
@@ -159,8 +147,6 @@ ATOMIC_INLINE unsigned int atomic_fetch_and_add_u(unsigned int *p, unsigned int
ATOMIC_INLINE unsigned int atomic_fetch_and_sub_u(unsigned int *p, unsigned int x)
{
- assert(sizeof(unsigned int) == LG_SIZEOF_INT);
-
#if (LG_SIZEOF_INT == 8)
return (unsigned int)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)-((int64_t)x));
#elif (LG_SIZEOF_INT == 4)
@@ -170,8 +156,6 @@ ATOMIC_INLINE unsigned int atomic_fetch_and_sub_u(unsigned int *p, unsigned int
ATOMIC_INLINE unsigned int atomic_cas_u(unsigned int *v, unsigned int old, unsigned int _new)
{
- assert(sizeof(unsigned int) == LG_SIZEOF_INT);
-
#if (LG_SIZEOF_INT == 8)
return (unsigned int)atomic_cas_uint64((uint64_t *)v, (uint64_t)old, (uint64_t)_new);
#elif (LG_SIZEOF_INT == 4)
@@ -180,6 +164,18 @@ ATOMIC_INLINE unsigned int atomic_cas_u(unsigned int *v, unsigned int old, unsig
}
/******************************************************************************/
+/* Char operations. */
+ATOMIC_INLINE char atomic_fetch_and_or_char(char *p, char b)
+{
+ return (char)atomic_fetch_and_or_uint8((uint8_t *)p, (uint8_t)b);
+}
+
+ATOMIC_INLINE char atomic_fetch_and_and_char(char *p, char b)
+{
+ return (char)atomic_fetch_and_and_uint8((uint8_t *)p, (uint8_t)b);
+}
+
+/******************************************************************************/
/* Pointer operations. */
ATOMIC_INLINE void *atomic_cas_ptr(void **v, void *old, void *_new)
@@ -193,11 +189,16 @@ ATOMIC_INLINE void *atomic_cas_ptr(void **v, void *old, void *_new)
/******************************************************************************/
/* float operations. */
+ATOMIC_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t), "sizeof(float) != sizeof(uint32_t)");
-ATOMIC_INLINE float atomic_add_and_fetch_fl(float *p, const float x)
+ATOMIC_INLINE float atomic_cas_float(float *v, float old, float _new)
{
- assert(sizeof(float) == sizeof(uint32_t));
+ uint32_t ret = atomic_cas_uint32((uint32_t *)v, *(uint32_t *)&old, *(uint32_t *)&_new);
+ return *(float *)&ret;
+}
+ATOMIC_INLINE float atomic_add_and_fetch_fl(float *p, const float x)
+{
float oldval, newval;
uint32_t prevval;
diff --git a/intern/atomic/intern/atomic_ops_msvc.h b/intern/atomic/intern/atomic_ops_msvc.h
index 034ac1e3e53..c24a9095735 100644
--- a/intern/atomic/intern/atomic_ops_msvc.h
+++ b/intern/atomic/intern/atomic_ops_msvc.h
@@ -43,6 +43,7 @@
/******************************************************************************/
/* 64-bit operations. */
#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
+/* Unsigned */
ATOMIC_INLINE uint64_t atomic_add_and_fetch_uint64(uint64_t *p, uint64_t x)
{
return InterlockedExchangeAdd64((int64_t *)p, (int64_t)x) + x;
@@ -67,10 +68,37 @@ ATOMIC_INLINE uint64_t atomic_fetch_and_sub_uint64(uint64_t *p, uint64_t x)
{
return InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x));
}
+
+/* Signed */
+ATOMIC_INLINE int64_t atomic_add_and_fetch_int64(int64_t *p, int64_t x)
+{
+ return InterlockedExchangeAdd64(p, x) + x;
+}
+
+ATOMIC_INLINE int64_t atomic_sub_and_fetch_int64(int64_t *p, int64_t x)
+{
+ return InterlockedExchangeAdd64(p, -x) - x;
+}
+
+ATOMIC_INLINE int64_t atomic_cas_int64(int64_t *v, int64_t old, int64_t _new)
+{
+ return InterlockedCompareExchange64(v, _new, old);
+}
+
+ATOMIC_INLINE int64_t atomic_fetch_and_add_int64(int64_t *p, int64_t x)
+{
+ return InterlockedExchangeAdd64(p, x);
+}
+
+ATOMIC_INLINE int64_t atomic_fetch_and_sub_int64(int64_t *p, int64_t x)
+{
+ return InterlockedExchangeAdd64(p, -x);
+}
#endif
/******************************************************************************/
/* 32-bit operations. */
+/* Unsigned */
ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x)
{
return InterlockedExchangeAdd(p, x) + x;
@@ -101,9 +129,41 @@ ATOMIC_INLINE uint32_t atomic_fetch_and_and_uint32(uint32_t *p, uint32_t x)
return InterlockedAnd((long *)p, x);
}
+/* Signed */
+ATOMIC_INLINE int32_t atomic_add_and_fetch_int32(int32_t *p, int32_t x)
+{
+ return InterlockedExchangeAdd((long *)p, x) + x;
+}
+
+ATOMIC_INLINE int32_t atomic_sub_and_fetch_int32(int32_t *p, int32_t x)
+{
+ return InterlockedExchangeAdd((long *)p, -x) - x;
+}
+
+ATOMIC_INLINE int32_t atomic_cas_int32(int32_t *v, int32_t old, int32_t _new)
+{
+ return InterlockedCompareExchange((long *)v, _new, old);
+}
+
+ATOMIC_INLINE int32_t atomic_fetch_and_add_int32(int32_t *p, int32_t x)
+{
+ return InterlockedExchangeAdd((long *)p, x);
+}
+
+ATOMIC_INLINE int32_t atomic_fetch_and_or_int32(int32_t *p, int32_t x)
+{
+ return InterlockedOr((long *)p, x);
+}
+
+ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x)
+{
+ return InterlockedAnd((long *)p, x);
+}
+
/******************************************************************************/
/* 8-bit operations. */
+/* Unsigned */
#pragma intrinsic(_InterlockedAnd8)
ATOMIC_INLINE uint8_t atomic_fetch_and_and_uint8(uint8_t *p, uint8_t b)
{
@@ -124,4 +184,25 @@ ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b)
#endif
}
+/* Signed */
+#pragma intrinsic(_InterlockedAnd8)
+ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b)
+{
+#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
+ return InterlockedAnd8((char *)p, (char)b);
+#else
+ return _InterlockedAnd8((char *)p, (char)b);
+#endif
+}
+
+#pragma intrinsic(_InterlockedOr8)
+ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b)
+{
+#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
+ return InterlockedOr8((char *)p, (char)b);
+#else
+ return _InterlockedOr8((char *)p, (char)b);
+#endif
+}
+
#endif /* __ATOMIC_OPS_MSVC_H__ */
diff --git a/intern/atomic/intern/atomic_ops_unix.h b/intern/atomic/intern/atomic_ops_unix.h
index 0a3322ad2b1..783a30f743b 100644
--- a/intern/atomic/intern/atomic_ops_unix.h
+++ b/intern/atomic/intern/atomic_ops_unix.h
@@ -58,6 +58,7 @@
/* 64-bit operations. */
#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
# if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8))
+/* Unsigned */
ATOMIC_INLINE uint64_t atomic_add_and_fetch_uint64(uint64_t *p, uint64_t x)
{
return __sync_add_and_fetch(p, x);
@@ -82,7 +83,35 @@ ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _ne
{
return __sync_val_compare_and_swap(v, old, _new);
}
+
+/* Signed */
+ATOMIC_INLINE int64_t atomic_add_and_fetch_int64(int64_t *p, int64_t x)
+{
+ return __sync_add_and_fetch(p, x);
+}
+
+ATOMIC_INLINE int64_t atomic_sub_and_fetch_int64(int64_t *p, int64_t x)
+{
+ return __sync_sub_and_fetch(p, x);
+}
+
+ATOMIC_INLINE int64_t atomic_fetch_and_add_int64(int64_t *p, int64_t x)
+{
+ return __sync_fetch_and_add(p, x);
+}
+
+ATOMIC_INLINE int64_t atomic_fetch_and_sub_int64(int64_t *p, int64_t x)
+{
+ return __sync_fetch_and_sub(p, x);
+}
+
+ATOMIC_INLINE int64_t atomic_cas_int64(int64_t *v, int64_t old, int64_t _new)
+{
+ return __sync_val_compare_and_swap(v, old, _new);
+}
+
# elif (defined(__amd64__) || defined(__x86_64__))
+/* Unsigned */
ATOMIC_INLINE uint64_t atomic_fetch_and_add_uint64(uint64_t *p, uint64_t x)
{
asm volatile (
@@ -124,6 +153,49 @@ ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _ne
: "memory");
return ret;
}
+
+/* Signed */
+ATOMIC_INLINE int64_t atomic_fetch_and_add_int64(int64_t *p, int64_t x)
+{
+ asm volatile (
+ "lock; xaddq %0, %1;"
+ : "+r" (x), "=m" (*p) /* Outputs. */
+ : "m" (*p) /* Inputs. */
+ );
+ return x;
+}
+
+ATOMIC_INLINE int64_t atomic_fetch_and_sub_int64(int64_t *p, int64_t x)
+{
+ x = -x;
+ asm volatile (
+ "lock; xaddq %0, %1;"
+ : "+r" (x), "=m" (*p) /* Outputs. */
+ : "m" (*p) /* Inputs. */
+ );
+ return x;
+}
+
+ATOMIC_INLINE int64_t atomic_add_and_fetch_int64(int64_t *p, int64_t x)
+{
+ return atomic_fetch_and_add_int64(p, x) + x;
+}
+
+ATOMIC_INLINE int64_t atomic_sub_and_fetch_int64(int64_t *p, int64_t x)
+{
+ return atomic_fetch_and_sub_int64(p, x) - x;
+}
+
+ATOMIC_INLINE int64_t atomic_cas_int64(int64_t *v, int64_t old, int64_t _new)
+{
+ int64_t ret;
+ asm volatile (
+ "lock; cmpxchgq %2,%1"
+ : "=a" (ret), "+m" (*v)
+ : "r" (_new), "0" (old)
+ : "memory");
+ return ret;
+}
# else
# error "Missing implementation for 64-bit atomic operations"
# endif
@@ -132,6 +204,7 @@ ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _ne
/******************************************************************************/
/* 32-bit operations. */
#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))
+/* Unsigned */
ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x)
{
return __sync_add_and_fetch(p, x);
@@ -146,7 +219,25 @@ ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _ne
{
return __sync_val_compare_and_swap(v, old, _new);
}
+
+/* Signed */
+ATOMIC_INLINE int32_t atomic_add_and_fetch_int32(int32_t *p, int32_t x)
+{
+ return __sync_add_and_fetch(p, x);
+}
+
+ATOMIC_INLINE int32_t atomic_sub_and_fetch_int32(int32_t *p, int32_t x)
+{
+ return __sync_sub_and_fetch(p, x);
+}
+
+ATOMIC_INLINE int32_t atomic_cas_int32(int32_t *v, int32_t old, int32_t _new)
+{
+ return __sync_val_compare_and_swap(v, old, _new);
+}
+
#elif (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))
+/* Unsigned */
ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x)
{
uint32_t ret = x;
@@ -155,18 +246,18 @@ ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x)
: "+r" (ret), "=m" (*p) /* Outputs. */
: "m" (*p) /* Inputs. */
);
- return ret+x;
+ return ret + x;
}
ATOMIC_INLINE uint32_t atomic_sub_and_fetch_uint32(uint32_t *p, uint32_t x)
{
- ret = (uint32_t)(-(int32_t)x);
+ uint32_t ret = (uint32_t)(-(int32_t)x);
asm volatile (
"lock; xaddl %0, %1;"
: "+r" (ret), "=m" (*p) /* Outputs. */
: "m" (*p) /* Inputs. */
);
- return ret-x;
+ return ret - x;
}
ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new)
@@ -179,11 +270,47 @@ ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _ne
: "memory");
return ret;
}
+
+/* Signed */
+ATOMIC_INLINE int32_t atomic_add_and_fetch_int32(int32_t *p, int32_t x)
+{
+ int32_t ret = x;
+ asm volatile (
+ "lock; xaddl %0, %1;"
+ : "+r" (ret), "=m" (*p) /* Outputs. */
+ : "m" (*p) /* Inputs. */
+ );
+ return ret + x;
+}
+
+ATOMIC_INLINE int32_t atomic_sub_and_fetch_int32(int32_t *p, int32_t x)
+{
+ int32_t ret = -x;
+ asm volatile (
+ "lock; xaddl %0, %1;"
+ : "+r" (ret), "=m" (*p) /* Outputs. */
+ : "m" (*p) /* Inputs. */
+ );
+ return ret - x;
+}
+
+ATOMIC_INLINE int32_t atomic_cas_int32(int32_t *v, int32_t old, int32_t _new)
+{
+ int32_t ret;
+ asm volatile (
+ "lock; cmpxchgl %2,%1"
+ : "=a" (ret), "+m" (*v)
+ : "r" (_new), "0" (old)
+ : "memory");
+ return ret;
+}
+
#else
# error "Missing implementation for 32-bit atomic operations"
#endif
#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))
+/* Unsigned */
ATOMIC_INLINE uint32_t atomic_fetch_and_add_uint32(uint32_t *p, uint32_t x)
{
return __sync_fetch_and_add(p, x);
@@ -199,6 +326,22 @@ ATOMIC_INLINE uint32_t atomic_fetch_and_and_uint32(uint32_t *p, uint32_t x)
return __sync_fetch_and_and(p, x);
}
+/* Signed */
+ATOMIC_INLINE int32_t atomic_fetch_and_add_int32(int32_t *p, int32_t x)
+{
+ return __sync_fetch_and_add(p, x);
+}
+
+ATOMIC_INLINE int32_t atomic_fetch_and_or_int32(int32_t *p, int32_t x)
+{
+ return __sync_fetch_and_or(p, x);
+}
+
+ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x)
+{
+ return __sync_fetch_and_and(p, x);
+}
+
#else
# error "Missing implementation for 32-bit atomic operations"
#endif
@@ -206,6 +349,7 @@ ATOMIC_INLINE uint32_t atomic_fetch_and_and_uint32(uint32_t *p, uint32_t x)
/******************************************************************************/
/* 8-bit operations. */
#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_1))
+/* Unsigned */
ATOMIC_INLINE uint8_t atomic_fetch_and_and_uint8(uint8_t *p, uint8_t b)
{
return __sync_fetch_and_and(p, b);
@@ -214,6 +358,17 @@ ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b)
{
return __sync_fetch_and_or(p, b);
}
+
+/* Signed */
+ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b)
+{
+ return __sync_fetch_and_and(p, b);
+}
+ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b)
+{
+ return __sync_fetch_and_or(p, b);
+}
+
#else
# error "Missing implementation for 8-bit atomic operations"
#endif
diff --git a/intern/atomic/intern/atomic_ops_utils.h b/intern/atomic/intern/atomic_ops_utils.h
index c190b655e0a..621b3e95906 100644
--- a/intern/atomic/intern/atomic_ops_utils.h
+++ b/intern/atomic/intern/atomic_ops_utils.h
@@ -104,4 +104,31 @@
# error "Cannot find int size"
#endif
+/* Copied from BLI_utils... */
+/* C++ can't use _Static_assert, expects static_assert() but c++0x only,
+ * Coverity also errors out. */
+#if (!defined(__cplusplus)) && \
+ (!defined(__COVERITY__)) && \
+ (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */
+# define ATOMIC_STATIC_ASSERT(a, msg) __extension__ _Static_assert(a, msg);
+#else
+/* Code adapted from http://www.pixelbeat.org/programming/gcc/static_assert.html */
+/* Note we need the two concats below because arguments to ## are not expanded, so we need to
+ * expand __LINE__ with one indirection before doing the actual concatenation. */
+# define ATOMIC_ASSERT_CONCAT_(a, b) a##b
+# define ATOMIC_ASSERT_CONCAT(a, b) ATOMIC_ASSERT_CONCAT_(a, b)
+ /* These can't be used after statements in c89. */
+# if defined(__COUNTER__) /* MSVC */
+# define ATOMIC_STATIC_ASSERT(a, msg) \
+ ; enum { ATOMIC_ASSERT_CONCAT(static_assert_, __COUNTER__) = 1 / (int)(!!(a)) };
+# else /* older gcc, clang... */
+ /* This can't be used twice on the same line so ensure if using in headers
+ * that the headers are not included twice (by wrapping in #ifndef...#endif)
+ * Note it doesn't cause an issue when used on same line of separate modules
+ * compiled with gcc -combine -fwhole-program. */
+# define ATOMIC_STATIC_ASSERT(a, msg) \
+ ; enum { ATOMIC_ASSERT_CONCAT(assert_line_, __LINE__) = 1 / (int)(!!(a)) };
+# endif
+#endif
+
#endif /* __ATOMIC_OPS_UTILS_H__ */
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 5844c2480d6..dbf1bcece16 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -209,6 +209,10 @@ if(WITH_CYCLES_DEBUG)
add_definitions(-DWITH_CYCLES_DEBUG)
endif()
+if(NOT OPENIMAGEIO_PUGIXML_FOUND)
+ add_definitions(-DWITH_SYSTEM_PUGIXML)
+endif()
+
include_directories(
SYSTEM
${BOOST_INCLUDE_DIR}
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 3a1c7205c34..f2db9271a89 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -358,7 +358,7 @@ static void xml_read_shader(XMLReadState& state, xml_node node)
/* Background */
-static void xml_read_background(XMLReadState& state, pugi::xml_node node)
+static void xml_read_background(XMLReadState& state, xml_node node)
{
/* Background Settings */
xml_read_node(state, state.scene->background, node);
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 3018fd5b316..1f97eff9bd0 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -234,10 +234,13 @@ def register_passes(engine, scene, srl):
if srl.use_pass_environment: engine.register_pass(scene, srl, "Env", 3, "RGB", 'COLOR')
crl = srl.cycles
- if crl.pass_debug_bvh_traversed_nodes: engine.register_pass(scene, srl, "Debug BVH Traversed Nodes", 1, "X", 'VALUE')
- if crl.pass_debug_bvh_traversed_instances: engine.register_pass(scene, srl, "Debug BVH Traversed Instances", 1, "X", 'VALUE')
- if crl.pass_debug_bvh_intersections: engine.register_pass(scene, srl, "Debug BVH Intersections", 1, "X", 'VALUE')
- if crl.pass_debug_ray_bounces: engine.register_pass(scene, srl, "Debug Ray Bounces", 1, "X", 'VALUE')
+ if crl.pass_debug_render_time: engine.register_pass(scene, srl, "Debug Render Time", 1, "X", 'VALUE')
+ if crl.pass_debug_bvh_traversed_nodes: engine.register_pass(scene, srl, "Debug BVH Traversed Nodes", 1, "X", 'VALUE')
+ if crl.pass_debug_bvh_traversed_instances: engine.register_pass(scene, srl, "Debug BVH Traversed Instances", 1, "X", 'VALUE')
+ if crl.pass_debug_bvh_intersections: engine.register_pass(scene, srl, "Debug BVH Intersections", 1, "X", 'VALUE')
+ if crl.pass_debug_ray_bounces: engine.register_pass(scene, srl, "Debug Ray Bounces", 1, "X", 'VALUE')
+ if crl.use_pass_volume_direct: engine.register_pass(scene, srl, "VolumeDir", 3, "RGB", 'COLOR')
+ if crl.use_pass_volume_indirect: engine.register_pass(scene, srl, "VolumeInd", 3, "RGB", 'COLOR')
cscene = scene.cycles
if crl.use_denoising and crl.denoising_store_passes and not cscene.use_progressive_refine:
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 2e149527066..e5084138a9c 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -1189,6 +1189,24 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
default=False,
update=update_render_passes,
)
+ cls.pass_debug_render_time = BoolProperty(
+ name="Debug Render Time",
+ description="Render time in milliseconds per sample and pixel",
+ default=False,
+ update=update_render_passes,
+ )
+ cls.use_pass_volume_direct = BoolProperty(
+ name="Volume Direct",
+ description="Deliver direct volumetric scattering pass",
+ default=False,
+ update=update_render_passes,
+ )
+ cls.use_pass_volume_indirect = BoolProperty(
+ name="Volume Indirect",
+ description="Deliver indirect volumetric scattering pass",
+ default=False,
+ update=update_render_passes,
+ )
cls.use_denoising = BoolProperty(
name="Use Denoising",
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 67f1029acb9..03ca1ab6c7f 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -526,6 +526,10 @@ class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel):
row.prop(rl, "use_pass_subsurface_direct", text="Direct", toggle=True)
row.prop(rl, "use_pass_subsurface_indirect", text="Indirect", toggle=True)
row.prop(rl, "use_pass_subsurface_color", text="Color", toggle=True)
+ col.label(text="Volume:")
+ row = col.row(align=True)
+ row.prop(crl, "use_pass_volume_direct", text="Direct", toggle=True)
+ row.prop(crl, "use_pass_volume_indirect", text="Indirect", toggle=True)
col.separator()
col.prop(rl, "use_pass_emit", text="Emission")
@@ -537,8 +541,9 @@ class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel):
sub.active = crl.use_denoising
sub.prop(crl, "denoising_store_passes", text="Denoising")
+ col = layout.column()
+ col.prop(crl, "pass_debug_render_time")
if _cycles.with_cycles_debug:
- col = layout.column()
col.prop(crl, "pass_debug_bvh_traversed_nodes")
col.prop(crl, "pass_debug_bvh_traversed_instances")
col.prop(crl, "pass_debug_bvh_intersections")
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index eb573b75e9e..f02d5496112 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -112,6 +112,7 @@ static uint object_ray_visibility(BL::Object& b_ob)
void BlenderSync::sync_light(BL::Object& b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
BL::Object& b_ob,
+ BL::DupliObject& b_dupli_ob,
Transform& tfm,
bool *use_portal)
{
@@ -193,6 +194,13 @@ void BlenderSync::sync_light(BL::Object& b_parent,
light->max_bounces = get_int(clamp, "max_bounces");
+ if(b_dupli_ob) {
+ light->random_id = b_dupli_ob.random_id();
+ }
+ else {
+ light->random_id = hash_int_2d(hash_string(b_ob.name().c_str()), 0);
+ }
+
if(light->type == LIGHT_AREA)
light->is_portal = get_boolean(clamp, "is_portal");
else
@@ -271,7 +279,7 @@ Object *BlenderSync::sync_object(BL::Object& b_parent,
if(object_is_light(b_ob)) {
/* don't use lamps for excluded layers used as mask layer */
if(!motion && !((layer_flag & render_layer.holdout_layer) && (layer_flag & render_layer.exclude_layer)))
- sync_light(b_parent, persistent_id, b_ob, tfm, use_portal);
+ sync_light(b_parent, persistent_id, b_ob, b_dupli_ob, tfm, use_portal);
return NULL;
}
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 142fd5ef85b..e24ed31b926 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -496,11 +496,13 @@ PassType BlenderSync::get_pass_type(BL::RenderPass& b_pass)
MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT);
MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT);
MAP_PASS("SubsurfaceDir", PASS_SUBSURFACE_DIRECT);
+ MAP_PASS("VolumeDir", PASS_VOLUME_DIRECT);
MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT);
MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT);
MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT);
MAP_PASS("SubsurfaceInd", PASS_SUBSURFACE_INDIRECT);
+ MAP_PASS("VolumeInd", PASS_VOLUME_INDIRECT);
MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR);
MAP_PASS("GlossCol", PASS_GLOSSY_COLOR);
@@ -518,6 +520,7 @@ PassType BlenderSync::get_pass_type(BL::RenderPass& b_pass)
MAP_PASS("Debug BVH Intersections", PASS_BVH_INTERSECTIONS);
MAP_PASS("Debug Ray Bounces", PASS_RAY_BOUNCES);
#endif
+ MAP_PASS("Debug Render Time", PASS_RENDER_TIME);
#undef MAP_PASS
return PASS_NONE;
@@ -604,6 +607,18 @@ array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
Pass::add(PASS_RAY_BOUNCES, passes);
}
#endif
+ if(get_boolean(crp, "pass_debug_render_time")) {
+ b_engine.add_pass("Debug Render Time", 1, "X", b_srlay.name().c_str());
+ Pass::add(PASS_RENDER_TIME, passes);
+ }
+ if(get_boolean(crp, "use_pass_volume_direct")) {
+ b_engine.add_pass("VolumeDir", 3, "RGB", b_srlay.name().c_str());
+ Pass::add(PASS_VOLUME_DIRECT, passes);
+ }
+ if(get_boolean(crp, "use_pass_volume_indirect")) {
+ b_engine.add_pass("VolumeInd", 3, "RGB", b_srlay.name().c_str());
+ Pass::add(PASS_VOLUME_INDIRECT, passes);
+ }
return passes;
}
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 11e279b81c4..e7b71ae9310 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -131,6 +131,7 @@ private:
void sync_light(BL::Object& b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
BL::Object& b_ob,
+ BL::DupliObject& b_dupli_ob,
Transform& tfm,
bool *use_portal);
void sync_background_light(bool use_portal);
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index 7557f584ebe..12094d58101 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -688,6 +688,8 @@ public:
void path_trace(DeviceTask &task, RenderTile &tile, KernelGlobals *kg)
{
+ scoped_timer timer(&tile.buffers->render_time);
+
float *render_buffer = (float*)tile.buffer;
int start_sample = tile.start_sample;
int end_sample = tile.start_sample + tile.num_samples;
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index a38340cb286..d8d787ba706 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -908,7 +908,7 @@ public:
cmem->texobject = 0;
cmem->array = array_3d;
}
- else if(mem.data_height > 1) {
+ else if(mem.data_height > 0) {
/* 2D texture, using pitch aligned linear memory. */
int alignment = 0;
cuda_assert(cuDeviceGetAttribute(&alignment, CU_DEVICE_ATTRIBUTE_TEXTURE_PITCH_ALIGNMENT, cuDevice));
@@ -962,7 +962,7 @@ public:
resDesc.res.array.hArray = array_3d;
resDesc.flags = 0;
}
- else if(mem.data_height > 1) {
+ else if(mem.data_height > 0) {
resDesc.resType = CU_RESOURCE_TYPE_PITCH2D;
resDesc.res.pitch2D.devPtr = mem.device_pointer;
resDesc.res.pitch2D.format = format;
@@ -1012,7 +1012,7 @@ public:
if(array_3d) {
cuda_assert(cuTexRefSetArray(texref, array_3d, CU_TRSA_OVERRIDE_FORMAT));
}
- else if(mem.data_height > 1) {
+ else if(mem.data_height > 0) {
CUDA_ARRAY_DESCRIPTOR array_desc;
array_desc.Format = format;
array_desc.Height = mem.data_height;
@@ -1436,6 +1436,8 @@ public:
void path_trace(DeviceTask& task, RenderTile& rtile, device_vector<WorkTile>& work_tiles)
{
+ scoped_timer timer(&rtile.buffers->render_time);
+
if(have_error())
return;
diff --git a/intern/cycles/device/opencl/opencl_mega.cpp b/intern/cycles/device/opencl/opencl_mega.cpp
index 575ab73330e..ef39cfb5f7d 100644
--- a/intern/cycles/device/opencl/opencl_mega.cpp
+++ b/intern/cycles/device/opencl/opencl_mega.cpp
@@ -59,6 +59,8 @@ public:
void path_trace(RenderTile& rtile, int sample)
{
+ scoped_timer timer(&rtile.buffers->render_time);
+
/* Cast arguments to cl types. */
cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
cl_mem d_buffer = CL_MEM_PTR(rtile.buffer);
diff --git a/intern/cycles/device/opencl/opencl_split.cpp b/intern/cycles/device/opencl/opencl_split.cpp
index 1073cfa6bf6..2d819080674 100644
--- a/intern/cycles/device/opencl/opencl_split.cpp
+++ b/intern/cycles/device/opencl/opencl_split.cpp
@@ -138,6 +138,8 @@ public:
while(task->acquire_tile(this, tile)) {
if(tile.task == RenderTile::PATH_TRACE) {
assert(tile.task == RenderTile::PATH_TRACE);
+ scoped_timer timer(&tile.buffers->render_time);
+
split_kernel->path_trace(task,
tile,
kgbuffer,
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 0a3f9ff23fe..e4573024e85 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -36,6 +36,22 @@
CCL_NAMESPACE_BEGIN
+/* Returns the square of the roughness of the closure if it has roughness,
+ * 0 for singular closures and 1 otherwise. */
+ccl_device_inline float bsdf_get_roughness_sqr(const ShaderClosure *sc)
+{
+ if(CLOSURE_IS_BSDF_SINGULAR(sc->type)) {
+ return 0.0f;
+ }
+
+ if(CLOSURE_IS_BSDF_MICROFACET(sc->type)) {
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*) sc;
+ return bsdf->alpha_x*bsdf->alpha_y;
+ }
+
+ return 1.0f;
+}
+
ccl_device_forceinline int bsdf_sample(KernelGlobals *kg,
ShaderData *sd,
const ShaderClosure *sc,
@@ -438,23 +454,5 @@ ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
#endif
}
-/* Classifies a closure as diffuse-like or specular-like.
- * This is needed for the denoising feature pass generation,
- * which are written on the first bounce where more than 25%
- * of the sampling weight belongs to diffuse-line closures. */
-ccl_device_inline bool bsdf_is_specular_like(ShaderClosure *sc)
-{
- if(CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) {
- return true;
- }
-
- if(CLOSURE_IS_BSDF_MICROFACET(sc->type)) {
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*) sc;
- return (bsdf->alpha_x*bsdf->alpha_y <= 0.075f*0.075f);
- }
-
- return false;
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h
index 6791c0b83cc..ec10e452148 100644
--- a/intern/cycles/kernel/closure/bssrdf.h
+++ b/intern/cycles/kernel/closure/bssrdf.h
@@ -119,7 +119,7 @@ ccl_device float bssrdf_cubic_eval(const float radius, const float sharpness, fl
else {
Rmy = powf(Rm, y);
ry = powf(r, y);
- ryinv = (r > 0.0f)? powf(r, 2.0f*y - 2.0f): 0.0f;
+ ryinv = (r > 0.0f)? powf(r, y - 1.0f): 0.0f;
}
const float Rmy5 = (Rmy*Rmy) * (Rmy*Rmy) * Rmy;
diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h
index 1ffc143be34..a276096a745 100644
--- a/intern/cycles/kernel/geom/geom_object.h
+++ b/intern/cycles/kernel/geom/geom_object.h
@@ -244,6 +244,17 @@ ccl_device_inline float object_pass_id(KernelGlobals *kg, int object)
return f.y;
}
+/* Per lamp random number for shader variation */
+
+ccl_device_inline float lamp_random_number(KernelGlobals *kg, int lamp)
+{
+ if(lamp == LAMP_NONE)
+ return 0.0f;
+
+ float4 f = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 4);
+ return f.y;
+}
+
/* Per object random number for shader variation */
ccl_device_inline float object_random_number(KernelGlobals *kg, int object)
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index 366f25422fd..7c1b2a015e1 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -187,7 +187,6 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
L->color_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->color_transmission = make_float3(0.0f, 0.0f, 0.0f);
L->color_subsurface = make_float3(0.0f, 0.0f, 0.0f);
- L->color_scatter = make_float3(0.0f, 0.0f, 0.0f);
L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index b31356905f2..29451b6b8b6 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -140,7 +140,7 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg,
/* All closures contribute to the normal feature, but only diffuse-like ones to the albedo. */
normal += sc->N * sc->sample_weight;
sum_weight += sc->sample_weight;
- if(!bsdf_is_specular_like(sc)) {
+ if(bsdf_get_roughness_sqr(sc) > sqr(0.075f)) {
albedo += sc->weight;
sum_nonspecular_weight += sc->sample_weight;
}
@@ -170,19 +170,19 @@ ccl_device_inline void kernel_write_debug_passes(KernelGlobals *kg,
PathRadiance *L)
{
int flag = kernel_data.film.pass_flag;
- if(flag & PASS_BVH_TRAVERSED_NODES) {
+ if(flag & PASSMASK(BVH_TRAVERSED_NODES)) {
kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_nodes,
L->debug_data.num_bvh_traversed_nodes);
}
- if(flag & PASS_BVH_TRAVERSED_INSTANCES) {
+ if(flag & PASSMASK(BVH_TRAVERSED_INSTANCES)) {
kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_instances,
L->debug_data.num_bvh_traversed_instances);
}
- if(flag & PASS_BVH_INTERSECTIONS) {
+ if(flag & PASSMASK(BVH_INTERSECTIONS)) {
kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_intersections,
L->debug_data.num_bvh_intersections);
}
- if(flag & PASS_RAY_BOUNCES) {
+ if(flag & PASSMASK(RAY_BOUNCES)) {
kernel_write_pass_float(buffer + kernel_data.film.pass_ray_bounces,
L->debug_data.num_ray_bounces);
}
@@ -199,8 +199,9 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
return;
int flag = kernel_data.film.pass_flag;
+ int light_flag = kernel_data.film.light_pass_flag;
- if(!(flag & PASS_ALL))
+ if(!((flag | light_flag) & PASS_ANY))
return;
if(!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) {
@@ -209,29 +210,29 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold)
{
if(state->sample == 0) {
- if(flag & PASS_DEPTH) {
+ if(flag & PASSMASK(DEPTH)) {
float depth = camera_distance(kg, sd->P);
kernel_write_pass_float(buffer + kernel_data.film.pass_depth, depth);
}
- if(flag & PASS_OBJECT_ID) {
+ if(flag & PASSMASK(OBJECT_ID)) {
float id = object_pass_id(kg, sd->object);
kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, id);
}
- if(flag & PASS_MATERIAL_ID) {
+ if(flag & PASSMASK(MATERIAL_ID)) {
float id = shader_pass_id(kg, sd);
kernel_write_pass_float(buffer + kernel_data.film.pass_material_id, id);
}
}
- if(flag & PASS_NORMAL) {
+ if(flag & PASSMASK(NORMAL)) {
float3 normal = shader_bsdf_average_normal(kg, sd);
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, normal);
}
- if(flag & PASS_UV) {
+ if(flag & PASSMASK(UV)) {
float3 uv = primitive_uv(kg, sd);
kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, uv);
}
- if(flag & PASS_MOTION) {
+ if(flag & PASSMASK(MOTION)) {
float4 speed = primitive_motion_vector(kg, sd);
kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, speed);
kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, 1.0f);
@@ -241,16 +242,16 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
}
}
- if(flag & (PASS_DIFFUSE_INDIRECT|PASS_DIFFUSE_COLOR|PASS_DIFFUSE_DIRECT))
+ if(light_flag & PASSMASK_COMPONENT(DIFFUSE))
L->color_diffuse += shader_bsdf_diffuse(kg, sd)*throughput;
- if(flag & (PASS_GLOSSY_INDIRECT|PASS_GLOSSY_COLOR|PASS_GLOSSY_DIRECT))
+ if(light_flag & PASSMASK_COMPONENT(GLOSSY))
L->color_glossy += shader_bsdf_glossy(kg, sd)*throughput;
- if(flag & (PASS_TRANSMISSION_INDIRECT|PASS_TRANSMISSION_COLOR|PASS_TRANSMISSION_DIRECT))
+ if(light_flag & PASSMASK_COMPONENT(TRANSMISSION))
L->color_transmission += shader_bsdf_transmission(kg, sd)*throughput;
- if(flag & (PASS_SUBSURFACE_INDIRECT|PASS_SUBSURFACE_COLOR|PASS_SUBSURFACE_DIRECT))
+ if(light_flag & PASSMASK_COMPONENT(SUBSURFACE))
L->color_subsurface += shader_bsdf_subsurface(kg, sd)*throughput;
- if(flag & PASS_MIST) {
+ if(light_flag & PASSMASK(MIST)) {
/* bring depth into 0..1 range */
float mist_start = kernel_data.film.mist_start;
float mist_inv_depth = kernel_data.film.mist_inv_depth;
@@ -280,49 +281,53 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
ccl_device_inline void kernel_write_light_passes(KernelGlobals *kg, ccl_global float *buffer, PathRadiance *L)
{
#ifdef __PASSES__
- int flag = kernel_data.film.pass_flag;
+ int light_flag = kernel_data.film.light_pass_flag;
if(!kernel_data.film.use_light_pass)
return;
- if(flag & PASS_DIFFUSE_INDIRECT)
+ if(light_flag & PASSMASK(DIFFUSE_INDIRECT))
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_indirect, L->indirect_diffuse);
- if(flag & PASS_GLOSSY_INDIRECT)
+ if(light_flag & PASSMASK(GLOSSY_INDIRECT))
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_indirect, L->indirect_glossy);
- if(flag & PASS_TRANSMISSION_INDIRECT)
+ if(light_flag & PASSMASK(TRANSMISSION_INDIRECT))
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_indirect, L->indirect_transmission);
- if(flag & PASS_SUBSURFACE_INDIRECT)
+ if(light_flag & PASSMASK(SUBSURFACE_INDIRECT))
kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_indirect, L->indirect_subsurface);
- if(flag & PASS_DIFFUSE_DIRECT)
+ if(light_flag & PASSMASK(VOLUME_INDIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_indirect, L->indirect_scatter);
+ if(light_flag & PASSMASK(DIFFUSE_DIRECT))
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_direct, L->direct_diffuse);
- if(flag & PASS_GLOSSY_DIRECT)
+ if(light_flag & PASSMASK(GLOSSY_DIRECT))
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_direct, L->direct_glossy);
- if(flag & PASS_TRANSMISSION_DIRECT)
+ if(light_flag & PASSMASK(TRANSMISSION_DIRECT))
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_direct, L->direct_transmission);
- if(flag & PASS_SUBSURFACE_DIRECT)
+ if(light_flag & PASSMASK(SUBSURFACE_DIRECT))
kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_direct, L->direct_subsurface);
+ if(light_flag & PASSMASK(VOLUME_DIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_direct, L->direct_scatter);
- if(flag & PASS_EMISSION)
+ if(light_flag & PASSMASK(EMISSION))
kernel_write_pass_float3(buffer + kernel_data.film.pass_emission, L->emission);
- if(flag & PASS_BACKGROUND)
+ if(light_flag & PASSMASK(BACKGROUND))
kernel_write_pass_float3(buffer + kernel_data.film.pass_background, L->background);
- if(flag & PASS_AO)
+ if(light_flag & PASSMASK(AO))
kernel_write_pass_float3(buffer + kernel_data.film.pass_ao, L->ao);
- if(flag & PASS_DIFFUSE_COLOR)
+ if(light_flag & PASSMASK(DIFFUSE_COLOR))
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_color, L->color_diffuse);
- if(flag & PASS_GLOSSY_COLOR)
+ if(light_flag & PASSMASK(GLOSSY_COLOR))
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color, L->color_glossy);
- if(flag & PASS_TRANSMISSION_COLOR)
+ if(light_flag & PASSMASK(TRANSMISSION_COLOR))
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, L->color_transmission);
- if(flag & PASS_SUBSURFACE_COLOR)
+ if(light_flag & PASSMASK(SUBSURFACE_COLOR))
kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_color, L->color_subsurface);
- if(flag & PASS_SHADOW) {
+ if(light_flag & PASSMASK(SHADOW)) {
float4 shadow = L->shadow;
shadow.w = kernel_data.film.pass_shadow_scale;
kernel_write_pass_float4(buffer + kernel_data.film.pass_shadow, shadow);
}
- if(flag & PASS_MIST)
+ if(light_flag & PASSMASK(MIST))
kernel_write_pass_float(buffer + kernel_data.film.pass_mist, 1.0f - L->mist);
#endif
}
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index c43cdedac3b..45c9764cc99 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -59,6 +59,11 @@ ccl_device_forceinline bool kernel_path_scene_intersect(
{
uint visibility = path_state_ray_visibility(kg, state);
+ if(path_state_ao_bounce(kg, state)) {
+ visibility = PATH_RAY_SHADOW;
+ ray->t = kernel_data.background.ao_distance;
+ }
+
#ifdef __HAIR__
float difl = 0.0f, extmax = 0.0f;
uint lcg_state = 0;
@@ -74,11 +79,6 @@ ccl_device_forceinline bool kernel_path_scene_intersect(
lcg_state = lcg_state_init_addrspace(state, 0x51633e2d);
}
- if(path_state_ao_bounce(kg, state)) {
- visibility = PATH_RAY_SHADOW;
- ray->t = kernel_data.background.ao_distance;
- }
-
bool hit = scene_intersect(kg, *ray, visibility, isect, &lcg_state, difl, extmax);
#else
bool hit = scene_intersect(kg, *ray, visibility, isect, NULL, 0.0f, 0.0f);
@@ -185,7 +185,7 @@ ccl_device_forceinline bool kernel_path_background_setup(
L->transparent += average(throughput);
#ifdef __PASSES__
- if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
+ if(!(kernel_data.film.light_pass_flag & PASSMASK(BACKGROUND)))
#endif /* __PASSES__ */
return false;
}
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 3c84938a349..eb2d87bd358 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -57,6 +57,7 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
#ifdef __INSTANCING__
sd->object = (isect->object == PRIM_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
#endif
+ sd->lamp = LAMP_NONE;
sd->type = isect->type;
sd->flag = 0;
@@ -265,6 +266,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
#ifdef __INSTANCING__
sd->object = object;
#endif
+ sd->lamp = LAMP_NONE;
/* currently no access to bvh prim index for strand sd->prim*/
sd->prim = prim;
#ifdef __UV__
@@ -286,6 +288,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
else if(lamp != LAMP_NONE) {
sd->ob_tfm = lamp_fetch_transform(kg, lamp, false);
sd->ob_itfm = lamp_fetch_transform(kg, lamp, true);
+ sd->lamp = lamp;
#endif
}
@@ -391,6 +394,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat
#ifdef __INSTANCING__
sd->object = PRIM_NONE;
#endif
+ sd->lamp = LAMP_NONE;
sd->prim = PRIM_NONE;
#ifdef __UV__
sd->u = 0.0f;
@@ -431,6 +435,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s
# ifdef __INSTANCING__
sd->object = PRIM_NONE; /* todo: fill this for texture coordinates */
# endif
+ sd->lamp = LAMP_NONE;
sd->prim = PRIM_NONE;
sd->type = PRIMITIVE_NONE;
@@ -1190,6 +1195,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
/* setup shaderdata from stack. it's mostly setup already in
* shader_setup_from_volume, this switching should be quick */
sd->object = stack[i].object;
+ sd->lamp = LAMP_NONE;
sd->shader = stack[i].shader;
sd->flag &= ~SD_SHADER_FLAGS;
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index e1fdd1340db..0b878f17880 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -368,43 +368,59 @@ typedef enum ClosureLabel {
/* Render Passes */
+#define PASS_NAME_JOIN(a, b) a ## _ ## b
+#define PASSMASK(pass) (1 << ((PASS_NAME_JOIN(PASS, pass)) % 32))
+
+#define PASSMASK_COMPONENT(comp) (PASSMASK(PASS_NAME_JOIN(comp, DIRECT)) | \
+ PASSMASK(PASS_NAME_JOIN(comp, INDIRECT)) | \
+ PASSMASK(PASS_NAME_JOIN(comp, COLOR)))
+
typedef enum PassType {
PASS_NONE = 0,
- PASS_COMBINED = (1 << 0),
- PASS_DEPTH = (1 << 1),
- PASS_NORMAL = (1 << 2),
- PASS_UV = (1 << 3),
- PASS_OBJECT_ID = (1 << 4),
- PASS_MATERIAL_ID = (1 << 5),
- PASS_DIFFUSE_COLOR = (1 << 6),
- PASS_GLOSSY_COLOR = (1 << 7),
- PASS_TRANSMISSION_COLOR = (1 << 8),
- PASS_DIFFUSE_INDIRECT = (1 << 9),
- PASS_GLOSSY_INDIRECT = (1 << 10),
- PASS_TRANSMISSION_INDIRECT = (1 << 11),
- PASS_DIFFUSE_DIRECT = (1 << 12),
- PASS_GLOSSY_DIRECT = (1 << 13),
- PASS_TRANSMISSION_DIRECT = (1 << 14),
- PASS_EMISSION = (1 << 15),
- PASS_BACKGROUND = (1 << 16),
- PASS_AO = (1 << 17),
- PASS_SHADOW = (1 << 18),
- PASS_MOTION = (1 << 19),
- PASS_MOTION_WEIGHT = (1 << 20),
- PASS_MIST = (1 << 21),
- PASS_SUBSURFACE_DIRECT = (1 << 22),
- PASS_SUBSURFACE_INDIRECT = (1 << 23),
- PASS_SUBSURFACE_COLOR = (1 << 24),
- PASS_LIGHT = (1 << 25), /* no real pass, used to force use_light_pass */
+
+ /* Main passes */
+ PASS_COMBINED = 1,
+ PASS_DEPTH,
+ PASS_NORMAL,
+ PASS_UV,
+ PASS_OBJECT_ID,
+ PASS_MATERIAL_ID,
+ PASS_MOTION,
+ PASS_MOTION_WEIGHT,
#ifdef __KERNEL_DEBUG__
- PASS_BVH_TRAVERSED_NODES = (1 << 26),
- PASS_BVH_TRAVERSED_INSTANCES = (1 << 27),
- PASS_BVH_INTERSECTIONS = (1 << 28),
- PASS_RAY_BOUNCES = (1 << 29),
+ PASS_BVH_TRAVERSED_NODES,
+ PASS_BVH_TRAVERSED_INSTANCES,
+ PASS_BVH_INTERSECTIONS,
+ PASS_RAY_BOUNCES,
#endif
+ PASS_RENDER_TIME,
+ PASS_CATEGORY_MAIN_END = 31,
+
+ PASS_MIST = 32,
+ PASS_EMISSION,
+ PASS_BACKGROUND,
+ PASS_AO,
+ PASS_SHADOW,
+ PASS_LIGHT, /* no real pass, used to force use_light_pass */
+ PASS_DIFFUSE_DIRECT,
+ PASS_DIFFUSE_INDIRECT,
+ PASS_DIFFUSE_COLOR,
+ PASS_GLOSSY_DIRECT,
+ PASS_GLOSSY_INDIRECT,
+ PASS_GLOSSY_COLOR,
+ PASS_TRANSMISSION_DIRECT,
+ PASS_TRANSMISSION_INDIRECT,
+ PASS_TRANSMISSION_COLOR,
+ PASS_SUBSURFACE_DIRECT,
+ PASS_SUBSURFACE_INDIRECT,
+ PASS_SUBSURFACE_COLOR,
+ PASS_VOLUME_DIRECT,
+ PASS_VOLUME_INDIRECT,
+ /* No Scatter color since it's tricky to define what it would even mean. */
+ PASS_CATEGORY_LIGHT_END = 63,
} PassType;
-#define PASS_ALL (~0)
+#define PASS_ANY (~0)
typedef enum DenoisingPassOffsets {
DENOISING_PASS_NORMAL = 0,
@@ -509,7 +525,6 @@ typedef ccl_addr_space struct PathRadiance {
float3 color_glossy;
float3 color_transmission;
float3 color_subsurface;
- float3 color_scatter;
float3 direct_diffuse;
float3 direct_glossy;
@@ -966,6 +981,8 @@ typedef ccl_addr_space struct ShaderData {
float v;
/* object id if there is one, ~0 otherwise */
int object;
+ /* lamp id if there is one, ~0 otherwise */
+ int lamp;
/* motion blur sample time */
float time;
@@ -1186,6 +1203,7 @@ static_assert_align(KernelCamera, 16);
typedef struct KernelFilm {
float exposure;
int pass_flag;
+ int light_pass_flag;
int pass_stride;
int use_light_pass;
@@ -1208,11 +1226,13 @@ typedef struct KernelFilm {
int pass_glossy_indirect;
int pass_transmission_indirect;
int pass_subsurface_indirect;
+ int pass_volume_indirect;
int pass_diffuse_direct;
int pass_glossy_direct;
int pass_transmission_direct;
int pass_subsurface_direct;
+ int pass_volume_direct;
int pass_emission;
int pass_background;
@@ -1222,7 +1242,6 @@ typedef struct KernelFilm {
int pass_shadow;
float pass_shadow_scale;
int filter_table_offset;
- int pass_pad2;
int pass_mist;
float mist_start;
@@ -1232,7 +1251,8 @@ typedef struct KernelFilm {
int pass_denoising_data;
int pass_denoising_clean;
int denoising_flags;
- int pad;
+
+ int pad1, pad2, pad3;
#ifdef __KERNEL_DEBUG__
int pass_bvh_traversed_nodes;
diff --git a/intern/cycles/kernel/kernels/cuda/kernel_config.h b/intern/cycles/kernel/kernels/cuda/kernel_config.h
index 7ae205b7e14..94f59ff38d9 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel_config.h
+++ b/intern/cycles/kernel/kernels/cuda/kernel_config.h
@@ -73,9 +73,15 @@
/* tunable parameters */
# define CUDA_THREADS_BLOCK_WIDTH 16
-# define CUDA_KERNEL_MAX_REGISTERS 48
+/* CUDA 9.0 seems to cause slowdowns on high-end Pascal cards unless we increase the number of registers */
+# if __CUDACC_VER_MAJOR__ == 9 && __CUDA_ARCH__ >= 600
+# define CUDA_KERNEL_MAX_REGISTERS 64
+# else
+# define CUDA_KERNEL_MAX_REGISTERS 48
+# endif
# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
+
/* unknown architecture */
#else
# error "Unknown or unsupported CUDA architecture, can't determine launch bounds"
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index e3e85705ebc..597d25e9f30 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -232,7 +232,11 @@ static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, O
/* optimization: it's possible to not use a prepare function at all and
* only initialize the actual class when accessing the closure component
* data, but then we need to map the id to the class somehow */
+#if OSL_LIBRARY_VERSION_CODE >= 10900
+ ss->register_closure(name, id, params, prepare, NULL);
+#else
ss->register_closure(name, id, params, prepare, NULL, 16);
+#endif
}
void OSLShader::register_closures(OSLShadingSystem *ss_)
diff --git a/intern/cycles/kernel/split/kernel_branched.h b/intern/cycles/kernel/split/kernel_branched.h
index 6456636caaa..368a4395760 100644
--- a/intern/cycles/kernel/split/kernel_branched.h
+++ b/intern/cycles/kernel/split/kernel_branched.h
@@ -33,9 +33,9 @@ ccl_device_inline void kernel_split_branched_path_indirect_loop_init(KernelGloba
BRANCHED_STORE(isect);
BRANCHED_STORE(ray_state);
- branched_state->sd = *kernel_split_sd(sd, ray_index);
- for(int i = 0; i < branched_state->sd.num_closure; i++) {
- branched_state->sd.closure[i] = kernel_split_sd(sd, ray_index)->closure[i];
+ *kernel_split_sd(branched_state_sd, ray_index) = *kernel_split_sd(sd, ray_index);
+ for(int i = 0; i < kernel_split_sd(branched_state_sd, ray_index)->num_closure; i++) {
+ kernel_split_sd(branched_state_sd, ray_index)->closure[i] = kernel_split_sd(sd, ray_index)->closure[i];
}
#undef BRANCHED_STORE
@@ -60,9 +60,9 @@ ccl_device_inline void kernel_split_branched_path_indirect_loop_end(KernelGlobal
BRANCHED_RESTORE(isect);
BRANCHED_RESTORE(ray_state);
- *kernel_split_sd(sd, ray_index) = branched_state->sd;
- for(int i = 0; i < branched_state->sd.num_closure; i++) {
- kernel_split_sd(sd, ray_index)->closure[i] = branched_state->sd.closure[i];
+ *kernel_split_sd(sd, ray_index) = *kernel_split_sd(branched_state_sd, ray_index);
+ for(int i = 0; i < kernel_split_sd(branched_state_sd, ray_index)->num_closure; i++) {
+ kernel_split_sd(sd, ray_index)->closure[i] = kernel_split_sd(branched_state_sd, ray_index)->closure[i];
}
#undef BRANCHED_RESTORE
@@ -83,10 +83,17 @@ ccl_device_inline bool kernel_split_branched_indirect_start_shared(KernelGlobals
}
#define SPLIT_DATA_ENTRY(type, name, num) \
- kernel_split_state.name[inactive_ray] = kernel_split_state.name[ray_index];
+ if(num) { \
+ kernel_split_state.name[inactive_ray] = kernel_split_state.name[ray_index]; \
+ }
SPLIT_DATA_ENTRIES_BRANCHED_SHARED
#undef SPLIT_DATA_ENTRY
+ *kernel_split_sd(sd, inactive_ray) = *kernel_split_sd(sd, ray_index);
+ for(int i = 0; i < kernel_split_sd(sd, ray_index)->num_closure; i++) {
+ kernel_split_sd(sd, inactive_ray)->closure[i] = kernel_split_sd(sd, ray_index)->closure[i];
+ }
+
kernel_split_state.branched_state[inactive_ray].shared_sample_count = 0;
kernel_split_state.branched_state[inactive_ray].original_ray = ray_index;
kernel_split_state.branched_state[inactive_ray].waiting_on_shared_samples = false;
diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
index bb6bf1cc7e6..75a0af7567b 100644
--- a/intern/cycles/kernel/split/kernel_next_iteration_setup.h
+++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
@@ -145,7 +145,7 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
if(kernel_split_branched_path_surface_indirect_light_iter(kg,
ray_index,
1.0f,
- &kernel_split_state.branched_state[ray_index].sd,
+ kernel_split_sd(branched_state_sd, ray_index),
true,
true))
{
@@ -190,7 +190,7 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
if(kernel_split_branched_path_surface_indirect_light_iter(kg,
ray_index,
1.0f,
- &kernel_split_state.branched_state[ray_index].sd,
+ kernel_split_sd(branched_state_sd, ray_index),
true,
true))
{
diff --git a/intern/cycles/kernel/split/kernel_split_data.h b/intern/cycles/kernel/split/kernel_split_data.h
index fa2f0b20a83..9297e1e0ad5 100644
--- a/intern/cycles/kernel/split/kernel_split_data.h
+++ b/intern/cycles/kernel/split/kernel_split_data.h
@@ -34,7 +34,7 @@ ccl_device_inline uint64_t split_data_buffer_size(KernelGlobals *kg, size_t num_
uint64_t closure_size = sizeof(ShaderClosure) * (kernel_data.integrator.max_closures-1);
#ifdef __BRANCHED_PATH__
- size += align_up(closure_size * num_elements, 16);
+ size += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16);
#endif
size += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16);
@@ -60,7 +60,8 @@ ccl_device_inline void split_data_init(KernelGlobals *kg,
uint64_t closure_size = sizeof(ShaderClosure) * (kernel_data.integrator.max_closures-1);
#ifdef __BRANCHED_PATH__
- p += align_up(closure_size * num_elements, 16);
+ split_data->_branched_state_sd = (ShaderData*)p;
+ p += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16);
#endif
split_data->_sd = (ShaderData*)p;
diff --git a/intern/cycles/kernel/split/kernel_split_data_types.h b/intern/cycles/kernel/split/kernel_split_data_types.h
index dab0bf72fcf..9970ec1315c 100644
--- a/intern/cycles/kernel/split/kernel_split_data_types.h
+++ b/intern/cycles/kernel/split/kernel_split_data_types.h
@@ -85,13 +85,11 @@ typedef ccl_global struct SplitBranchedState {
int shared_sample_count; /* number of branched samples shared with other threads */
int original_ray; /* index of original ray when sharing branched samples */
bool waiting_on_shared_samples;
-
- /* Must be last in to allow for dynamic size of closures */
- struct ShaderData sd;
} SplitBranchedState;
#define SPLIT_DATA_BRANCHED_ENTRIES \
- SPLIT_DATA_ENTRY( SplitBranchedState, branched_state, 1)
+ SPLIT_DATA_ENTRY( SplitBranchedState, branched_state, 1) \
+ SPLIT_DATA_ENTRY(ShaderData, _branched_state_sd, 0)
#else
#define SPLIT_DATA_BRANCHED_ENTRIES
#endif /* __BRANCHED_PATH__ */
diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h
index 887c3e313d1..5bf7483e9a2 100644
--- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h
+++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h
@@ -37,7 +37,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
{
SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
- ShaderData *sd = &branched_state->sd;
+ ShaderData *sd = kernel_split_sd(branched_state_sd, ray_index);
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
ShaderData *emission_sd = AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]);
diff --git a/intern/cycles/kernel/svm/svm_bevel.h b/intern/cycles/kernel/svm/svm_bevel.h
index 65afe1f74ec..bbbc8dce2cf 100644
--- a/intern/cycles/kernel/svm/svm_bevel.h
+++ b/intern/cycles/kernel/svm/svm_bevel.h
@@ -198,7 +198,7 @@ ccl_device_noinline float3 svm_bevel(
/* Normalize. */
float3 N = safe_normalize(sum_N);
- return is_zero(N) ? sd->N : N;
+ return is_zero(N) ? sd->N : (sd->flag & SD_BACKFACING) ? -N : N;
}
ccl_device void svm_node_bevel(
diff --git a/intern/cycles/kernel/svm/svm_brick.h b/intern/cycles/kernel/svm/svm_brick.h
index 14245cf0522..90fa2a99b67 100644
--- a/intern/cycles/kernel/svm/svm_brick.h
+++ b/intern/cycles/kernel/svm/svm_brick.h
@@ -18,9 +18,9 @@ CCL_NAMESPACE_BEGIN
/* Brick */
-ccl_device_noinline float brick_noise(int n) /* fast integer noise */
+ccl_device_noinline float brick_noise(uint n) /* fast integer noise */
{
- int nn;
+ uint nn;
n = (n + 1013) & 0x7fffffff;
n = (n >> 13) ^ n;
nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index cce4e89e715..9af4a0182d9 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -90,7 +90,15 @@ ccl_device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *s
}
case NODE_INFO_OB_INDEX: data = object_pass_id(kg, sd->object); break;
case NODE_INFO_MAT_INDEX: data = shader_pass_id(kg, sd); break;
- case NODE_INFO_OB_RANDOM: data = object_random_number(kg, sd->object); break;
+ case NODE_INFO_OB_RANDOM: {
+ if(sd->lamp != LAMP_NONE) {
+ data = lamp_random_number(kg, sd->lamp);
+ }
+ else {
+ data = object_random_number(kg, sd->object);
+ }
+ break;
+ }
default: data = 0.0f; break;
}
diff --git a/intern/cycles/kernel/svm/svm_gradient.h b/intern/cycles/kernel/svm/svm_gradient.h
index 53d7b4f812c..74e36e70427 100644
--- a/intern/cycles/kernel/svm/svm_gradient.h
+++ b/intern/cycles/kernel/svm/svm_gradient.h
@@ -46,7 +46,10 @@ ccl_device float svm_gradient(float3 p, NodeGradientType type)
return atan2f(y, x) / M_2PI_F + 0.5f;
}
else {
- float r = fmaxf(1.0f - sqrtf(x*x + y*y + z*z), 0.0f);
+ /* Bias a little bit for the case where p is a unit length vector,
+ * to get exactly zero instead of a small random value depending
+ * on float precision. */
+ float r = fmaxf(0.999999f - sqrtf(x*x + y*y + z*z), 0.0f);
if(type == NODE_BLEND_QUADRATIC_SPHERE)
return r*r;
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index f08ec76c055..c7fe7948422 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -465,13 +465,16 @@ typedef enum ClosureType {
#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID)
#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSLUCENT_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
#define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID || type == CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID)
+#define CLOSURE_IS_BSDF_SINGULAR(type) (type == CLOSURE_BSDF_REFLECTION_ID || \
+ type == CLOSURE_BSDF_REFRACTION_ID || \
+ type == CLOSURE_BSDF_TRANSPARENT_ID)
#define CLOSURE_IS_BSDF_TRANSPARENT(type) (type == CLOSURE_BSDF_TRANSPARENT_ID)
-#define CLOSURE_IS_BSDF_ANISOTROPIC(type) (type >= CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID)
#define CLOSURE_IS_BSDF_MULTISCATTER(type) (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID ||\
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID || \
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
-#define CLOSURE_IS_BSDF_MICROFACET(type) ((type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID) ||\
- (type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID))
+#define CLOSURE_IS_BSDF_MICROFACET(type) ((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID) ||\
+ (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) ||\
+ (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID))
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_BURLEY_ID)
#define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_BURLEY_ID)
#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index ac675dc7b39..5c7729ec89f 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -116,7 +116,7 @@ RenderTile::RenderTile()
RenderBuffers::RenderBuffers(Device *device)
: buffer(device, "RenderBuffers", MEM_READ_WRITE),
- map_neighbor_copied(false)
+ map_neighbor_copied(false), render_time(0.0f)
{
}
@@ -236,10 +236,17 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int
int size = params.width*params.height;
- if(components == 1) {
+ if(components == 1 && type == PASS_RENDER_TIME) {
+ /* Render time is not stored by kernel, but measured per tile. */
+ float val = (float) (1000.0 * render_time/(params.width * params.height * sample));
+ for(int i = 0; i < size; i++, pixels++) {
+ pixels[0] = val;
+ }
+ }
+ else if(components == 1) {
assert(pass.components == components);
- /* scalar */
+ /* Scalar */
if(type == PASS_DEPTH) {
for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
float f = *in;
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 9fa0cdd4e27..028bfb83735 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -75,6 +75,7 @@ public:
/* float buffer */
device_vector<float> buffer;
bool map_neighbor_copied;
+ double render_time;
explicit RenderBuffers(Device *device);
~RenderBuffers();
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index c8213d258d5..6c8c929c2f9 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -85,83 +85,81 @@ void Pass::add(PassType type, array<Pass>& passes)
pass.components = 1;
pass.filter = false;
break;
- case PASS_DIFFUSE_COLOR:
- case PASS_GLOSSY_COLOR:
- case PASS_TRANSMISSION_COLOR:
- case PASS_SUBSURFACE_COLOR:
- pass.components = 4;
- break;
- case PASS_DIFFUSE_INDIRECT:
+
+ case PASS_EMISSION:
+ case PASS_BACKGROUND:
pass.components = 4;
pass.exposure = true;
- pass.divide_type = PASS_DIFFUSE_COLOR;
break;
- case PASS_GLOSSY_INDIRECT:
+ case PASS_AO:
pass.components = 4;
- pass.exposure = true;
- pass.divide_type = PASS_GLOSSY_COLOR;
break;
- case PASS_TRANSMISSION_INDIRECT:
+ case PASS_SHADOW:
pass.components = 4;
- pass.exposure = true;
- pass.divide_type = PASS_TRANSMISSION_COLOR;
+ pass.exposure = false;
break;
- case PASS_SUBSURFACE_INDIRECT:
+ case PASS_LIGHT:
+ /* This isn't a real pass, used by baking to see whether
+ * light data is needed or not.
+ *
+ * Set components to 0 so pass sort below happens in a
+ * determined way.
+ */
+ pass.components = 0;
+ break;
+#ifdef WITH_CYCLES_DEBUG
+ case PASS_BVH_TRAVERSED_NODES:
+ case PASS_BVH_TRAVERSED_INSTANCES:
+ case PASS_BVH_INTERSECTIONS:
+ case PASS_RAY_BOUNCES:
+ pass.components = 1;
+ pass.exposure = false;
+ break;
+#endif
+ case PASS_RENDER_TIME:
+ /* This pass is handled entirely on the host side. */
+ pass.components = 0;
+ break;
+
+ case PASS_DIFFUSE_COLOR:
+ case PASS_GLOSSY_COLOR:
+ case PASS_TRANSMISSION_COLOR:
+ case PASS_SUBSURFACE_COLOR:
pass.components = 4;
- pass.exposure = true;
- pass.divide_type = PASS_SUBSURFACE_COLOR;
break;
case PASS_DIFFUSE_DIRECT:
+ case PASS_DIFFUSE_INDIRECT:
pass.components = 4;
pass.exposure = true;
pass.divide_type = PASS_DIFFUSE_COLOR;
break;
case PASS_GLOSSY_DIRECT:
+ case PASS_GLOSSY_INDIRECT:
pass.components = 4;
pass.exposure = true;
pass.divide_type = PASS_GLOSSY_COLOR;
break;
case PASS_TRANSMISSION_DIRECT:
+ case PASS_TRANSMISSION_INDIRECT:
pass.components = 4;
pass.exposure = true;
pass.divide_type = PASS_TRANSMISSION_COLOR;
break;
case PASS_SUBSURFACE_DIRECT:
+ case PASS_SUBSURFACE_INDIRECT:
pass.components = 4;
pass.exposure = true;
pass.divide_type = PASS_SUBSURFACE_COLOR;
break;
-
- case PASS_EMISSION:
- case PASS_BACKGROUND:
+ case PASS_VOLUME_DIRECT:
+ case PASS_VOLUME_INDIRECT:
pass.components = 4;
pass.exposure = true;
break;
- case PASS_AO:
- pass.components = 4;
- break;
- case PASS_SHADOW:
- pass.components = 4;
- pass.exposure = false;
- break;
- case PASS_LIGHT:
- /* This isn't a real pass, used by baking to see whether
- * light data is needed or not.
- *
- * Set components to 0 so pass sort below happens in a
- * determined way.
- */
- pass.components = 0;
- break;
-#ifdef WITH_CYCLES_DEBUG
- case PASS_BVH_TRAVERSED_NODES:
- case PASS_BVH_TRAVERSED_INSTANCES:
- case PASS_BVH_INTERSECTIONS:
- case PASS_RAY_BOUNCES:
- pass.components = 1;
- pass.exposure = false;
+
+ default:
+ assert(false);
break;
-#endif
}
passes.push_back_slow(pass);
@@ -318,7 +316,19 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
for(size_t i = 0; i < passes.size(); i++) {
Pass& pass = passes[i];
- kfilm->pass_flag |= pass.type;
+
+ if(pass.type == PASS_NONE)
+ continue;
+
+ int pass_flag = (1 << (pass.type % 32));
+ if(pass.type <= PASS_CATEGORY_MAIN_END) {
+ kfilm->pass_flag |= pass_flag;
+ }
+ else {
+ assert(pass.type <= PASS_CATEGORY_LIGHT_END);
+ kfilm->use_light_pass = 1;
+ kfilm->light_pass_flag |= pass_flag;
+ }
switch(pass.type) {
case PASS_COMBINED:
@@ -327,10 +337,6 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
case PASS_DEPTH:
kfilm->pass_depth = kfilm->pass_stride;
break;
- case PASS_MIST:
- kfilm->pass_mist = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
- break;
case PASS_NORMAL:
kfilm->pass_normal = kfilm->pass_stride;
break;
@@ -349,74 +355,67 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
case PASS_MATERIAL_ID:
kfilm->pass_material_id = kfilm->pass_stride;
break;
+
+ case PASS_MIST:
+ kfilm->pass_mist = kfilm->pass_stride;
+ break;
+ case PASS_EMISSION:
+ kfilm->pass_emission = kfilm->pass_stride;
+ break;
+ case PASS_BACKGROUND:
+ kfilm->pass_background = kfilm->pass_stride;
+ break;
+ case PASS_AO:
+ kfilm->pass_ao = kfilm->pass_stride;
+ break;
+ case PASS_SHADOW:
+ kfilm->pass_shadow = kfilm->pass_stride;
+ break;
+
+ case PASS_LIGHT:
+ break;
+
case PASS_DIFFUSE_COLOR:
kfilm->pass_diffuse_color = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
break;
case PASS_GLOSSY_COLOR:
kfilm->pass_glossy_color = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
break;
case PASS_TRANSMISSION_COLOR:
kfilm->pass_transmission_color = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
break;
case PASS_SUBSURFACE_COLOR:
kfilm->pass_subsurface_color = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
break;
case PASS_DIFFUSE_INDIRECT:
kfilm->pass_diffuse_indirect = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
break;
case PASS_GLOSSY_INDIRECT:
kfilm->pass_glossy_indirect = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
break;
case PASS_TRANSMISSION_INDIRECT:
kfilm->pass_transmission_indirect = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
break;
case PASS_SUBSURFACE_INDIRECT:
kfilm->pass_subsurface_indirect = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
+ break;
+ case PASS_VOLUME_INDIRECT:
+ kfilm->pass_volume_indirect = kfilm->pass_stride;
break;
case PASS_DIFFUSE_DIRECT:
kfilm->pass_diffuse_direct = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
break;
case PASS_GLOSSY_DIRECT:
kfilm->pass_glossy_direct = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
break;
case PASS_TRANSMISSION_DIRECT:
kfilm->pass_transmission_direct = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
break;
case PASS_SUBSURFACE_DIRECT:
kfilm->pass_subsurface_direct = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
break;
-
- case PASS_EMISSION:
- kfilm->pass_emission = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
- break;
- case PASS_BACKGROUND:
- kfilm->pass_background = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
- break;
- case PASS_AO:
- kfilm->pass_ao = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
- break;
- case PASS_SHADOW:
- kfilm->pass_shadow = kfilm->pass_stride;
- kfilm->use_light_pass = 1;
- break;
-
- case PASS_LIGHT:
- kfilm->use_light_pass = 1;
+ case PASS_VOLUME_DIRECT:
+ kfilm->pass_volume_direct = kfilm->pass_stride;
break;
#ifdef WITH_CYCLES_DEBUG
@@ -433,8 +432,11 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kfilm->pass_ray_bounces = kfilm->pass_stride;
break;
#endif
+ case PASS_RENDER_TIME:
+ break;
- case PASS_NONE:
+ default:
+ assert(false);
break;
}
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 9358b40a689..482442cce29 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -723,6 +723,7 @@ void ImageManager::device_load_image(Device *device,
*tex_img))
{
/* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
float *pixels = (float*)tex_img->alloc(1, 1);
pixels[0] = TEX_IMAGE_MISSING_R;
@@ -748,6 +749,7 @@ void ImageManager::device_load_image(Device *device,
*tex_img))
{
/* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
float *pixels = (float*)tex_img->alloc(1, 1);
pixels[0] = TEX_IMAGE_MISSING_R;
@@ -770,6 +772,7 @@ void ImageManager::device_load_image(Device *device,
*tex_img))
{
/* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
uchar *pixels = (uchar*)tex_img->alloc(1, 1);
pixels[0] = (TEX_IMAGE_MISSING_R * 255);
@@ -794,6 +797,7 @@ void ImageManager::device_load_image(Device *device,
texture_limit,
*tex_img)) {
/* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
uchar *pixels = (uchar*)tex_img->alloc(1, 1);
pixels[0] = (TEX_IMAGE_MISSING_R * 255);
@@ -815,6 +819,7 @@ void ImageManager::device_load_image(Device *device,
texture_limit,
*tex_img)) {
/* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
half *pixels = (half*)tex_img->alloc(1, 1);
pixels[0] = TEX_IMAGE_MISSING_R;
@@ -839,6 +844,7 @@ void ImageManager::device_load_image(Device *device,
texture_limit,
*tex_img)) {
/* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
half *pixels = (half*)tex_img->alloc(1, 1);
pixels[0] = TEX_IMAGE_MISSING_R;
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index b37a0768b53..b62453cf5fc 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -134,6 +134,7 @@ NODE_DEFINE(Light)
SOCKET_INT(samples, "Samples", 1);
SOCKET_INT(max_bounces, "Max Bounces", 1024);
+ SOCKET_UINT(random_id, "Random ID", 0);
SOCKET_BOOLEAN(is_portal, "Is Portal", false);
SOCKET_BOOLEAN(is_enabled, "Is Enabled", true);
@@ -638,6 +639,7 @@ void LightManager::device_update_points(Device *,
int shader_id = scene->shader_manager->get_shader_id(shader);
float samples = __int_as_float(light->samples);
float max_bounces = __int_as_float(light->max_bounces);
+ float random = (float)light->random_id * (1.0f/(float)0xFFFFFFFF);
if(!light->cast_shadow)
shader_id &= ~SHADER_CAST_SHADOW;
@@ -758,7 +760,7 @@ void LightManager::device_update_points(Device *,
light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
}
- light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, random, 0.0f, 0.0f);
Transform tfm = light->tfm;
Transform itfm = transform_inverse(tfm);
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index 7e9014eb823..97b7b971c73 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -70,6 +70,7 @@ public:
Shader *shader;
int samples;
int max_bounces;
+ uint random_id;
void tag_update(Scene *scene);
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index fb04d49bcd9..39ce6a93982 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -518,6 +518,11 @@ ccl_device float safe_modulo(float a, float b)
return (b != 0.0f)? fmodf(a, b): 0.0f;
}
+ccl_device_inline float sqr(float a)
+{
+ return a * a;
+}
+
ccl_device_inline float beta(float x, float y)
{
#ifndef __KERNEL_OPENCL__
diff --git a/intern/cycles/util/util_xml.h b/intern/cycles/util/util_xml.h
index e1a28df9433..6f06f17937b 100644
--- a/intern/cycles/util/util_xml.h
+++ b/intern/cycles/util/util_xml.h
@@ -23,10 +23,19 @@
CCL_NAMESPACE_BEGIN
-using OIIO_NAMESPACE::pugi::xml_node;
-using OIIO_NAMESPACE::pugi::xml_attribute;
+OIIO_NAMESPACE_USING
+
+#ifdef WITH_SYSTEM_PUGIXML
+# define PUGIXML_NAMESPACE pugi
+#else
+# define PUGIXML_NAMESPACE OIIO_NAMESPACE::pugi
+#endif
+
+using PUGIXML_NAMESPACE::xml_attribute;
+using PUGIXML_NAMESPACE::xml_document;
+using PUGIXML_NAMESPACE::xml_node;
+using PUGIXML_NAMESPACE::xml_parse_result;
CCL_NAMESPACE_END
#endif /* __UTIL_XML_H__ */
-
diff --git a/intern/eigen/intern/eigenvalues.cc b/intern/eigen/intern/eigenvalues.cc
index 57942a4dc55..b516443c421 100644
--- a/intern/eigen/intern/eigenvalues.cc
+++ b/intern/eigen/intern/eigenvalues.cc
@@ -28,7 +28,7 @@
#define __EIGEN3_EIGENVALUES_C_API_CC__
/* Eigen gives annoying huge amount of warnings here, silence them! */
-#ifdef __GNUC__
+#if defined(__GNUC__) && !defined(__clang__)
# pragma GCC diagnostic ignored "-Wlogical-op"
#endif
diff --git a/intern/eigen/intern/svd.cc b/intern/eigen/intern/svd.cc
index 04929cff798..7c331d25aa7 100644
--- a/intern/eigen/intern/svd.cc
+++ b/intern/eigen/intern/svd.cc
@@ -28,7 +28,7 @@
#define __EIGEN3_SVD_C_API_CC__
/* Eigen gives annoying huge amount of warnings here, silence them! */
-#ifdef __GNUC__
+#if defined(__GNUC__) && !defined(__clang__)
# pragma GCC diagnostic ignored "-Wlogical-op"
#endif
diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c
index f832b356ffe..ebf699c2428 100644
--- a/intern/mikktspace/mikktspace.c
+++ b/intern/mikktspace/mikktspace.c
@@ -447,305 +447,132 @@ typedef struct {
int index;
} STmpVert;
-static const int g_iCells = 2048;
-static const float g_iCells_fl = 2048.0f;
+static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
-#ifdef _MSC_VER
-# define NOINLINE __declspec(noinline)
-#else
-# define NOINLINE __attribute__ ((noinline))
-#endif
+typedef unsigned int uint;
-// it is IMPORTANT that this function is called to evaluate the hash since
-// inlining could potentially reorder instructions and generate different
-// results for the same effective input value fVal.
-static NOINLINE int FindGridCell(const float fMin, const float fMax, const float fVal)
+static uint float_as_uint(const float v)
{
- const float fIndex = g_iCells_fl * ((fVal-fMin)/(fMax-fMin));
- const int iIndex = (int)fIndex;
- return iIndex < g_iCells ? (iIndex >= 0 ? iIndex : 0) : (g_iCells - 1);
+ return *((uint*)(&v));
}
-static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in);
-static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries);
-static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
+#define HASH(x, y, z) (((x) * 73856093) ^ ((y) * 19349663) ^ ((z) * 83492791))
+#define HASH_F(x, y, z) HASH(float_as_uint(x), float_as_uint(y), float_as_uint(z))
-static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
+/* Sort comp and data based on comp.
+ * comp2 and data2 are used as temporary storage. */
+static void radixsort_pair(uint *comp, int *data, uint *comp2, int *data2, int n)
{
+ int shift = 0;
+ for(int pass = 0; pass < 4; pass++, shift+=8) {
+ int bins[257] = {0};
+ /* Count number of elements per bin. */
+ for(int i = 0; i < n; i++) {
+ bins[((comp[i] >> shift) & 0xff) + 1]++;
+ }
+ /* Compute prefix sum to find position of each bin in the sorted array. */
+ for(int i = 2; i < 256; i++) {
+ bins[i] += bins[i-1];
+ }
+ /* Insert the elements in their correct location based on their bin. */
+ for(int i = 0; i < n; i++) {
+ int pos = bins[(comp[i] >> shift) & 0xff]++;
+ comp2[pos] = comp[i];
+ data2[pos] = data[i];
+ }
- // Generate bounding box
- int * piHashTable=NULL, * piHashCount=NULL, * piHashOffsets=NULL, * piHashCount2=NULL;
- STmpVert * pTmpVert = NULL;
- int i=0, iChannel=0, k=0, e=0;
- int iMaxCount=0;
- SVec3 vMin = GetPosition(pContext, 0), vMax = vMin, vDim;
- float fMin, fMax;
- for (i=1; i<(iNrTrianglesIn*3); i++)
- {
- const int index = piTriList_in_and_out[i];
-
- const SVec3 vP = GetPosition(pContext, index);
- if (vMin.x > vP.x) vMin.x = vP.x;
- else if (vMax.x < vP.x) vMax.x = vP.x;
- if (vMin.y > vP.y) vMin.y = vP.y;
- else if (vMax.y < vP.y) vMax.y = vP.y;
- if (vMin.z > vP.z) vMin.z = vP.z;
- else if (vMax.z < vP.z) vMax.z = vP.z;
+ /* Swap arrays. */
+ int *tmpdata = data; data = data2; data2 = tmpdata;
+ uint *tmpcomp = comp; comp = comp2; comp2 = tmpcomp;
}
+}
- vDim = vsub(vMax,vMin);
- iChannel = 0;
- fMin = vMin.x; fMax=vMax.x;
- if (vDim.y>vDim.x && vDim.y>vDim.z)
- {
- iChannel=1;
- fMin = vMin.y;
- fMax = vMax.y;
- }
- else if (vDim.z>vDim.x)
- {
- iChannel=2;
- fMin = vMin.z;
- fMax = vMax.z;
- }
+/* Merge identical vertices.
+ * To find vertices with identical position, normal and texcoord, we calculate a hash of the 9 values.
+ * Then, by sorting based on that hash, identical elements (having identical hashes) will be moved next to each other.
+ * Since there might be hash collisions, the elements of each block are then compared with each other and duplicates
+ * are merged.
+ */
+static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
+{
+ int numVertices = iNrTrianglesIn*3;
- // make allocations
- piHashTable = (int *) malloc(sizeof(int[3])*iNrTrianglesIn);
- piHashCount = (int *) malloc(sizeof(int)*g_iCells);
- piHashOffsets = (int *) malloc(sizeof(int)*g_iCells);
- piHashCount2 = (int *) malloc(sizeof(int)*g_iCells);
+ uint *hashes = (uint*) malloc(sizeof(uint)*numVertices);
+ int *indices = (int*) malloc(sizeof(int)*numVertices);
+ uint *temp_hashes = (uint*) malloc(sizeof(uint)*numVertices);
+ int *temp_indices = (int*) malloc(sizeof(int)*numVertices);
+
+ if(hashes == NULL || indices == NULL || temp_hashes == NULL || temp_indices == NULL) {
+ free(hashes);
+ free(indices);
+ free(temp_hashes);
+ free(temp_indices);
- if (piHashTable==NULL || piHashCount==NULL || piHashOffsets==NULL || piHashCount2==NULL)
- {
- if (piHashTable!=NULL) free(piHashTable);
- if (piHashCount!=NULL) free(piHashCount);
- if (piHashOffsets!=NULL) free(piHashOffsets);
- if (piHashCount2!=NULL) free(piHashCount2);
GenerateSharedVerticesIndexListSlow(piTriList_in_and_out, pContext, iNrTrianglesIn);
return;
}
- memset(piHashCount, 0, sizeof(int)*g_iCells);
- memset(piHashCount2, 0, sizeof(int)*g_iCells);
- // count amount of elements in each cell unit
- for (i=0; i<(iNrTrianglesIn*3); i++)
- {
+ for (int i = 0; i < numVertices; i++) {
const int index = piTriList_in_and_out[i];
- const SVec3 vP = GetPosition(pContext, index);
- const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z);
- const int iCell = FindGridCell(fMin, fMax, fVal);
- ++piHashCount[iCell];
- }
- // evaluate start index of each cell.
- piHashOffsets[0]=0;
- for (k=1; k<g_iCells; k++)
- piHashOffsets[k]=piHashOffsets[k-1]+piHashCount[k-1];
-
- // insert vertices
- for (i=0; i<(iNrTrianglesIn*3); i++)
- {
- const int index = piTriList_in_and_out[i];
const SVec3 vP = GetPosition(pContext, index);
- const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z);
- const int iCell = FindGridCell(fMin, fMax, fVal);
- int * pTable = NULL;
-
- assert(piHashCount2[iCell]<piHashCount[iCell]);
- pTable = &piHashTable[piHashOffsets[iCell]];
- pTable[piHashCount2[iCell]] = i; // vertex i has been inserted.
- ++piHashCount2[iCell];
- }
- for (k=0; k<g_iCells; k++)
- assert(piHashCount2[k] == piHashCount[k]); // verify the count
- free(piHashCount2);
-
- // find maximum amount of entries in any hash entry
- iMaxCount = piHashCount[0];
- for (k=1; k<g_iCells; k++)
- if (iMaxCount<piHashCount[k])
- iMaxCount=piHashCount[k];
- pTmpVert = (STmpVert *) malloc(sizeof(STmpVert)*iMaxCount);
+ const uint hashP = HASH_F(vP.x, vP.y, vP.z);
+ const SVec3 vN = GetNormal(pContext, index);
+ const uint hashN = HASH_F(vN.x, vN.y, vN.z);
- // complete the merge
- for (k=0; k<g_iCells; k++)
- {
- // extract table of cell k and amount of entries in it
- int * pTable = &piHashTable[piHashOffsets[k]];
- const int iEntries = piHashCount[k];
- if (iEntries < 2) continue;
+ const SVec3 vT = GetTexCoord(pContext, index);
+ const uint hashT = HASH_F(vT.x, vT.y, vT.z);
- if (pTmpVert!=NULL)
- {
- for (e=0; e<iEntries; e++)
- {
- int i = pTable[e];
- const SVec3 vP = GetPosition(pContext, piTriList_in_and_out[i]);
- pTmpVert[e].vert[0] = vP.x; pTmpVert[e].vert[1] = vP.y;
- pTmpVert[e].vert[2] = vP.z; pTmpVert[e].index = i;
- }
- MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, 0, iEntries-1);
- }
- else
- MergeVertsSlow(piTriList_in_and_out, pContext, pTable, iEntries);
+ hashes[i] = HASH(hashP, hashN, hashT);
+ indices[i] = i;
}
- if (pTmpVert!=NULL) { free(pTmpVert); }
- free(piHashTable);
- free(piHashCount);
- free(piHashOffsets);
-}
-
-static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in)
-{
- // make bbox
- int c=0, l=0, channel=0;
- float fvMin[3], fvMax[3];
- float dx=0, dy=0, dz=0, fSep=0;
- for (c=0; c<3; c++)
- { fvMin[c]=pTmpVert[iL_in].vert[c]; fvMax[c]=fvMin[c]; }
- for (l=(iL_in+1); l<=iR_in; l++) {
- for (c=0; c<3; c++) {
- if (fvMin[c]>pTmpVert[l].vert[c]) fvMin[c]=pTmpVert[l].vert[c];
- if (fvMax[c]<pTmpVert[l].vert[c]) fvMax[c]=pTmpVert[l].vert[c];
+ radixsort_pair(hashes, indices, temp_hashes, temp_indices, numVertices);
+
+ free(temp_hashes);
+ free(temp_indices);
+
+ /* Process blocks of vertices with the same hash.
+ * Vertices in the block might still be separate, but we know for sure that
+ * vertices in different blocks will never be identical. */
+ int blockstart = 0;
+ while (blockstart < numVertices) {
+ /* Find end of this block (exclusive). */
+ uint hash = hashes[blockstart];
+ int blockend = blockstart+1;
+ for(; blockend < numVertices; blockend++) {
+ if(hashes[blockend] != hash) break;
}
- }
-
- dx = fvMax[0]-fvMin[0];
- dy = fvMax[1]-fvMin[1];
- dz = fvMax[2]-fvMin[2];
-
- channel = 0;
- if (dy>dx && dy>dz) channel=1;
- else if (dz>dx) channel=2;
-
- fSep = 0.5f*(fvMax[channel]+fvMin[channel]);
- // stop if all vertices are NaNs
- if (!isfinite(fSep))
- return;
-
- // terminate recursion when the separation/average value
- // is no longer strictly between fMin and fMax values.
- if (fSep>=fvMax[channel] || fSep<=fvMin[channel])
- {
- // complete the weld
- for (l=iL_in; l<=iR_in; l++)
- {
- int i = pTmpVert[l].index;
- const int index = piTriList_in_and_out[i];
- const SVec3 vP = GetPosition(pContext, index);
- const SVec3 vN = GetNormal(pContext, index);
- const SVec3 vT = GetTexCoord(pContext, index);
-
- tbool bNotFound = TTRUE;
- int l2=iL_in, i2rec=-1;
- while (l2<l && bNotFound)
- {
- const int i2 = pTmpVert[l2].index;
- const int index2 = piTriList_in_and_out[i2];
- const SVec3 vP2 = GetPosition(pContext, index2);
- const SVec3 vN2 = GetNormal(pContext, index2);
- const SVec3 vT2 = GetTexCoord(pContext, index2);
- i2rec=i2;
-
- //if (vP==vP2 && vN==vN2 && vT==vT2)
- if (vP.x==vP2.x && vP.y==vP2.y && vP.z==vP2.z &&
- vN.x==vN2.x && vN.y==vN2.y && vN.z==vN2.z &&
- vT.x==vT2.x && vT.y==vT2.y && vT.z==vT2.z)
- bNotFound = TFALSE;
- else
- ++l2;
- }
-
- // merge if previously found
- if (!bNotFound)
- piTriList_in_and_out[i] = piTriList_in_and_out[i2rec];
- }
- }
- else
- {
- int iL=iL_in, iR=iR_in;
- assert((iR_in-iL_in)>0); // at least 2 entries
-
- // separate (by fSep) all points between iL_in and iR_in in pTmpVert[]
- while (iL < iR)
- {
- tbool bReadyLeftSwap = TFALSE, bReadyRightSwap = TFALSE;
- while ((!bReadyLeftSwap) && iL<iR)
- {
- assert(iL>=iL_in && iL<=iR_in);
- bReadyLeftSwap = !(pTmpVert[iL].vert[channel]<fSep);
- if (!bReadyLeftSwap) ++iL;
- }
- while ((!bReadyRightSwap) && iL<iR)
- {
- assert(iR>=iL_in && iR<=iR_in);
- bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep;
- if (!bReadyRightSwap) --iR;
- }
- assert( (iL<iR) || !(bReadyLeftSwap && bReadyRightSwap) );
-
- if (bReadyLeftSwap && bReadyRightSwap)
- {
- const STmpVert sTmp = pTmpVert[iL];
- assert(iL<iR);
- pTmpVert[iL] = pTmpVert[iR];
- pTmpVert[iR] = sTmp;
- ++iL; --iR;
+ for(int i = blockstart; i < blockend; i++) {
+ int index1 = piTriList_in_and_out[indices[i]];
+ const SVec3 vP = GetPosition(pContext, index1);
+ const SVec3 vN = GetNormal(pContext, index1);
+ const SVec3 vT = GetTexCoord(pContext, index1);
+ for(int i2 = i+1; i2 < blockend; i2++) {
+ int index2 = piTriList_in_and_out[indices[i2]];
+ if(index1 == index2) continue;
+
+ if(veq(vP, GetPosition(pContext, index2)) &&
+ veq(vN, GetNormal(pContext, index2)) &&
+ veq(vT, GetTexCoord(pContext, index2)))
+ {
+ piTriList_in_and_out[indices[i2]] = index1;
+ /* Once i2>i has been identified as a duplicate, we can stop since any
+ * i3>i2>i that is a duplicate of i (and therefore also i2) will also be
+ * compared to i2 and therefore be identified there anyways. */
+ break;
+ }
}
}
- assert(iL==(iR+1) || (iL==iR));
- if (iL==iR)
- {
- const tbool bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep;
- if (bReadyRightSwap) ++iL;
- else --iR;
- }
-
- // only need to weld when there is more than 1 instance of the (x,y,z)
- if (iL_in < iR)
- MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL_in, iR); // weld all left of fSep
- if (iL < iR_in)
- MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL, iR_in); // weld all right of (or equal to) fSep
+ /* Advance to next block. */
+ blockstart = blockend;
}
-}
-
-static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries)
-{
- // this can be optimized further using a tree structure or more hashing.
- int e=0;
- for (e=0; e<iEntries; e++)
- {
- int i = pTable[e];
- const int index = piTriList_in_and_out[i];
- const SVec3 vP = GetPosition(pContext, index);
- const SVec3 vN = GetNormal(pContext, index);
- const SVec3 vT = GetTexCoord(pContext, index);
- tbool bNotFound = TTRUE;
- int e2=0, i2rec=-1;
- while (e2<e && bNotFound)
- {
- const int i2 = pTable[e2];
- const int index2 = piTriList_in_and_out[i2];
- const SVec3 vP2 = GetPosition(pContext, index2);
- const SVec3 vN2 = GetNormal(pContext, index2);
- const SVec3 vT2 = GetTexCoord(pContext, index2);
- i2rec = i2;
-
- if (veq(vP,vP2) && veq(vN,vN2) && veq(vT,vT2))
- bNotFound = TFALSE;
- else
- ++e2;
- }
-
- // merge if previously found
- if (!bNotFound)
- piTriList_in_and_out[i] = piTriList_in_and_out[i2rec];
- }
+ free(hashes);
+ free(indices);
}
static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
diff --git a/intern/smoke/intern/IMAGE.h b/intern/smoke/intern/IMAGE.h
index a606fcddf72..79f71c6402a 100644
--- a/intern/smoke/intern/IMAGE.h
+++ b/intern/smoke/intern/IMAGE.h
@@ -48,27 +48,27 @@ template < class T > inline void CLAMP( T &a, T b=0., T c=1.) {
if(a>c) { a=c; return; }
}
-template < class T > inline T MIN( T a, T b) {
+template < class T > inline T MIN( const T& a, const T& b) {
return (a < b) ? a : b;
}
-template < class T > inline T MAX( T a, T b) {
+template < class T > inline T MAX( const T& a, const T& b) {
return (a > b) ? a : b;
}
-template < class T > inline T MAX3( T a, T b, T c) {
+template < class T > inline T MAX3( const T& a, const T& b, const T& c) {
T max = (a > b) ? a : b;
max = (max > c) ? max : c;
return max;
}
-template < class T > inline float MAX3V( T vec) {
+template < class T > inline float MAX3V( const T& vec) {
float max = (vec[0] > vec[1]) ? vec[0] : vec[1];
max = (max > vec[2]) ? max : vec[2];
return max;
}
-template < class T > inline float MIN3V( T vec) {
+template < class T > inline float MIN3V( const T& vec) {
float min = (vec[0] < vec[1]) ? vec[0] : vec[1];
min = (min < vec[2]) ? min : vec[2];
return min;
diff --git a/intern/smoke/intern/WTURBULENCE.cpp b/intern/smoke/intern/WTURBULENCE.cpp
index 3d712d2124a..61389201796 100644
--- a/intern/smoke/intern/WTURBULENCE.cpp
+++ b/intern/smoke/intern/WTURBULENCE.cpp
@@ -245,7 +245,7 @@ void WTURBULENCE::initBlenderRNA(float *strength)
// Takes the one-sided finite difference in both directions and
// selects the smaller of the two
//////////////////////////////////////////////////////////////////////
-static float minDx(int x, int y, int z, float* input, Vec3Int res)
+static float minDx(int x, int y, int z, float* input, const Vec3Int& res)
{
const int index = x + y * res[0] + z * res[0] * res[1];
const int maxx = res[0]-2;
@@ -280,7 +280,7 @@ static float minDx(int x, int y, int z, float* input, Vec3Int res)
// Takes the one-sided finite difference in both directions and
// selects the smaller of the two
//////////////////////////////////////////////////////////////////////
-static float minDy(int x, int y, int z, float* input, Vec3Int res)
+static float minDy(int x, int y, int z, float* input, const Vec3Int& res)
{
const int index = x + y * res[0] + z * res[0] * res[1];
const int maxy = res[1]-2;
@@ -314,7 +314,7 @@ static float minDy(int x, int y, int z, float* input, Vec3Int res)
// Takes the one-sided finite difference in both directions and
// selects the smaller of the two
//////////////////////////////////////////////////////////////////////
-static float minDz(int x, int y, int z, float* input, Vec3Int res)
+static float minDz(int x, int y, int z, float* input, const Vec3Int& res)
{
const int slab = res[0]*res[1];
const int index = x + y * res[0] + z * slab;
@@ -605,7 +605,7 @@ Vec3 WTURBULENCE::WVelocity(Vec3 orgPos)
//////////////////////////////////////////////////////////////////////////////////////////
// Evaluate derivatives with Jacobian
//////////////////////////////////////////////////////////////////////////////////////////
-Vec3 WTURBULENCE::WVelocityWithJacobian(Vec3 orgPos, float* xUnwarped, float* yUnwarped, float* zUnwarped)
+Vec3 WTURBULENCE::WVelocityWithJacobian(const Vec3& orgPos, float* xUnwarped, float* yUnwarped, float* zUnwarped)
{
// arbitrarily offset evaluation points
const Vec3 p1 = orgPos + Vec3(NOISE_TILE_SIZE/2.0,0,0);
diff --git a/intern/smoke/intern/WTURBULENCE.h b/intern/smoke/intern/WTURBULENCE.h
index 36635325f62..a00a818527a 100644
--- a/intern/smoke/intern/WTURBULENCE.h
+++ b/intern/smoke/intern/WTURBULENCE.h
@@ -62,7 +62,7 @@ struct WTURBULENCE
// evaluate wavelet noise function
Vec3 WVelocity(Vec3 p);
- Vec3 WVelocityWithJacobian(Vec3 p, float* xUnwarped, float* yUnwarped, float* zUnwarped);
+ Vec3 WVelocityWithJacobian(const Vec3& p, float* xUnwarped, float* yUnwarped, float* zUnwarped);
// access functions
inline float* getDensityBig() { return _densityBig; }
diff --git a/release/datafiles/locale b/release/datafiles/locale
-Subproject c93ed11a47b3016cf59711ec16de2e2e94c30e9
+Subproject b3d9c97f487bff8b2423c903c14204ba5ca21a8
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject 371960484a38fc64e0a2635170a41a0d8ab2f6b
+Subproject 85a2b50e0e3d505f702a172efc0befa46e87d85
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
-Subproject a8515cfdfe9a98127b592f36fcbe51b7e23b969
+Subproject c3991195ad6eac741db27dc9e8905efb224f219
diff --git a/release/scripts/modules/bpy_extras/anim_utils.py b/release/scripts/modules/bpy_extras/anim_utils.py
index ea0bd77c0f0..75d2065a3d1 100644
--- a/release/scripts/modules/bpy_extras/anim_utils.py
+++ b/release/scripts/modules/bpy_extras/anim_utils.py
@@ -153,15 +153,29 @@ def bake_action_iter(
# -------------------------------------------------------------------------
# Helper Functions and vars
+ # Note: BBONE_PROPS is a list so we can preserve the ordering
+ BBONE_PROPS = [
+ 'bbone_curveinx', 'bbone_curveoutx',
+ 'bbone_curveiny', 'bbone_curveouty',
+ 'bbone_rollin', 'bbone_rollout',
+ 'bbone_scalein', 'bbone_scaleout',
+ 'bbone_easein', 'bbone_easeout'
+ ]
+
def pose_frame_info(obj):
matrix = {}
+ bbones = {}
for name, pbone in obj.pose.bones.items():
if do_visual_keying:
# Get the final transform of the bone in its own local space...
matrix[name] = obj.convert_space(pbone, pbone.matrix, 'POSE', 'LOCAL')
else:
matrix[name] = pbone.matrix_basis.copy()
- return matrix
+
+ # Bendy Bones
+ if pbone.bone.bbone_segments > 1:
+ bbones[name] = {bb_prop : getattr(pbone, bb_prop) for bb_prop in BBONE_PROPS}
+ return matrix, bbones
if do_parents_clear:
if do_visual_keying:
@@ -214,7 +228,7 @@ def bake_action_iter(
break
if do_pose:
- pose_info.append((frame, pose_frame_info(obj)))
+ pose_info.append((frame, *pose_frame_info(obj)))
if do_object:
obj_info.append((frame, obj_frame_info(obj)))
@@ -255,7 +269,7 @@ def bake_action_iter(
# create compatible eulers
euler_prev = None
- for (f, matrix) in pose_info:
+ for (f, matrix, bbones) in pose_info:
pbone.matrix_basis = matrix[name].copy()
pbone.keyframe_insert("location", -1, f, name, options)
@@ -278,6 +292,14 @@ def bake_action_iter(
pbone.keyframe_insert("scale", -1, f, name, options)
+ # Bendy Bones
+ if pbone.bone.bbone_segments > 1:
+ bbone_shape = bbones[name]
+ for bb_prop in BBONE_PROPS:
+ # update this property with value from bbone_shape, then key it
+ setattr(pbone, bb_prop, bbone_shape[bb_prop])
+ pbone.keyframe_insert(bb_prop, -1, f, name, options)
+
# object. TODO. multiple objects
if do_object:
if do_constraint_clear:
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 2f3adf546b8..8093746c646 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -457,19 +457,19 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel):
pbox.prop(ffmpeg, "max_b_frames", text="")
pbox.enabled = ffmpeg.use_max_b_frames
- split = layout.split()
- split.enabled = ffmpeg.constant_rate_factor == 'NONE'
- col = split.column()
- col.label(text="Rate:")
- col.prop(ffmpeg, "video_bitrate")
- col.prop(ffmpeg, "minrate", text="Minimum")
- col.prop(ffmpeg, "maxrate", text="Maximum")
- col.prop(ffmpeg, "buffersize", text="Buffer")
+ if ffmpeg.constant_rate_factor == 'NONE':
+ split = layout.split()
+ col = split.column()
+ col.label(text="Rate:")
+ col.prop(ffmpeg, "video_bitrate")
+ col.prop(ffmpeg, "minrate", text="Minimum")
+ col.prop(ffmpeg, "maxrate", text="Maximum")
+ col.prop(ffmpeg, "buffersize", text="Buffer")
- col = split.column()
- col.label(text="Mux:")
- col.prop(ffmpeg, "muxrate", text="Rate")
- col.prop(ffmpeg, "packetsize", text="Packet Size")
+ col = split.column()
+ col.label(text="Mux:")
+ col.prop(ffmpeg, "muxrate", text="Rate")
+ col.prop(ffmpeg, "packetsize", text="Packet Size")
layout.separator()
@@ -477,10 +477,10 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel):
if ffmpeg.format != 'MP3':
layout.prop(ffmpeg, "audio_codec", text="Audio Codec")
- row = layout.row()
- row.enabled = ffmpeg.audio_codec != 'NONE'
- row.prop(ffmpeg, "audio_bitrate")
- row.prop(ffmpeg, "audio_volume", slider=True)
+ if ffmpeg.audio_codec != 'NONE':
+ row = layout.row()
+ row.prop(ffmpeg, "audio_bitrate")
+ row.prop(ffmpeg, "audio_volume", slider=True)
class RENDER_PT_bake(RenderButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 1ca1da315b7..106e6695553 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -1128,6 +1128,8 @@ class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel):
row.active = render.sequencer_gl_preview == 'SOLID'
row.prop(render, "use_sequencer_gl_textured_solid")
+ col.prop(render, "use_sequencer_gl_dof")
+
class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel):
bl_label = "View Settings"
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index c7e05a4173e..096c164d7d0 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -1550,18 +1550,21 @@ class VIEW3D_MT_object_specials(Menu):
layout.operator_context = 'INVOKE_REGION_WIN'
if scene.render.use_shading_nodes:
- try:
- value = lamp.node_tree.nodes["Emission"].inputs["Strength"].default_value
- except AttributeError:
- value = None
-
- if value is not None:
+ emission_node = None
+ if lamp.node_tree:
+ for node in lamp.node_tree.nodes:
+ if getattr(node, "type", None) == 'EMISSION':
+ emission_node = node
+ break
+
+ if emission_node is not None:
props = layout.operator("wm.context_modal_mouse", text="Strength")
props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.node_tree.nodes[\"Emission\"].inputs[\"Strength\"].default_value"
+ props.data_path_item = "data.node_tree" \
+ ".nodes[\"" + emission_node.name + "\"]" \
+ ".inputs[\"Strength\"].default_value"
props.header_text = "Lamp Strength: %.3f"
props.input_scale = 0.1
- del value
if lamp.type == 'AREA':
props = layout.operator("wm.context_modal_mouse", text="Size X")
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 12f15b8b90e..3792ac13d18 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -852,12 +852,12 @@ class VIEW3D_PT_tools_posemode(View3DPanel, Panel):
draw_keyframing_tools(context, layout)
- pchan = context.active_pose_bone
- mpath = pchan.motion_path if pchan else None
+ ob = context.object
+ avs = ob.pose.animation_visualization
col = layout.column(align=True)
col.label(text="Motion Paths:")
- if mpath:
+ if avs.motion_path.has_motion_paths:
row = col.row(align=True)
row.operator("pose.paths_update", text="Update")
row.operator("pose.paths_clear", text="", icon='X')
@@ -1810,12 +1810,6 @@ class VIEW3D_PT_tools_vertexpaint(Panel, View3DPaintPanel):
vpaint = toolsettings.vertex_paint
col = layout.column()
- col.label("Falloff:")
- row = col.row()
- row.prop(vpaint, "use_normal_falloff")
- sub = row.row()
- sub.active = (vpaint.use_normal_falloff)
- sub.prop(vpaint, "normal_angle", text="")
self.unified_paint_settings(col, context)
diff --git a/source/blender/alembic/intern/abc_mball.h b/source/blender/alembic/intern/abc_mball.h
index 46b61151216..9b943698416 100644
--- a/source/blender/alembic/intern/abc_mball.h
+++ b/source/blender/alembic/intern/abc_mball.h
@@ -25,7 +25,7 @@
#include "abc_object.h"
-struct AbcMeshWriter;
+class AbcMeshWriter;
struct Main;
struct MetaBall;
struct Object;
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index ec0bfa6f5fa..647291382ef 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -48,10 +48,17 @@ void BKE_blender_version_string(
char *version_str, size_t maxncpy,
short version, short subversion, bool v_prefix, bool include_subversion);
-void BKE_blender_userdef_set_data(struct UserDef *userdef);
-void BKE_blender_userdef_free_data(struct UserDef *userdef);
+void BKE_blender_userdef_data_swap(struct UserDef *userdef_dst, struct UserDef *userdef_src);
+void BKE_blender_userdef_data_set(struct UserDef *userdef);
+void BKE_blender_userdef_data_set_and_free(struct UserDef *userdef);
-void BKE_blender_userdef_set_app_template(struct UserDef *userdef);
+void BKE_blender_userdef_app_template_data_swap(struct UserDef *userdef_dst, struct UserDef *userdef_src);
+void BKE_blender_userdef_app_template_data_set(struct UserDef *userdef);
+void BKE_blender_userdef_app_template_data_set_and_free(struct UserDef *userdef);
+
+void BKE_blender_userdef_data_duplicate(struct UserDef *userdef_dst, struct UserDef *userdef_src);
+
+void BKE_blender_userdef_data_free(struct UserDef *userdef, bool clear_fonts);
/* set this callback when a UI is running */
void BKE_blender_callback_test_break_set(void (*func)(void));
diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h
index ac58451e412..9ff164f60be 100644
--- a/source/blender/blenkernel/BKE_blendfile.h
+++ b/source/blender/blenkernel/BKE_blendfile.h
@@ -58,8 +58,8 @@ struct UserDef *BKE_blendfile_userdef_read_from_memory(
const void *filebuf, int filelength,
struct ReportList *reports);
-int BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports);
-
+bool BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports);
+bool BKE_blendfile_userdef_write_app_template(const char *filepath, struct ReportList *reports);
/* partial blend file writing */
void BKE_blendfile_write_partial_tag_ID(struct ID *id, bool set);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 657e99f05d1..6c9dc12b44f 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -421,11 +421,21 @@ struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seq
struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
/* view3d draw callback, run when not in background view */
+/* NOTE: Keep in sync with V3D_OFSDRAW_* flags. */
+enum {
+ SEQ_OFSDRAW_NONE = (0),
+ SEQ_OFSDRAW_USE_BACKGROUND = (1 << 0),
+ SEQ_OFSDRAW_USE_FULL_SAMPLE = (1 << 1),
+ SEQ_OFSDRAW_USE_GPENCIL = (1 << 2),
+ SEQ_OFSDRAW_USE_SOLID_TEX = (1 << 2),
+ SEQ_OFSDRAW_USE_CAMERA_DOF = (1 << 3),
+};
+
typedef struct ImBuf *(*SequencerDrawView)(
- struct Scene *, struct Object *, int, int,
- unsigned int, int, bool, bool, bool,
- int, int, bool, const char *,
- struct GPUFX *, struct GPUOffScreen *, char[256]);
+ struct Scene *scene, struct Object *camera, int width, int height,
+ unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode,
+ int samples, const char *viewname,
+ struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
extern SequencerDrawView sequencer_view3d_cb;
/* copy/paste */
diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h
index f52bb2ab9cb..92170325113 100644
--- a/source/blender/blenkernel/BKE_subsurf.h
+++ b/source/blender/blenkernel/BKE_subsurf.h
@@ -125,6 +125,8 @@ typedef struct CCGDerivedMesh {
struct CCGFace **gridFaces;
struct DMFlagMat *gridFlagMats;
unsigned int **gridHidden;
+ /* Elements in arrays above. */
+ unsigned int numGrid;
struct {
struct MultiresModifierData *mmd;
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h
deleted file mode 100644
index 7c1e0e97565..00000000000
--- a/source/blender/blenkernel/BKE_utildefines.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file BKE_utildefines.h
- * \ingroup bke
- * \brief blender format specific macros
- * \note generic defines should go in BLI_utildefines.h
- */
-
-
-#ifndef __BKE_UTILDEFINES_H__
-#define __BKE_UTILDEFINES_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define BKE_BIT_TEST_SET(value, test, flag) \
-{ \
- if (test) (value) |= flag; \
- else (value) &= ~flag; \
-} (void)0
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __BKE_UTILDEFINES_H__ */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 74c69c5aeb9..96c653dee23 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -292,7 +292,6 @@ set(SRC
BKE_texture.h
BKE_tracking.h
BKE_unit.h
- BKE_utildefines.h
BKE_world.h
BKE_writeavi.h
BKE_writeframeserver.h
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index 6dd852c7875..8d4776dca0e 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -290,6 +290,33 @@ static bool get_path_user(
}
/**
+ * Special convenience exception for dev builds to allow overrides to the system path.
+ * With this, need for running 'make install' can be avoided, e.g. by symlinking SOURCE_DIR/release
+ * to EXECUTABLE_DIR/release, or by running Blender from source directory directly.
+ */
+static bool get_path_system_dev_build_exception(
+ char *targetpath, size_t targetpath_len, const char *relfolder)
+{
+ char cwd[FILE_MAX];
+
+ /* Try EXECUTABLE_DIR/release/folder_name. Allows symlinking release folder from source dir. */
+ if (test_path(targetpath, targetpath_len, bprogdir, "release", relfolder)) {
+ return true;
+ }
+ /* Try CWD/release/folder_name. Allows executing Blender from any directory
+ * (usually source dir), even without a release dir in bprogdir. */
+ if (BLI_current_working_dir(cwd, sizeof(cwd))) {
+ if (test_path(targetpath, targetpath_len, cwd, "release", relfolder)) {
+ return true;
+ }
+ }
+ /* never use if not existing. */
+ targetpath[0] = '\0';
+
+ return false;
+}
+
+/**
* Returns the path of a folder within the Blender installation directory.
*
* \param targetpath String to return path
@@ -305,7 +332,6 @@ static bool get_path_system(
{
char system_path[FILE_MAX];
const char *system_base_path;
- char cwd[FILE_MAX];
char relfolder[FILE_MAX];
if (folder_name) {
@@ -320,25 +346,9 @@ static bool get_path_system(
relfolder[0] = '\0';
}
- /* first allow developer only overrides to the system path
- * these are only used when running blender from source */
-
- /* try CWD/release/folder_name */
- if (BLI_current_working_dir(cwd, sizeof(cwd))) {
- if (test_path(targetpath, targetpath_len, cwd, "release", relfolder)) {
- return true;
- }
- }
- /* try EXECUTABLE_DIR/release/folder_name */
- if (test_path(targetpath, targetpath_len, bprogdir, "release", relfolder)) {
+ if (get_path_system_dev_build_exception(targetpath, targetpath_len, relfolder)) {
return true;
}
- /* never use if not existing. */
- targetpath[0] = '\0';
-
- /* end developer overrides */
-
-
system_path[0] = '\0';
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 2624019e63a..af46b6ec852 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -150,11 +150,21 @@ static void keymap_item_free(wmKeyMapItem *kmi)
MEM_freeN(kmi->ptr);
}
-void BKE_blender_userdef_set_data(UserDef *userdef)
+void BKE_blender_userdef_data_swap(UserDef *userdef_a, UserDef *userdef_b)
{
- /* only here free userdef themes... */
- BKE_blender_userdef_free_data(&U);
- U = *userdef;
+ SWAP(UserDef, *userdef_a, *userdef_b);
+}
+
+void BKE_blender_userdef_data_set(UserDef *userdef)
+{
+ BKE_blender_userdef_data_swap(&U, userdef);
+ BKE_blender_userdef_data_free(userdef, true);
+}
+
+void BKE_blender_userdef_data_set_and_free(UserDef *userdef)
+{
+ BKE_blender_userdef_data_set(userdef);
+ MEM_freeN(userdef);
}
static void userdef_free_keymaps(UserDef *userdef)
@@ -201,7 +211,7 @@ static void userdef_free_addons(UserDef *userdef)
* When loading a new userdef from file,
* or when exiting Blender.
*/
-void BKE_blender_userdef_free_data(UserDef *userdef)
+void BKE_blender_userdef_data_free(UserDef *userdef, bool clear_fonts)
{
#define U _invalid_access_ /* ensure no accidental global access */
#ifdef U /* quiet warning */
@@ -210,12 +220,13 @@ void BKE_blender_userdef_free_data(UserDef *userdef)
userdef_free_keymaps(userdef);
userdef_free_addons(userdef);
- for (uiFont *font = userdef->uifonts.first; font; font = font->next) {
- BLF_unload_id(font->blf_id);
+ if (clear_fonts) {
+ for (uiFont *font = userdef->uifonts.first; font; font = font->next) {
+ BLF_unload_id(font->blf_id);
+ }
+ BLF_default_set(-1);
}
- BLF_default_set(-1);
-
BLI_freelistN(&userdef->autoexec_paths);
BLI_freelistN(&userdef->uistyles);
@@ -229,38 +240,55 @@ void BKE_blender_userdef_free_data(UserDef *userdef)
* Write U from userdef.
* This function defines which settings a template will override for the user preferences.
*/
-void BKE_blender_userdef_set_app_template(UserDef *userdef)
+void BKE_blender_userdef_app_template_data_swap(UserDef *userdef_a, UserDef *userdef_b)
{
/* TODO:
* - keymaps
* - various minor settings (add as needed).
*/
-#define LIST_OVERRIDE(id) { \
- BLI_freelistN(&U.id); \
- BLI_movelisttolist(&U.id, &userdef->id); \
-} ((void)0)
+#define DATA_SWAP(id) \
+ { \
+ UserDef userdef_tmp; \
+ memcpy(&(userdef_tmp.id), &(userdef_a->id), sizeof(userdef_tmp.id)); \
+ memcpy(&(userdef_a->id), &(userdef_b->id), sizeof(userdef_tmp.id)); \
+ memcpy(&(userdef_b->id), &(userdef_tmp.id), sizeof(userdef_tmp.id)); \
+ }
-#define MEMCPY_OVERRIDE(id) \
- memcpy(U.id, userdef->id, sizeof(U.id));
+#define LIST_SWAP(id) { \
+ SWAP(ListBase, userdef_a->id, userdef_b->id); \
+} ((void)0)
/* for some types we need custom free functions */
- userdef_free_addons(&U);
- userdef_free_keymaps(&U);
+ LIST_SWAP(addons);
+ LIST_SWAP(user_keymaps);
+
+ LIST_SWAP(uistyles);
+ LIST_SWAP(uifonts);
+ LIST_SWAP(themes);
+ LIST_SWAP(addons);
+ LIST_SWAP(user_keymaps);
+
+ DATA_SWAP(light);
- LIST_OVERRIDE(uistyles);
- LIST_OVERRIDE(uifonts);
- LIST_OVERRIDE(themes);
- LIST_OVERRIDE(addons);
- LIST_OVERRIDE(user_keymaps);
+ DATA_SWAP(font_path_ui);
+ DATA_SWAP(font_path_ui_mono);
- MEMCPY_OVERRIDE(light);
+#undef SWAP_TYPELESS
+#undef LIST_SWAP
+#undef DATA_SWAP
+}
- MEMCPY_OVERRIDE(font_path_ui);
- MEMCPY_OVERRIDE(font_path_ui_mono);
+void BKE_blender_userdef_app_template_data_set(UserDef *userdef)
+{
+ BKE_blender_userdef_app_template_data_swap(&U, userdef);
+ BKE_blender_userdef_data_free(userdef, true);
+}
-#undef LIST_OVERRIDE
-#undef MEMCPY_OVERRIDE
+void BKE_blender_userdef_app_template_data_set_and_free(UserDef *userdef)
+{
+ BKE_blender_userdef_app_template_data_set(userdef);
+ MEM_freeN(userdef);
}
/* ***************** testing for break ************* */
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 980df05aca2..cc992a4a520 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -226,11 +226,9 @@ static void setup_app_data(
CTX_data_main_set(C, G.main);
if (bfd->user) {
-
/* only here free userdef themes... */
- BKE_blender_userdef_free_data(&U);
-
- U = *bfd->user;
+ BKE_blender_userdef_data_set_and_free(bfd->user);
+ bfd->user = NULL;
/* Security issue: any blend file could include a USER block.
*
@@ -241,8 +239,6 @@ static void setup_app_data(
* enable scripts auto-execution by loading a '.blend' file.
*/
U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
-
- MEM_freeN(bfd->user);
}
/* case G_FILE_NO_UI or no screens in file */
@@ -497,21 +493,48 @@ UserDef *BKE_blendfile_userdef_read_from_memory(
}
-/* only write the userdef in a .blend */
-int BKE_blendfile_userdef_write(const char *filepath, ReportList *reports)
+/**
+ * Only write the userdef in a .blend
+ * \return success
+ */
+bool BKE_blendfile_userdef_write(const char *filepath, ReportList *reports)
{
Main *mainb = MEM_callocN(sizeof(Main), "empty main");
- int retval = 0;
+ bool ok = false;
if (BLO_write_file(mainb, filepath, G_FILE_USERPREFS, reports, NULL)) {
- retval = 1;
+ ok = true;
}
MEM_freeN(mainb);
- return retval;
+ return ok;
}
+/**
+ * Only write the userdef in a .blend, merging with the existing blend file.
+ * \return success
+ *
+ * \note In the future we should re-evaluate user preferences,
+ * possibly splitting out system/hardware specific prefs.
+ */
+bool BKE_blendfile_userdef_write_app_template(const char *filepath, ReportList *reports)
+{
+ /* if it fails, overwrite is OK. */
+ UserDef *userdef_default = BKE_blendfile_userdef_read(filepath, NULL);
+ if (userdef_default == NULL) {
+ return BKE_blendfile_userdef_write(filepath, reports);
+ }
+
+ BKE_blender_userdef_app_template_data_swap(&U, userdef_default);
+ bool ok = BKE_blendfile_userdef_write(filepath, reports);
+ BKE_blender_userdef_app_template_data_swap(&U, userdef_default);
+ BKE_blender_userdef_data_free(userdef_default, false);
+ MEM_freeN(userdef_default);
+ return ok;
+}
+
+
/** \} */
diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c
index 79b3f89da20..8018629ef2a 100644
--- a/source/blender/blenkernel/intern/bmfont.c
+++ b/source/blender/blenkernel/intern/bmfont.c
@@ -52,11 +52,10 @@
#include "MEM_guardedalloc.h"
#include "IMB_imbuf_types.h"
-#include "BKE_bmfont.h"
-#include "BKE_bmfont_types.h"
-
#include "BLI_utildefines.h"
+#include "BKE_bmfont.h"
+#include "BKE_bmfont_types.h"
#include "BKE_global.h"
void printfGlyph(bmGlyph *glyph)
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index ee25be36855..21e28f5180c 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -801,8 +801,8 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa
if ( cloth->bvhselftree ) {
// search for overlapping collision pairs
overlap = BLI_bvhtree_overlap(cloth->bvhselftree, cloth->bvhselftree, &result, NULL, NULL);
-
- // #pragma omp parallel for private(k, i, j) schedule(static)
+
+ /* Could be parallelized (using BLI_task)... */
for ( k = 0; k < result; k++ ) {
float temp[3];
float length = 0;
@@ -1147,9 +1147,10 @@ static CollPair *cloth_point_collision(
return collpair;
}
-static void cloth_points_objcollisions_nearcheck(ClothModifierData * clmd, CollisionModifierData *collmd,
- CollPair **collisions, CollPair **collisions_index,
- int numresult, BVHTreeOverlap *overlap, float epsilon, double dt)
+static void cloth_points_objcollisions_nearcheck(
+ ClothModifierData *clmd, CollisionModifierData *collmd,
+ CollPair **collisions, CollPair **collisions_index,
+ int numresult, BVHTreeOverlap *overlap, float epsilon, double dt)
{
int i;
@@ -1163,8 +1164,9 @@ static void cloth_points_objcollisions_nearcheck(ClothModifierData * clmd, Colli
}
}
-static int cloth_points_objcollisions_resolve(ClothModifierData * clmd, CollisionModifierData *collmd, PartDeflect *pd,
- CollPair *collisions, CollPair *collisions_index, float dt)
+static int cloth_points_objcollisions_resolve(
+ ClothModifierData *clmd, CollisionModifierData *collmd, PartDeflect *pd,
+ CollPair *collisions, CollPair *collisions_index, float dt)
{
Cloth *cloth = clmd->clothObject;
int i = 0, mvert_num = clmd->clothObject->mvert_num;
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 382b26abbc6..9c85a26b58a 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1775,7 +1775,7 @@ void driver_variable_name_validate(DriverVar *dvar)
/* 1) Must start with a letter */
/* XXX: We assume that valid unicode letters in other languages are ok too, hence the blacklisting */
- if (ELEM(dvar->name[0], '0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) {
+ if (IN_RANGE_INCL(dvar->name[0], '0', '9')) {
dvar->flag |= DVAR_FLAG_INVALID_START_NUM;
}
else if (dvar->name[0] == '_') {
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index e45a938a4fc..686fe3bda93 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -34,14 +34,14 @@
#include "DNA_freestyle_types.h"
#include "DNA_group_types.h"
-#include "BKE_freestyle.h"
-#include "BKE_library.h"
-#include "BKE_linestyle.h"
-
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_string_utils.h"
+#include "BKE_freestyle.h"
+#include "BKE_library.h"
+#include "BKE_linestyle.h"
+
// function declarations
static FreestyleLineSet *alloc_lineset(void);
static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset, const int flag);
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 7e259b38842..b84a494c70e 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -2383,10 +2383,10 @@ void BKE_library_filepath_set(Library *lib, const char *filepath)
void BKE_id_tag_set_atomic(ID *id, int tag)
{
- atomic_fetch_and_or_uint32((uint32_t *)&id->tag, tag);
+ atomic_fetch_and_or_int32(&id->tag, tag);
}
void BKE_id_tag_clear_atomic(ID *id, int tag)
{
- atomic_fetch_and_and_uint32((uint32_t *)&id->tag, ~tag);
+ atomic_fetch_and_and_int32(&id->tag, ~tag);
}
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 13ec970c65c..104bb0c07a6 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -80,6 +80,7 @@
#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BLI_task.h"
#include "BLI_listbase.h"
#include "BLI_linklist.h"
@@ -1423,15 +1424,39 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x
return value;
}
+
+typedef struct MaskRasterizeBufferData {
+ MaskRasterHandle *mr_handle;
+ float x_inv, y_inv;
+ float x_px_ofs, y_px_ofs;
+ uint width;
+
+ float *buffer;
+} MaskRasterizeBufferData;
+
+static void maskrasterize_buffer_cb(void *userdata, int y)
+{
+ MaskRasterizeBufferData *data = userdata;
+
+ MaskRasterHandle *mr_handle = data->mr_handle;
+ float *buffer = data->buffer;
+
+ const uint width = data->width;
+ const float x_inv = data->x_inv;
+ const float x_px_ofs = data->x_px_ofs;
+
+ uint i = (uint)y * width;
+ float xy[2];
+ xy[1] = ((float)y * data->y_inv) + data->y_px_ofs;
+ for (uint x = 0; x < width; x++, i++) {
+ xy[0] = ((float)x * x_inv) + x_px_ofs;
+
+ buffer[i] = BKE_maskrasterize_handle_sample(mr_handle, xy);
+ }
+}
+
/**
- * \brief Rasterize a buffer from a single mask
- *
- * We could get some speedup by inlining #BKE_maskrasterize_handle_sample
- * and calculating each layer then blending buffers, but this function is only
- * used by the sequencer - so better have the caller thread.
- *
- * Since #BKE_maskrasterize_handle_sample is used threaded elsewhere,
- * we can simply use openmp here for some speedup.
+ * \brief Rasterize a buffer from a single mask (threaded execution).
*/
void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle,
const unsigned int width, const unsigned int height,
@@ -1439,33 +1464,15 @@ void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle,
{
const float x_inv = 1.0f / (float)width;
const float y_inv = 1.0f / (float)height;
- const float x_px_ofs = x_inv * 0.5f;
- const float y_px_ofs = y_inv * 0.5f;
-#ifdef _MSC_VER
- int y; /* msvc requires signed for some reason */
-
- /* ignore sign mismatch */
-# pragma warning(push)
-# pragma warning(disable:4018)
-#else
- unsigned int y;
-#endif
-
-#pragma omp parallel for private(y)
- for (y = 0; y < height; y++) {
- unsigned int i = y * width;
- unsigned int x;
- float xy[2];
- xy[1] = ((float)y * y_inv) + y_px_ofs;
- for (x = 0; x < width; x++, i++) {
- xy[0] = ((float)x * x_inv) + x_px_ofs;
-
- buffer[i] = BKE_maskrasterize_handle_sample(mr_handle, xy);
- }
- }
-
-#ifdef _MSC_VER
-# pragma warning(pop)
-#endif
+ MaskRasterizeBufferData data = {
+ .mr_handle = mr_handle,
+ .x_inv = x_inv,
+ .y_inv = y_inv,
+ .x_px_ofs = x_inv * 0.5f,
+ .y_px_ofs = y_inv * 0.5f,
+ .width = width,
+ .buffer = buffer
+ };
+ BLI_task_parallel_range(0, (int)height, &data, maskrasterize_buffer_cb, height * width > 10000);
}
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index b0580f75044..f321c94bf00 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -1482,6 +1482,7 @@ void BKE_mesh_remap_calc_loops_from_dm(
for (i = vert_to_refelem_map_src[nearest.index].count; i--;) {
const int index_src = vert_to_refelem_map_src[nearest.index].indices[i];
+ BLI_assert(index_src != -1);
const float dot = dot_v3v3(nors_src[index_src], *nor_dst);
pidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ?
@@ -1522,7 +1523,12 @@ void BKE_mesh_remap_calc_loops_from_dm(
}
}
}
- if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) {
+ if (best_index_src == -1) {
+ /* We found no item to map back from closest vertex... */
+ best_nor_dot = -1.0f;
+ hit_dist = FLT_MAX;
+ }
+ else if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) {
/* Our best_index_src is a poly one for now!
* Have to find its loop matching our closest vertex. */
mp_src = &polys_src[best_index_src];
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index c64a183a511..f231f8f61c9 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -330,14 +330,14 @@ void BKE_object_free_derived_caches(Object *ob)
Mesh *me = ob->data;
if (me && me->bb) {
- atomic_fetch_and_or_uint32((uint *)&me->bb->flag, BOUNDBOX_DIRTY);
+ atomic_fetch_and_or_int32(&me->bb->flag, BOUNDBOX_DIRTY);
}
}
else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
Curve *cu = ob->data;
if (cu && cu->bb) {
- atomic_fetch_and_or_uint32((uint *)&cu->bb->flag, BOUNDBOX_DIRTY);
+ atomic_fetch_and_or_int32(&cu->bb->flag, BOUNDBOX_DIRTY);
}
}
diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c
index f31ba34a984..4d97121e2a3 100644
--- a/source/blender/blenkernel/intern/outliner_treehash.c
+++ b/source/blender/blenkernel/intern/outliner_treehash.c
@@ -28,14 +28,14 @@
#include <stdlib.h>
-#include "BKE_outliner_treehash.h"
-
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_mempool.h"
#include "DNA_outliner_types.h"
+#include "BKE_outliner_treehash.h"
+
#include "MEM_guardedalloc.h"
typedef struct TseGroup {
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index aa8ab07518f..39d1d8e8510 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1007,9 +1007,7 @@ static void pbvh_update_normals_store_task_cb(void *userdata, const int n)
MVert *mvert = &bvh->verts[v];
/* mvert is shared between nodes, hence between threads. */
- if (atomic_fetch_and_and_uint8(
- (uint8_t *)&mvert->flag, (uint8_t)~ME_VERT_PBVH_UPDATE) & ME_VERT_PBVH_UPDATE)
- {
+ if (atomic_fetch_and_and_char(&mvert->flag, (char)~ME_VERT_PBVH_UPDATE) & ME_VERT_PBVH_UPDATE) {
normalize_v3(vnors[v]);
normal_float_to_short_v3(mvert->no, vnors[v]);
}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 9b0db300e6d..9e8e202c2bc 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -3295,11 +3295,18 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) {
char err_out[256] = "unknown";
- int width = (scene->r.xsch * scene->r.size) / 100;
- int height = (scene->r.ysch * scene->r.size) / 100;
+ const int width = (scene->r.xsch * scene->r.size) / 100;
+ const int height = (scene->r.ysch * scene->r.size) / 100;
const bool use_background = (scene->r.alphamode == R_ADDSKY);
const char *viewname = BKE_scene_multiview_render_view_name_get(&scene->r, context->view_id);
+ unsigned int draw_flags = SEQ_OFSDRAW_NONE;
+ draw_flags |= (use_gpencil) ? SEQ_OFSDRAW_USE_GPENCIL : 0;
+ draw_flags |= (use_background) ? SEQ_OFSDRAW_USE_BACKGROUND : 0;
+ draw_flags |= (context->gpu_full_samples) ? SEQ_OFSDRAW_USE_FULL_SAMPLE : 0;
+ draw_flags |= (context->scene->r.seq_flag & R_SEQ_SOLID_TEX) ? SEQ_OFSDRAW_USE_SOLID_TEX : 0;
+ draw_flags |= (context->scene->r.seq_flag & R_SEQ_CAMERA_DOF) ? SEQ_OFSDRAW_USE_CAMERA_DOF : 0;
+
/* for old scene this can be uninitialized,
* should probably be added to do_versions at some point if the functionality stays */
if (context->scene->r.seq_prev_type == 0)
@@ -3309,11 +3316,8 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
ibuf = sequencer_view3d_cb(
/* set for OpenGL render (NULL when scrubbing) */
- scene, camera, width, height, IB_rect,
- context->scene->r.seq_prev_type,
- (context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0,
- use_gpencil, use_background, scene->r.alphamode,
- context->gpu_samples, context->gpu_full_samples, viewname,
+ scene, camera, width, height, IB_rect, draw_flags, context->scene->r.seq_prev_type,
+ scene->r.alphamode, context->gpu_samples, viewname,
context->gpu_fx, context->gpu_offscreen, err_out);
if (ibuf == NULL) {
fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 0cdc97c829f..f8025f8df84 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -4031,10 +4031,12 @@ static void ccgDM_release(DerivedMesh *dm)
if (ccgdm->gridOffset) MEM_freeN(ccgdm->gridOffset);
if (ccgdm->gridFlagMats) MEM_freeN(ccgdm->gridFlagMats);
if (ccgdm->gridHidden) {
- int i, numGrids = dm->getNumGrids(dm);
- for (i = 0; i < numGrids; i++) {
- if (ccgdm->gridHidden[i])
+ /* Using dm->getNumGrids(dm) accesses freed memory */
+ uint numGrids = ccgdm->numGrid;
+ for (uint i = 0; i < numGrids; i++) {
+ if (ccgdm->gridHidden[i]) {
MEM_freeN(ccgdm->gridHidden[i]);
+ }
}
MEM_freeN(ccgdm->gridHidden);
}
@@ -4338,6 +4340,7 @@ static void ccgdm_create_grids(DerivedMesh *dm)
ccgdm->gridFaces = gridFaces;
ccgdm->gridOffset = gridOffset;
ccgdm->gridFlagMats = gridFlagMats;
+ ccgdm->numGrid = numGrids;
}
static CCGElem **ccgDM_getGridData(DerivedMesh *dm)
diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c
index 30981ed8f23..4ff4a129768 100644
--- a/source/blender/blenkernel/intern/tracking_auto.c
+++ b/source/blender/blenkernel/intern/tracking_auto.c
@@ -30,6 +30,7 @@
*/
#include <stdlib.h>
+#include "atomic_ops.h"
#include "MEM_guardedalloc.h"
@@ -38,6 +39,7 @@
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "BLI_math.h"
@@ -86,6 +88,8 @@ typedef struct AutoTrackContext {
int sync_frame;
bool first_sync;
SpinLock spin_lock;
+
+ bool step_ok;
} AutoTrackContext;
static void normalized_to_libmv_frame(const float normalized[2],
@@ -379,81 +383,94 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip,
return context;
}
-bool BKE_autotrack_context_step(AutoTrackContext *context)
+static void autotrack_context_step_cb(void *userdata, int track)
{
+ AutoTrackContext *context = userdata;
const int frame_delta = context->backwards ? -1 : 1;
- bool ok = false;
- int track;
-
-#pragma omp parallel for if (context->num_tracks > 1)
- for (track = 0; track < context->num_tracks; ++track) {
- AutoTrackOptions *options = &context->options[track];
- if (options->is_failed) {
- continue;
- }
- libmv_Marker libmv_current_marker,
- libmv_reference_marker,
- libmv_tracked_marker;
- libmv_TrackRegionResult libmv_result;
- const int frame = BKE_movieclip_remap_scene_to_clip_frame(
- context->clips[options->clip_index],
- context->user.framenr);
+
+ AutoTrackOptions *options = &context->options[track];
+ if (options->is_failed) {
+ return;
+ }
+ libmv_Marker libmv_current_marker,
+ libmv_reference_marker,
+ libmv_tracked_marker;
+ libmv_TrackRegionResult libmv_result;
+ const int frame = BKE_movieclip_remap_scene_to_clip_frame(
+ context->clips[options->clip_index],
+ context->user.framenr);
+ BLI_spin_lock(&context->spin_lock);
+ const bool has_marker = libmv_autoTrackGetMarker(context->autotrack,
+ options->clip_index,
+ frame,
+ options->track_index,
+ &libmv_current_marker);
+ BLI_spin_unlock(&context->spin_lock);
+ /* Check whether we've got marker to sync with. */
+ if (!has_marker) {
+ return;
+ }
+ /* Check whether marker is going outside of allowed frame margin. */
+ if (!tracking_check_marker_margin(&libmv_current_marker,
+ options->track->margin,
+ context->frame_width,
+ context->frame_height))
+ {
+ return;
+ }
+ libmv_tracked_marker = libmv_current_marker;
+ libmv_tracked_marker.frame = frame + frame_delta;
+ /* Update reference frame. */
+ if (options->use_keyframe_match) {
+ libmv_tracked_marker.reference_frame =
+ libmv_current_marker.reference_frame;
+ libmv_autoTrackGetMarker(context->autotrack,
+ options->clip_index,
+ libmv_tracked_marker.reference_frame,
+ options->track_index,
+ &libmv_reference_marker);
+ }
+ else {
+ libmv_tracked_marker.reference_frame = frame;
+ libmv_reference_marker = libmv_current_marker;
+ }
+ /* Perform actual tracking. */
+ if (libmv_autoTrackMarker(context->autotrack,
+ &options->track_region_options,
+ &libmv_tracked_marker,
+ &libmv_result))
+ {
BLI_spin_lock(&context->spin_lock);
- const bool has_marker = libmv_autoTrackGetMarker(context->autotrack,
- options->clip_index,
- frame,
- options->track_index,
- &libmv_current_marker);
+ libmv_autoTrackAddMarker(context->autotrack, &libmv_tracked_marker);
BLI_spin_unlock(&context->spin_lock);
- /* Check whether we've got marker to sync with. */
- if (!has_marker) {
- continue;
- }
- /* Check whether marker is going outside of allowed frame margin. */
- if (!tracking_check_marker_margin(&libmv_current_marker,
- options->track->margin,
- context->frame_width,
- context->frame_height))
- {
- continue;
- }
- libmv_tracked_marker = libmv_current_marker;
- libmv_tracked_marker.frame = frame + frame_delta;
- /* Update reference frame. */
- if (options->use_keyframe_match) {
- libmv_tracked_marker.reference_frame =
- libmv_current_marker.reference_frame;
- libmv_autoTrackGetMarker(context->autotrack,
- options->clip_index,
- libmv_tracked_marker.reference_frame,
- options->track_index,
- &libmv_reference_marker);
- }
- else {
- libmv_tracked_marker.reference_frame = frame;
- libmv_reference_marker = libmv_current_marker;
- }
- /* Perform actual tracking. */
- if (libmv_autoTrackMarker(context->autotrack,
- &options->track_region_options,
- &libmv_tracked_marker,
- &libmv_result))
- {
- BLI_spin_lock(&context->spin_lock);
- libmv_autoTrackAddMarker(context->autotrack, &libmv_tracked_marker);
- BLI_spin_unlock(&context->spin_lock);
- }
- else {
- options->is_failed = true;
- options->failed_frame = frame + frame_delta;
- }
- ok = true;
}
+ else {
+ options->is_failed = true;
+ options->failed_frame = frame + frame_delta;
+ }
+
+ /* Note: Atomic is probably not actually needed here, I doubt we could get
+ * any other result than a true bool anyway.
+ * But for sake of consistency, and since it costs nothing...
+ */
+ atomic_fetch_and_or_uint8((uint8_t *)&context->step_ok, true);
+}
+
+bool BKE_autotrack_context_step(AutoTrackContext *context)
+{
+ const int frame_delta = context->backwards ? -1 : 1;
+ context->step_ok = false;
+
+ BLI_task_parallel_range(0, context->num_tracks,
+ context,
+ autotrack_context_step_cb,
+ context->num_tracks > 1);
+
/* Advance the frame. */
BLI_spin_lock(&context->spin_lock);
context->user.framenr += frame_delta;
BLI_spin_unlock(&context->spin_lock);
- return ok;
+ return context->step_ok;
}
void BKE_autotrack_context_sync(AutoTrackContext *context)
@@ -555,8 +572,9 @@ void BKE_autotrack_context_finish(AutoTrackContext *context)
if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
int track;
for (track = 0; track < context->num_tracks; ++track) {
- if (BKE_tracking_plane_track_has_point_track(plane_track,
- context->options[track].track))
+ if (BKE_tracking_plane_track_has_point_track(
+ plane_track,
+ context->options[track].track))
{
BKE_tracking_track_plane_from_existing_motion(
plane_track,
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index b8dfb217c16..edddeb41cc8 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -41,13 +41,14 @@
#include "BLI_utildefines.h"
#include "BLI_sort_utils.h"
+#include "BLI_ghash.h"
#include "BLI_math_vector.h"
#include "BLI_math.h"
+#include "BLI_task.h"
#include "BKE_tracking.h"
#include "BKE_movieclip.h"
#include "BKE_fcurve.h"
-#include "BLI_ghash.h"
#include "MEM_guardedalloc.h"
#include "IMB_imbuf_types.h"
@@ -1491,6 +1492,35 @@ void BKE_tracking_stabilization_data_get(MovieClip *clip,
discard_stabilization_working_context(ctx);
}
+
+typedef void (*interpolation_func)(struct ImBuf *, struct ImBuf *, float, float, int, int);
+
+typedef struct TrackingStabilizeFrameInterpolationData {
+ ImBuf *ibuf;
+ ImBuf *tmpibuf;
+ float (*mat)[4];
+
+ interpolation_func interpolation;
+} TrackingStabilizeFrameInterpolationData;
+
+static void tracking_stabilize_frame_interpolation_cb(void *userdata, int j)
+{
+ TrackingStabilizeFrameInterpolationData *data = userdata;
+ ImBuf *ibuf = data->ibuf;
+ ImBuf *tmpibuf = data->tmpibuf;
+ float (*mat)[4] = data->mat;
+
+ interpolation_func interpolation = data->interpolation;
+
+ for (int i = 0; i < tmpibuf->x; i++) {
+ float vec[3] = {i, j, 0.0f};
+
+ mul_v3_m4v3(vec, mat, vec);
+
+ interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j);
+ }
+}
+
/* Stabilize given image buffer using stabilization data for a specified
* frame number.
*
@@ -1511,8 +1541,8 @@ ImBuf *BKE_tracking_stabilize_frame(MovieClip *clip,
int width = ibuf->x, height = ibuf->y;
float pixel_aspect = tracking->camera.pixel_aspect;
float mat[4][4];
- int j, filter = tracking->stabilization.filter;
- void (*interpolation)(struct ImBuf *, struct ImBuf *, float, float, int, int) = NULL;
+ int filter = tracking->stabilization.filter;
+ interpolation_func interpolation = NULL;
int ibuf_flags;
if (translation)
@@ -1563,24 +1593,14 @@ ImBuf *BKE_tracking_stabilize_frame(MovieClip *clip,
/* fallback to default interpolation method */
interpolation = nearest_interpolation;
- /* This function is only used for display in clip editor and
- * sequencer only, which would only benefit of using threads
- * here.
- *
- * But need to keep an eye on this if the function will be
- * used in other cases.
- */
-#pragma omp parallel for if (tmpibuf->y > 128)
- for (j = 0; j < tmpibuf->y; j++) {
- int i;
- for (i = 0; i < tmpibuf->x; i++) {
- float vec[3] = {i, j, 0.0f};
-
- mul_v3_m4v3(vec, mat, vec);
-
- interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j);
- }
- }
+ TrackingStabilizeFrameInterpolationData data = {
+ .ibuf = ibuf, .tmpibuf = tmpibuf, .mat = mat,
+ .interpolation = interpolation
+ };
+ BLI_task_parallel_range(0, tmpibuf->y,
+ &data,
+ tracking_stabilize_frame_interpolation_cb,
+ tmpibuf->y > 128);
if (tmpibuf->rect_float)
tmpibuf->userflags |= IB_RECT_INVALID;
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index b42a36a3567..2720c0058b7 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -257,6 +257,10 @@ void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp,
const unsigned int nentries_reserve);
void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp);
+/* When set's are used for key & value. */
+void *BLI_gset_lookup(GSet *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
+void *BLI_gset_pop_key(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT;
+
GSet *BLI_gset_ptr_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
GSet *BLI_gset_ptr_new(const char *info);
GSet *BLI_gset_str_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index b06944e4985..1e931e6f0d7 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -50,12 +50,14 @@ void *BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED
void *BLI_findstring(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
void *BLI_findstring_ptr(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
void *BLI_findptr(const struct ListBase *listbase, const void *ptr, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void *BLI_listbase_bytes_find(const ListBase *listbase, const void *bytes, const size_t bytes_size, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
/* find backwards */
void *BLI_rfindlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
void *BLI_rfindstring(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
void *BLI_rfindstring_ptr(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
void *BLI_rfindptr(const struct ListBase *listbase, const void *ptr, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void *BLI_listbase_bytes_rfind(const ListBase *listbase, const void *bytes, const size_t bytes_size, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1);
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
@@ -77,6 +79,7 @@ int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
void BLI_listbase_swaplinks(struct ListBase *listbase, void *vlinka, void *vlinkb) ATTR_NONNULL(1, 2);
+void BLI_listbases_swaplinks(struct ListBase *listbasea, struct ListBase *listbaseb, void *vlinka, void *vlinkb) ATTR_NONNULL(2, 3);
void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1, 2);
void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1, 2);
diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h
index 5e6b1256d30..34fc52c12c0 100644
--- a/source/blender/blenlib/BLI_math_color.h
+++ b/source/blender/blenlib/BLI_math_color.h
@@ -141,7 +141,11 @@ MINLINE void float_to_byte_dither_v3(unsigned char b[3], const float f[3], float
#define rgba_char_args_set_fl(col, r, g, b, a) \
rgba_char_args_set(col, (r) * 255, (g) * 255, (b) * 255, (a) * 255)
+#define rgba_float_args_set_ch(col, r, g, b, a) \
+ rgba_float_args_set(col, (r) / 255.0f, (g) / 255.0f, (b) / 255.0f, (a) / 255.0f)
+
MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const char b, const char a);
+MINLINE void rgba_float_args_set(float col[4], const float r, const float g, const float b, const float a);
MINLINE void rgba_char_args_test_set(char col[4], const char r, const char g, const char b, const char a);
MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack);
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index d0dfad2a02f..173ef6861e6 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -210,6 +210,7 @@ void scale_m4_fl(float R[4][4], float scale);
float mat3_to_scale(float M[3][3]);
float mat4_to_scale(float M[4][4]);
+float mat4_to_xy_scale(float M[4][4]);
void size_to_mat3(float R[3][3], const float size[3]);
void size_to_mat4(float R[4][4], const float size[3]);
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 4fdb33926a2..3f603311530 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -151,6 +151,7 @@ MINLINE void negate_v3_short(short r[3]);
MINLINE void negate_v3_db(double r[3]);
MINLINE void invert_v2(float r[2]);
+MINLINE void invert_v3(float r[3]);
MINLINE void abs_v2(float r[2]);
MINLINE void abs_v2_v2(float r[2], const float a[2]);
@@ -311,6 +312,7 @@ void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]);
void ortho_v3_v3(float out[3], const float v[3]);
void ortho_v2_v2(float out[2], const float v[2]);
void bisect_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3]);
+void rotate_v2_v2fl(float r[2], const float p[2], const float angle);
void rotate_v3_v3v3fl(float v[3], const float p[3], const float axis[3], const float angle);
void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axis[3], const float angle);
@@ -326,6 +328,7 @@ void print_vn(const char *str, const float v[], const int n);
#define print_v4_id(v) print_v4(STRINGIFY(v), v)
#define print_vn_id(v, n) print_vn(STRINGIFY(v), v, n)
+MINLINE void normal_float_to_short_v2(short r[2], const float n[2]);
MINLINE void normal_short_to_float_v3(float r[3], const short n[3]);
MINLINE void normal_float_to_short_v3(short r[3], const float n[3]);
diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h
index 0c754f551e0..b68ca6b1f2b 100644
--- a/source/blender/blenlib/BLI_mempool.h
+++ b/source/blender/blenlib/BLI_mempool.h
@@ -71,6 +71,8 @@ typedef struct BLI_mempool_iter {
BLI_mempool *pool;
struct BLI_mempool_chunk *curchunk;
unsigned int curindex;
+
+ struct BLI_mempool_chunk **curchunk_threaded_shared;
} BLI_mempool_iter;
/* flag */
@@ -87,6 +89,9 @@ enum {
void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) ATTR_NONNULL();
void *BLI_mempool_iterstep(BLI_mempool_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_mempool_iter *BLI_mempool_iter_threadsafe_create(BLI_mempool *pool, const size_t num_iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BLI_mempool_iter_threadsafe_free(BLI_mempool_iter *iter_arr) ATTR_NONNULL();
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h
index f36d2faa1b8..69b23b2473f 100644
--- a/source/blender/blenlib/BLI_rand.h
+++ b/source/blender/blenlib/BLI_rand.h
@@ -101,4 +101,16 @@ RNG_THREAD_ARRAY *BLI_rng_threaded_new(void);
void BLI_rng_threaded_free(struct RNG_THREAD_ARRAY *rngarr) ATTR_NONNULL(1);
int BLI_rng_thread_rand(RNG_THREAD_ARRAY *rngarr, int thread) ATTR_WARN_UNUSED_RESULT;
+/** Low-discrepancy sequences **/
+
+/** Return the _n_th number of the given low-discrepancy sequence. */
+void BLI_halton_1D(unsigned int prime, double offset, int n, double *r);
+void BLI_halton_2D(unsigned int prime[2], double offset[2], int n, double *r);
+void BLI_halton_3D(unsigned int prime[3], double offset[3], int n, double *r);
+void BLI_hammersley_1D(unsigned int n, double *r);
+
+/** Return the whole low-discrepancy sequence up to _n_. */
+void BLI_halton_2D_sequence(unsigned int prime[2], double offset[2], int n, double *r);
+void BLI_hammersley_2D_sequence(unsigned int n, double *r);
+
#endif /* __BLI_RAND_H__ */
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index 721327d26a8..ccfa2b6e2e7 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -35,6 +35,8 @@ extern "C" {
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+struct BLI_mempool;
+
/* Task Scheduler
*
* Central scheduler that holds running threads ready to execute tasks. A single
@@ -150,6 +152,15 @@ void BLI_task_parallel_listbase(
TaskParallelListbaseFunc func,
const bool use_threading);
+typedef struct MempoolIterData MempoolIterData;
+typedef void (*TaskParallelMempoolFunc)(void *userdata,
+ MempoolIterData *iter);
+void BLI_task_parallel_mempool(
+ struct BLI_mempool *mempool,
+ void *userdata,
+ TaskParallelMempoolFunc func,
+ const bool use_threading);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h
index 0b1b4d8ee8c..60da6b39cbe 100644
--- a/source/blender/blenlib/BLI_threads.h
+++ b/source/blender/blenlib/BLI_threads.h
@@ -111,8 +111,10 @@ void BLI_mutex_unlock(ThreadMutex *mutex);
/* Spin Lock */
-#ifdef __APPLE__
+#if defined(__APPLE__)
typedef OSSpinLock SpinLock;
+#elif defined(_MSC_VER)
+typedef volatile int SpinLock;
#else
typedef pthread_spinlock_t SpinLock;
#endif
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 66c7f247f61..ee1acc5afdd 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -509,6 +509,16 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size);
#define SET_UINT_IN_POINTER(i) ((void *)(uintptr_t)(i))
#define GET_UINT_FROM_POINTER(i) ((void)0, ((unsigned int)(uintptr_t)(i)))
+/* Set flag from a single test */
+#define SET_FLAG_FROM_TEST(value, test, flag) \
+{ \
+ if (test) { \
+ (value) |= (flag); \
+ } \
+ else { \
+ (value) &= ~(flag); \
+ } \
+} ((void)0)
/* Macro to convert a value to string in the preprocessor
* STRINGIFY_ARG: gives the argument as a string
@@ -609,6 +619,9 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size);
/* BLI_assert(), default only to print
* for aborting need to define WITH_ASSERT_ABORT
*/
+/* For 'abort' only. */
+#include <stdlib.h>
+
#ifndef NDEBUG
# include "BLI_system.h"
# ifdef WITH_ASSERT_ABORT
@@ -647,10 +660,29 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size);
(defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */
# define BLI_STATIC_ASSERT(a, msg) __extension__ _Static_assert(a, msg);
#else
- /* TODO msvc, clang */
-# define BLI_STATIC_ASSERT(a, msg)
+/* Code adapted from http://www.pixelbeat.org/programming/gcc/static_assert.html */
+/* Note we need the two concats below because arguments to ## are not expanded, so we need to
+ * expand __LINE__ with one indirection before doing the actual concatenation. */
+# define ASSERT_CONCAT_(a, b) a##b
+# define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
+ /* These can't be used after statements in c89. */
+# if defined(__COUNTER__) /* MSVC */
+# define BLI_STATIC_ASSERT(a, msg) \
+ ; enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1 / (int)(!!(a)) };
+# else /* older gcc, clang... */
+ /* This can't be used twice on the same line so ensure if using in headers
+ * that the headers are not included twice (by wrapping in #ifndef...#endif)
+ * Note it doesn't cause an issue when used on same line of separate modules
+ * compiled with gcc -combine -fwhole-program. */
+# define BLI_STATIC_ASSERT(a, msg) \
+ ; enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1 / (int)(!!(a)) };
+# endif
#endif
+
+#define BLI_STATIC_ASSERT_ALIGN(st, align) \
+ BLI_STATIC_ASSERT((sizeof(st) % (align) == 0), "Structure must be strictly aligned")
+
/* hints for branch prediction, only use in code that runs a _lot_ where */
#ifdef __GNUC__
# define LIKELY(x) __builtin_expect(!!(x), 1)
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 1b2a27e33d8..28e98c17a9d 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -53,7 +53,7 @@
#define GHASH_USE_MODULO_BUCKETS
/* Also used by smallhash! */
-const unsigned int hashsizes[] = {
+const uint hashsizes[] = {
5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
4194319, 8388617, 16777259, 33554467, 67108879, 134217757,
@@ -103,16 +103,16 @@ struct GHash {
Entry **buckets;
struct BLI_mempool *entrypool;
- unsigned int nbuckets;
- unsigned int limit_grow, limit_shrink;
+ uint nbuckets;
+ uint limit_grow, limit_shrink;
#ifdef GHASH_USE_MODULO_BUCKETS
- unsigned int cursize, size_min;
+ uint cursize, size_min;
#else
- unsigned int bucket_mask, bucket_bit, bucket_bit_min;
+ uint bucket_mask, bucket_bit, bucket_bit_min;
#endif
- unsigned int nentries;
- unsigned int flag;
+ uint nentries;
+ uint flag;
};
@@ -141,7 +141,7 @@ BLI_INLINE void ghash_entry_copy(
/**
* Get the full hash for a key.
*/
-BLI_INLINE unsigned int ghash_keyhash(GHash *gh, const void *key)
+BLI_INLINE uint ghash_keyhash(GHash *gh, const void *key)
{
return gh->hashfp(key);
}
@@ -149,7 +149,7 @@ BLI_INLINE unsigned int ghash_keyhash(GHash *gh, const void *key)
/**
* Get the full hash for an entry.
*/
-BLI_INLINE unsigned int ghash_entryhash(GHash *gh, const Entry *e)
+BLI_INLINE uint ghash_entryhash(GHash *gh, const Entry *e)
{
return gh->hashfp(e->key);
}
@@ -157,7 +157,7 @@ BLI_INLINE unsigned int ghash_entryhash(GHash *gh, const Entry *e)
/**
* Get the bucket-index for an already-computed full hash.
*/
-BLI_INLINE unsigned int ghash_bucket_index(GHash *gh, const unsigned int hash)
+BLI_INLINE uint ghash_bucket_index(GHash *gh, const uint hash)
{
#ifdef GHASH_USE_MODULO_BUCKETS
return hash % gh->nbuckets;
@@ -169,7 +169,7 @@ BLI_INLINE unsigned int ghash_bucket_index(GHash *gh, const unsigned int hash)
/**
* Find the index of next used bucket, starting from \a curr_bucket (\a gh is assumed non-empty).
*/
-BLI_INLINE unsigned int ghash_find_next_bucket_index(GHash *gh, unsigned int curr_bucket)
+BLI_INLINE uint ghash_find_next_bucket_index(GHash *gh, uint curr_bucket)
{
if (curr_bucket >= gh->nbuckets) {
curr_bucket = 0;
@@ -194,12 +194,12 @@ BLI_INLINE unsigned int ghash_find_next_bucket_index(GHash *gh, unsigned int cur
/**
* Expand buckets to the next size up or down.
*/
-static void ghash_buckets_resize(GHash *gh, const unsigned int nbuckets)
+static void ghash_buckets_resize(GHash *gh, const uint nbuckets)
{
Entry **buckets_old = gh->buckets;
Entry **buckets_new;
- const unsigned int nbuckets_old = gh->nbuckets;
- unsigned int i;
+ const uint nbuckets_old = gh->nbuckets;
+ uint i;
BLI_assert((gh->nbuckets != nbuckets) || !gh->buckets);
// printf("%s: %d -> %d\n", __func__, nbuckets_old, nbuckets);
@@ -261,9 +261,9 @@ static void ghash_buckets_resize(GHash *gh, const unsigned int nbuckets)
* or small enough to require less buckets, and resize \a gh accordingly.
*/
static void ghash_buckets_expand(
- GHash *gh, const unsigned int nentries, const bool user_defined)
+ GHash *gh, const uint nentries, const bool user_defined)
{
- unsigned int new_nbuckets;
+ uint new_nbuckets;
if (LIKELY(gh->buckets && (nentries < gh->limit_grow))) {
return;
@@ -305,9 +305,9 @@ static void ghash_buckets_expand(
}
static void ghash_buckets_contract(
- GHash *gh, const unsigned int nentries, const bool user_defined, const bool force_shrink)
+ GHash *gh, const uint nentries, const bool user_defined, const bool force_shrink)
{
- unsigned int new_nbuckets;
+ uint new_nbuckets;
if (!(force_shrink || (gh->flag & GHASH_FLAG_ALLOW_SHRINK))) {
return;
@@ -355,7 +355,7 @@ static void ghash_buckets_contract(
/**
* Clear and reset \a gh buckets, reserve again buckets for given number of entries.
*/
-BLI_INLINE void ghash_buckets_reset(GHash *gh, const unsigned int nentries)
+BLI_INLINE void ghash_buckets_reset(GHash *gh, const uint nentries)
{
MEM_SAFE_FREE(gh->buckets);
@@ -383,7 +383,7 @@ BLI_INLINE void ghash_buckets_reset(GHash *gh, const unsigned int nentries)
* Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times.
*/
BLI_INLINE Entry *ghash_lookup_entry_ex(
- GHash *gh, const void *key, const unsigned int bucket_index)
+ GHash *gh, const void *key, const uint bucket_index)
{
Entry *e;
/* If we do not store GHash, not worth computing it for each entry here!
@@ -404,7 +404,7 @@ BLI_INLINE Entry *ghash_lookup_entry_ex(
*/
BLI_INLINE Entry *ghash_lookup_entry_prev_ex(
GHash *gh, const void *key,
- Entry **r_e_prev, const unsigned int bucket_index)
+ Entry **r_e_prev, const uint bucket_index)
{
/* If we do not store GHash, not worth computing it for each entry here!
* Typically, comparison function will be quicker, and since it's needed in the end anyway... */
@@ -424,13 +424,13 @@ BLI_INLINE Entry *ghash_lookup_entry_prev_ex(
*/
BLI_INLINE Entry *ghash_lookup_entry(GHash *gh, const void *key)
{
- const unsigned int hash = ghash_keyhash(gh, key);
- const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ const uint hash = ghash_keyhash(gh, key);
+ const uint bucket_index = ghash_bucket_index(gh, hash);
return ghash_lookup_entry_ex(gh, key, bucket_index);
}
static GHash *ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
- const unsigned int nentries_reserve, const unsigned int flag)
+ const uint nentries_reserve, const uint flag)
{
GHash *gh = MEM_mallocN(sizeof(*gh), info);
@@ -451,7 +451,7 @@ static GHash *ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
* Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times.
*/
BLI_INLINE void ghash_insert_ex(
- GHash *gh, void *key, void *val, const unsigned int bucket_index)
+ GHash *gh, void *key, void *val, const uint bucket_index)
{
GHashEntry *e = BLI_mempool_alloc(gh->entrypool);
@@ -470,7 +470,7 @@ BLI_INLINE void ghash_insert_ex(
* Insert function that takes a pre-allocated entry.
*/
BLI_INLINE void ghash_insert_ex_keyonly_entry(
- GHash *gh, void *key, const unsigned int bucket_index,
+ GHash *gh, void *key, const uint bucket_index,
Entry *e)
{
BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0));
@@ -486,7 +486,7 @@ BLI_INLINE void ghash_insert_ex_keyonly_entry(
* Insert function that doesn't set the value (use for GSet)
*/
BLI_INLINE void ghash_insert_ex_keyonly(
- GHash *gh, void *key, const unsigned int bucket_index)
+ GHash *gh, void *key, const uint bucket_index)
{
Entry *e = BLI_mempool_alloc(gh->entrypool);
@@ -502,8 +502,8 @@ BLI_INLINE void ghash_insert_ex_keyonly(
BLI_INLINE void ghash_insert(GHash *gh, void *key, void *val)
{
- const unsigned int hash = ghash_keyhash(gh, key);
- const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ const uint hash = ghash_keyhash(gh, key);
+ const uint bucket_index = ghash_bucket_index(gh, hash);
ghash_insert_ex(gh, key, val, bucket_index);
}
@@ -512,8 +512,8 @@ BLI_INLINE bool ghash_insert_safe(
GHash *gh, void *key, void *val, const bool override,
GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
- const unsigned int hash = ghash_keyhash(gh, key);
- const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ const uint hash = ghash_keyhash(gh, key);
+ const uint bucket_index = ghash_bucket_index(gh, hash);
GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index);
BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET));
@@ -541,8 +541,8 @@ BLI_INLINE bool ghash_insert_safe_keyonly(
GHash *gh, void *key, const bool override,
GHashKeyFreeFP keyfreefp)
{
- const unsigned int hash = ghash_keyhash(gh, key);
- const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ const uint hash = ghash_keyhash(gh, key);
+ const uint bucket_index = ghash_bucket_index(gh, hash);
Entry *e = ghash_lookup_entry_ex(gh, key, bucket_index);
BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0);
@@ -568,7 +568,7 @@ BLI_INLINE bool ghash_insert_safe_keyonly(
static Entry *ghash_remove_ex(
GHash *gh, const void *key,
GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
- const unsigned int bucket_index)
+ const uint bucket_index)
{
Entry *e_prev;
Entry *e = ghash_lookup_entry_prev_ex(gh, key, &e_prev, bucket_index);
@@ -601,7 +601,7 @@ static Entry *ghash_remove_ex(
*/
static Entry *ghash_pop(GHash *gh, GHashIterState *state)
{
- unsigned int curr_bucket = state->curr_bucket;
+ uint curr_bucket = state->curr_bucket;
if (gh->nentries == 0) {
return NULL;
}
@@ -626,7 +626,7 @@ static void ghash_free_cb(
GHash *gh,
GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
- unsigned int i;
+ uint i;
BLI_assert(keyfreefp || valfreefp);
BLI_assert(!valfreefp || !(gh->flag & GHASH_FLAG_IS_GSET));
@@ -651,9 +651,9 @@ static void ghash_free_cb(
static GHash *ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp)
{
GHash *gh_new;
- unsigned int i;
+ uint i;
/* This allows us to be sure to get the same number of buckets in gh_new as in ghash. */
- const unsigned int reserve_nentries_new = MAX2(GHASH_LIMIT_GROW(gh->nbuckets) - 1, gh->nentries);
+ const uint reserve_nentries_new = MAX2(GHASH_LIMIT_GROW(gh->nbuckets) - 1, gh->nentries);
BLI_assert(!valcopyfp || !(gh->flag & GHASH_FLAG_IS_GSET));
@@ -700,7 +700,7 @@ static GHash *ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP val
* \return An empty GHash.
*/
GHash *BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
- const unsigned int nentries_reserve)
+ const uint nentries_reserve)
{
return ghash_new(hashfp, cmpfp, info, nentries_reserve, 0);
}
@@ -724,7 +724,7 @@ GHash *BLI_ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcop
/**
* Reserve given amount of entries (resize \a gh accordingly if needed).
*/
-void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve)
+void BLI_ghash_reserve(GHash *gh, const uint nentries_reserve)
{
ghash_buckets_expand(gh, nentries_reserve, true);
ghash_buckets_contract(gh, nentries_reserve, true, false);
@@ -733,7 +733,7 @@ void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve)
/**
* \return size of the GHash.
*/
-unsigned int BLI_ghash_size(GHash *gh)
+uint BLI_ghash_size(GHash *gh)
{
return gh->nentries;
}
@@ -771,8 +771,8 @@ bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreef
*/
void *BLI_ghash_replace_key(GHash *gh, void *key)
{
- const unsigned int hash = ghash_keyhash(gh, key);
- const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ const uint hash = ghash_keyhash(gh, key);
+ const uint bucket_index = ghash_bucket_index(gh, hash);
GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index);
if (e != NULL) {
void *key_prev = e->e.key;
@@ -843,8 +843,8 @@ void **BLI_ghash_lookup_p(GHash *gh, const void *key)
*/
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val)
{
- const unsigned int hash = ghash_keyhash(gh, key);
- const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ const uint hash = ghash_keyhash(gh, key);
+ const uint bucket_index = ghash_bucket_index(gh, hash);
GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index);
const bool haskey = (e != NULL);
@@ -866,8 +866,8 @@ bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val)
bool BLI_ghash_ensure_p_ex(
GHash *gh, const void *key, void ***r_key, void ***r_val)
{
- const unsigned int hash = ghash_keyhash(gh, key);
- const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ const uint hash = ghash_keyhash(gh, key);
+ const uint bucket_index = ghash_bucket_index(gh, hash);
GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index);
const bool haskey = (e != NULL);
@@ -893,8 +893,8 @@ bool BLI_ghash_ensure_p_ex(
*/
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
- const unsigned int hash = ghash_keyhash(gh, key);
- const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ const uint hash = ghash_keyhash(gh, key);
+ const uint bucket_index = ghash_bucket_index(gh, hash);
Entry *e = ghash_remove_ex(gh, key, keyfreefp, valfreefp, bucket_index);
if (e) {
BLI_mempool_free(gh->entrypool, e);
@@ -916,8 +916,8 @@ bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHas
*/
void *BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp)
{
- const unsigned int hash = ghash_keyhash(gh, key);
- const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ const uint hash = ghash_keyhash(gh, key);
+ const uint bucket_index = ghash_bucket_index(gh, hash);
GHashEntry *e = (GHashEntry *)ghash_remove_ex(gh, key, keyfreefp, NULL, bucket_index);
BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET));
if (e) {
@@ -975,7 +975,7 @@ bool BLI_ghash_pop(
* \param nentries_reserve Optionally reserve the number of members that the hash will hold.
*/
void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
- const unsigned int nentries_reserve)
+ const uint nentries_reserve)
{
if (keyfreefp || valfreefp)
ghash_free_cb(gh, keyfreefp, valfreefp);
@@ -1013,7 +1013,7 @@ void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreef
/**
* Sets a GHash flag.
*/
-void BLI_ghash_flag_set(GHash *gh, unsigned int flag)
+void BLI_ghash_flag_set(GHash *gh, uint flag)
{
gh->flag |= flag;
}
@@ -1021,7 +1021,7 @@ void BLI_ghash_flag_set(GHash *gh, unsigned int flag)
/**
* Clear a GHash flag.
*/
-void BLI_ghash_flag_clear(GHash *gh, unsigned int flag)
+void BLI_ghash_flag_clear(GHash *gh, uint flag)
{
gh->flag &= ~flag;
}
@@ -1162,19 +1162,19 @@ bool BLI_ghashIterator_done(GHashIterator *ghi)
#if 0
/* works but slower */
-unsigned int BLI_ghashutil_ptrhash(const void *key)
+uint BLI_ghashutil_ptrhash(const void *key)
{
- return (unsigned int)(intptr_t)key;
+ return (uint)(intptr_t)key;
}
#else
/* based python3.3's pointer hashing function */
-unsigned int BLI_ghashutil_ptrhash(const void *key)
+uint BLI_ghashutil_ptrhash(const void *key)
{
size_t y = (size_t)key;
/* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid
* excessive hash collisions for dicts and sets */
y = (y >> 4) | (y << (8 * sizeof(void *) - 4));
- return (unsigned int)y;
+ return (uint)y;
}
#endif
bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
@@ -1182,9 +1182,9 @@ bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
return (a != b);
}
-unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4])
+uint BLI_ghashutil_uinthash_v4(const uint key[4])
{
- unsigned int hash;
+ uint hash;
hash = key[0];
hash *= 37;
hash += key[1];
@@ -1194,17 +1194,17 @@ unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4])
hash += key[3];
return hash;
}
-unsigned int BLI_ghashutil_uinthash_v4_murmur(const unsigned int key[4])
+uint BLI_ghashutil_uinthash_v4_murmur(const uint key[4])
{
return BLI_hash_mm2((const unsigned char *)key, sizeof(int) * 4 /* sizeof(key) */, 0);
}
bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b)
{
- return (memcmp(a, b, sizeof(unsigned int[4])) != 0);
+ return (memcmp(a, b, sizeof(uint[4])) != 0);
}
-unsigned int BLI_ghashutil_uinthash(unsigned int key)
+uint BLI_ghashutil_uinthash(uint key)
{
key += ~(key << 16);
key ^= (key >> 5);
@@ -1216,7 +1216,7 @@ unsigned int BLI_ghashutil_uinthash(unsigned int key)
return key;
}
-unsigned int BLI_ghashutil_inthash_p(const void *ptr)
+uint BLI_ghashutil_inthash_p(const void *ptr)
{
uintptr_t key = (uintptr_t)ptr;
@@ -1227,17 +1227,17 @@ unsigned int BLI_ghashutil_inthash_p(const void *ptr)
key += ~(key << 9);
key ^= (key >> 17);
- return (unsigned int)(key & 0xffffffff);
+ return (uint)(key & 0xffffffff);
}
-unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr)
+uint BLI_ghashutil_inthash_p_murmur(const void *ptr)
{
uintptr_t key = (uintptr_t)ptr;
return BLI_hash_mm2((const unsigned char *)&key, sizeof(key), 0);
}
-unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr)
+uint BLI_ghashutil_inthash_p_simple(const void *ptr)
{
return GET_UINT_FROM_POINTER(ptr);
}
@@ -1261,29 +1261,29 @@ size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b)
*
* note: this is the same hash method that glib 2.34.0 uses.
*/
-unsigned int BLI_ghashutil_strhash_n(const char *key, size_t n)
+uint BLI_ghashutil_strhash_n(const char *key, size_t n)
{
const signed char *p;
- unsigned int h = 5381;
+ uint h = 5381;
for (p = (const signed char *)key; n-- && *p != '\0'; p++) {
- h = (h << 5) + h + (unsigned int)*p;
+ h = (uint)((h << 5) + h) + (uint)*p;
}
return h;
}
-unsigned int BLI_ghashutil_strhash_p(const void *ptr)
+uint BLI_ghashutil_strhash_p(const void *ptr)
{
const signed char *p;
- unsigned int h = 5381;
+ uint h = 5381;
for (p = ptr; *p != '\0'; p++) {
- h = (h << 5) + h + (unsigned int)*p;
+ h = (uint)((h << 5) + h) + (uint)*p;
}
return h;
}
-unsigned int BLI_ghashutil_strhash_p_murmur(const void *ptr)
+uint BLI_ghashutil_strhash_p_murmur(const void *ptr)
{
const unsigned char *key = ptr;
@@ -1302,10 +1302,10 @@ GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second)
return pair;
}
-unsigned int BLI_ghashutil_pairhash(const void *ptr)
+uint BLI_ghashutil_pairhash(const void *ptr)
{
const GHashPair *pair = ptr;
- unsigned int hash = BLI_ghashutil_ptrhash(pair->first);
+ uint hash = BLI_ghashutil_ptrhash(pair->first);
return hash ^ BLI_ghashutil_ptrhash(pair->second);
}
@@ -1329,7 +1329,7 @@ void BLI_ghashutil_pairfree(void *ptr)
/** \name Convenience GHash Creation Functions
* \{ */
-GHash *BLI_ghash_ptr_new_ex(const char *info, const unsigned int nentries_reserve)
+GHash *BLI_ghash_ptr_new_ex(const char *info, const uint nentries_reserve)
{
return BLI_ghash_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve);
}
@@ -1338,7 +1338,7 @@ GHash *BLI_ghash_ptr_new(const char *info)
return BLI_ghash_ptr_new_ex(info, 0);
}
-GHash *BLI_ghash_str_new_ex(const char *info, const unsigned int nentries_reserve)
+GHash *BLI_ghash_str_new_ex(const char *info, const uint nentries_reserve)
{
return BLI_ghash_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve);
}
@@ -1347,7 +1347,7 @@ GHash *BLI_ghash_str_new(const char *info)
return BLI_ghash_str_new_ex(info, 0);
}
-GHash *BLI_ghash_int_new_ex(const char *info, const unsigned int nentries_reserve)
+GHash *BLI_ghash_int_new_ex(const char *info, const uint nentries_reserve)
{
return BLI_ghash_new_ex(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, info, nentries_reserve);
}
@@ -1356,7 +1356,7 @@ GHash *BLI_ghash_int_new(const char *info)
return BLI_ghash_int_new_ex(info, 0);
}
-GHash *BLI_ghash_pair_new_ex(const char *info, const unsigned int nentries_reserve)
+GHash *BLI_ghash_pair_new_ex(const char *info, const uint nentries_reserve)
{
return BLI_ghash_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve);
}
@@ -1376,7 +1376,7 @@ GHash *BLI_ghash_pair_new(const char *info)
/** \name GSet Functions
* \{ */
GSet *BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info,
- const unsigned int nentries_reserve)
+ const uint nentries_reserve)
{
return (GSet *)ghash_new(hashfp, cmpfp, info, nentries_reserve, GHASH_FLAG_IS_GSET);
}
@@ -1394,7 +1394,7 @@ GSet *BLI_gset_copy(GSet *gs, GHashKeyCopyFP keycopyfp)
return (GSet *)ghash_copy((GHash *)gs, keycopyfp, NULL);
}
-unsigned int BLI_gset_size(GSet *gs)
+uint BLI_gset_size(GSet *gs)
{
return ((GHash *)gs)->nentries;
}
@@ -1405,8 +1405,8 @@ unsigned int BLI_gset_size(GSet *gs)
*/
void BLI_gset_insert(GSet *gs, void *key)
{
- const unsigned int hash = ghash_keyhash((GHash *)gs, key);
- const unsigned int bucket_index = ghash_bucket_index((GHash *)gs, hash);
+ const uint hash = ghash_keyhash((GHash *)gs, key);
+ const uint bucket_index = ghash_bucket_index((GHash *)gs, hash);
ghash_insert_ex_keyonly((GHash *)gs, key, bucket_index);
}
@@ -1429,8 +1429,8 @@ bool BLI_gset_add(GSet *gs, void *key)
*/
bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key)
{
- const unsigned int hash = ghash_keyhash((GHash *)gs, key);
- const unsigned int bucket_index = ghash_bucket_index((GHash *)gs, hash);
+ const uint hash = ghash_keyhash((GHash *)gs, key);
+ const uint bucket_index = ghash_bucket_index((GHash *)gs, hash);
GSetEntry *e = (GSetEntry *)ghash_lookup_entry_ex((GHash *)gs, key, bucket_index);
const bool haskey = (e != NULL);
@@ -1505,7 +1505,7 @@ bool BLI_gset_pop(
}
void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp,
- const unsigned int nentries_reserve)
+ const uint nentries_reserve)
{
BLI_ghash_clear_ex((GHash *)gs, keyfreefp, NULL,
nentries_reserve);
@@ -1521,23 +1521,58 @@ void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
BLI_ghash_free((GHash *)gs, keyfreefp, NULL);
}
-void BLI_gset_flag_set(GSet *gs, unsigned int flag)
+void BLI_gset_flag_set(GSet *gs, uint flag)
{
((GHash *)gs)->flag |= flag;
}
-void BLI_gset_flag_clear(GSet *gs, unsigned int flag)
+void BLI_gset_flag_clear(GSet *gs, uint flag)
{
((GHash *)gs)->flag &= ~flag;
}
/** \} */
+/** \name GSet Combined Key/Value Usage
+ *
+ * \note Not typical ``set`` use, only use when the pointer identity matters.
+ * This can be useful when the key references data stored outside the GSet.
+ * \{ */
+
+/**
+ * Returns the pointer to the key if it's found.
+ */
+void *BLI_gset_lookup(GSet *gs, const void *key)
+{
+ Entry *e = ghash_lookup_entry((GHash *)gs, key);
+ return e ? e->key : NULL;
+}
+
+/**
+ * Returns the pointer to the key if it's found, removing it from the GSet.
+ * \node Caller must handle freeing.
+ */
+void *BLI_gset_pop_key(GSet *gs, const void *key)
+{
+ const uint hash = ghash_keyhash((GHash *)gs, key);
+ const uint bucket_index = ghash_bucket_index((GHash *)gs, hash);
+ Entry *e = ghash_remove_ex((GHash *)gs, key, NULL, NULL, bucket_index);
+ if (e) {
+ void *key_ret = e->key;
+ BLI_mempool_free(((GHash *)gs)->entrypool, e);
+ return key_ret;
+ }
+ else {
+ return NULL;
+ }
+}
+
+/** \} */
/** \name Convenience GSet Creation Functions
* \{ */
-GSet *BLI_gset_ptr_new_ex(const char *info, const unsigned int nentries_reserve)
+GSet *BLI_gset_ptr_new_ex(const char *info, const uint nentries_reserve)
{
return BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve);
}
@@ -1546,7 +1581,7 @@ GSet *BLI_gset_ptr_new(const char *info)
return BLI_gset_ptr_new_ex(info, 0);
}
-GSet *BLI_gset_str_new_ex(const char *info, const unsigned int nentries_reserve)
+GSet *BLI_gset_str_new_ex(const char *info, const uint nentries_reserve)
{
return BLI_gset_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve);
}
@@ -1555,7 +1590,7 @@ GSet *BLI_gset_str_new(const char *info)
return BLI_gset_str_new_ex(info, 0);
}
-GSet *BLI_gset_pair_new_ex(const char *info, const unsigned int nentries_reserve)
+GSet *BLI_gset_pair_new_ex(const char *info, const uint nentries_reserve)
{
return BLI_gset_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve);
}
@@ -1595,7 +1630,7 @@ double BLI_ghash_calc_quality_ex(
double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket)
{
double mean;
- unsigned int i;
+ uint i;
if (gh->nentries == 0) {
if (r_load) {
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index b02811616dd..5b13f129ad4 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -41,6 +41,8 @@
#include <string.h>
#include <stdlib.h>
+#include "atomic_ops.h"
+
#include "BLI_utildefines.h"
#include "BLI_mempool.h" /* own include */
@@ -553,7 +555,7 @@ void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr)
}
/**
- * Create a new mempool iterator, \a BLI_MEMPOOL_ALLOW_ITER flag must be set.
+ * Initialize a new mempool iterator, \a BLI_MEMPOOL_ALLOW_ITER flag must be set.
*/
void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter)
{
@@ -562,6 +564,47 @@ void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter)
iter->pool = pool;
iter->curchunk = pool->chunks;
iter->curindex = 0;
+
+ iter->curchunk_threaded_shared = NULL;
+}
+
+/**
+ * Initialize an array of mempool iterators, \a BLI_MEMPOOL_ALLOW_ITER flag must be set.
+ *
+ * This is used in threaded code, to generate as much iterators as needed (each task should have its own),
+ * such that each iterator goes over its own single chunk, and only getting the next chunk to iterate over has to be
+ * protected against concurrency (which can be done in a lockless way).
+ *
+ * To be used when creating a task for each single item in the pool is totally overkill.
+ *
+ * See BLI_task_parallel_mempool implementation for detailed usage example.
+ */
+BLI_mempool_iter *BLI_mempool_iter_threadsafe_create(BLI_mempool *pool, const size_t num_iter)
+{
+ BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER);
+
+ BLI_mempool_iter *iter_arr = MEM_mallocN(sizeof(*iter_arr) * num_iter, __func__);
+ BLI_mempool_chunk **curchunk_threaded_shared = MEM_mallocN(sizeof(void *), __func__);
+
+ BLI_mempool_iternew(pool, iter_arr);
+
+ *curchunk_threaded_shared = iter_arr->curchunk;
+ iter_arr->curchunk_threaded_shared = curchunk_threaded_shared;
+
+ for (size_t i = 1; i < num_iter; i++) {
+ iter_arr[i] = iter_arr[0];
+ *curchunk_threaded_shared = iter_arr[i].curchunk = (*curchunk_threaded_shared) ? (*curchunk_threaded_shared)->next : NULL;
+ }
+
+ return iter_arr;
+}
+
+void BLI_mempool_iter_threadsafe_free(BLI_mempool_iter *iter_arr)
+{
+ BLI_assert(iter_arr->curchunk_threaded_shared != NULL);
+
+ MEM_freeN(iter_arr->curchunk_threaded_shared);
+ MEM_freeN(iter_arr);
}
#if 0
@@ -571,15 +614,28 @@ static void *bli_mempool_iternext(BLI_mempool_iter *iter)
{
void *ret = NULL;
- if (!iter->curchunk || !iter->pool->totused) return NULL;
+ if (iter->curchunk == NULL || !iter->pool->totused) {
+ return ret;
+ }
ret = ((char *)CHUNK_DATA(iter->curchunk)) + (iter->pool->esize * iter->curindex);
iter->curindex++;
if (iter->curindex == iter->pool->pchunk) {
- iter->curchunk = iter->curchunk->next;
iter->curindex = 0;
+ if (iter->curchunk_threaded_shared) {
+ while (1) {
+ iter->curchunk = *iter->curchunk_threaded_shared;
+ if (iter->curchunk == NULL) {
+ return ret;
+ }
+ if (atomic_cas_ptr((void **)iter->curchunk_threaded_shared, iter->curchunk, iter->curchunk->next) == iter->curchunk) {
+ break;
+ }
+ }
+ }
+ iter->curchunk = iter->curchunk->next;
}
return ret;
@@ -620,8 +676,18 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
}
else {
iter->curindex = 0;
+ if (iter->curchunk_threaded_shared) {
+ for (iter->curchunk = *iter->curchunk_threaded_shared;
+ (iter->curchunk != NULL) &&
+ (atomic_cas_ptr((void **)iter->curchunk_threaded_shared, iter->curchunk, iter->curchunk->next) != iter->curchunk);
+ iter->curchunk = *iter->curchunk_threaded_shared);
+
+ if (UNLIKELY(iter->curchunk == NULL)) {
+ return (ret->freeword == FREEWORD) ? NULL : ret;
+ }
+ }
iter->curchunk = iter->curchunk->next;
- if (iter->curchunk == NULL) {
+ if (UNLIKELY(iter->curchunk == NULL)) {
return (ret->freeword == FREEWORD) ? NULL : ret;
}
curnode = CHUNK_DATA(iter->curchunk);
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index 46dcee48eda..d2cf0cf49a2 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -170,6 +170,34 @@ void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb)
}
/**
+ * Swaps \a vlinka and \a vlinkb from their respective lists. Assumes they are both already in their lista!
+ */
+void BLI_listbases_swaplinks(ListBase *listbasea, ListBase *listbaseb, void *vlinka, void *vlinkb)
+{
+ Link *linka = vlinka;
+ Link *linkb = vlinkb;
+ Link linkc = {NULL};
+
+ if (!linka || !linkb) {
+ return;
+ }
+
+ /* Temporary link to use as placeholder of the links positions */
+ BLI_insertlinkafter(listbasea, linka, &linkc);
+
+ /* Bring linka into linkb position */
+ BLI_remlink(listbasea, linka);
+ BLI_insertlinkafter(listbaseb, linkb, linka);
+
+ /* Bring linkb into linka position */
+ BLI_remlink(listbaseb, linkb);
+ BLI_insertlinkafter(listbasea, &linkc, linkb);
+
+ /* Remove temporary link */
+ BLI_remlink(listbasea, &linkc);
+}
+
+/**
* Removes the head from \a listbase and returns it.
*/
void *BLI_pophead(ListBase *listbase)
@@ -664,6 +692,46 @@ void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset)
}
/**
+ * Finds the first element of listbase which contains the specified bytes
+ * at the specified offset, returning NULL if not found.
+ */
+void *BLI_listbase_bytes_find(const ListBase *listbase, const void *bytes, const size_t bytes_size, const int offset)
+{
+ Link *link = NULL;
+ const void *ptr_iter;
+
+ for (link = listbase->first; link; link = link->next) {
+ ptr_iter = (const void *)(((const char *)link) + offset);
+
+ if (memcmp(bytes, ptr_iter, bytes_size) == 0) {
+ return link;
+ }
+ }
+
+ return NULL;
+}
+/* same as above but find reverse */
+/**
+ * Finds the last element of listbase which contains the specified bytes
+ * at the specified offset, returning NULL if not found.
+ */
+void *BLI_listbase_bytes_rfind(const ListBase *listbase, const void *bytes, const size_t bytes_size, const int offset)
+{
+ Link *link = NULL;
+ const void *ptr_iter;
+
+ for (link = listbase->last; link; link = link->prev) {
+ ptr_iter = (const void *)(((const char *)link) + offset);
+
+ if (memcmp(bytes, ptr_iter, bytes_size) == 0) {
+ return link;
+ }
+ }
+
+ return NULL;
+}
+
+/**
* Returns the 0-based index of the first element of listbase which contains the specified
* null-terminated string at the specified offset, or -1 if not found.
*/
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index 01a805a09b6..bc3a1ee3e90 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -239,6 +239,14 @@ MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const c
col[3] = a;
}
+MINLINE void rgba_float_args_set(float col[4], const float r, const float g, const float b, const float a)
+{
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
+ col[3] = a;
+}
+
MINLINE void rgba_char_args_test_set(char col[4], const char r, const char g, const char b, const char a)
{
if (col[3] == 0) {
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index d1a219c196a..311d963f64d 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -1523,6 +1523,15 @@ float mat4_to_scale(float mat[4][4])
return len_v3(unit_vec);
}
+/** Return 2D scale (in XY plane) of given mat4. */
+float mat4_to_xy_scale(float M[4][4])
+{
+ /* unit length vector in xy plane */
+ float unit_vec[3] = {(float)M_SQRT1_2, (float)M_SQRT1_2, 0.0f};
+ mul_mat3_m4_v3(M, unit_vec);
+ return len_v3(unit_vec);
+}
+
void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3])
{
/* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */
@@ -1625,6 +1634,7 @@ void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
mat[3][2] += (Tx * mat[0][2] + Ty * mat[1][2] + Tz * mat[2][2]);
}
+/* TODO: enum for axis? */
/**
* Rotate a matrix in-place.
*
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 5f44c93e169..05562502278 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -850,6 +850,20 @@ void ortho_v2_v2(float out[2], const float v[2])
}
/**
+ * Rotate a point \a p by \a angle around origin (0, 0)
+ */
+void rotate_v2_v2fl(float r[2], const float p[2], const float angle)
+{
+ const float co = cosf(angle);
+ const float si = sinf(angle);
+
+ BLI_assert(r != p);
+
+ r[0] = co * p[0] - si * p[1];
+ r[1] = si * p[0] + co * p[1];
+}
+
+/**
* Rotate a point \a p by \a angle around an arbitrary unit length \a axis.
* http://local.wasp.uwa.edu.au/~pbourke/geometry/
*/
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index ee5e8651bd3..08687a1ab47 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -658,6 +658,14 @@ MINLINE void invert_v2(float r[2])
r[1] = 1.0f / r[1];
}
+MINLINE void invert_v3(float r[3])
+{
+ BLI_assert(!ELEM(0.0f, r[0], r[1], r[2]));
+ r[0] = 1.0f / r[0];
+ r[1] = 1.0f / r[1];
+ r[2] = 1.0f / r[2];
+}
+
MINLINE void abs_v2(float r[2])
{
r[0] = fabsf(r[0]);
@@ -960,6 +968,12 @@ MINLINE float normalize_v3(float n[3])
return normalize_v3_v3(n, n);
}
+MINLINE void normal_float_to_short_v2(short out[2], const float in[2])
+{
+ out[0] = (short) (in[0] * 32767.0f);
+ out[1] = (short) (in[1] * 32767.0f);
+}
+
MINLINE void normal_short_to_float_v3(float out[3], const short in[3])
{
out[0] = in[0] * (1.0f / 32767.0f);
diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c
index 40d9a3da3d9..1a178db1413 100644
--- a/source/blender/blenlib/intern/rand.c
+++ b/source/blender/blenlib/intern/rand.c
@@ -41,6 +41,9 @@
#include "BLI_rand.h"
#include "BLI_math.h"
+/* defines BLI_INLINE */
+#include "BLI_utildefines.h"
+
#include "BLI_sys_types.h"
#include "BLI_strict_flags.h"
@@ -353,3 +356,101 @@ int BLI_rng_thread_rand(RNG_THREAD_ARRAY *rngarr, int thread)
return BLI_rng_get_int(&rngarr->rng_tab[thread]);
}
+/* ********* Low-discrepancy sequences ************** */
+
+/* incremental halton sequence generator, from:
+ * "Instant Radiosity", Keller A. */
+BLI_INLINE double halton_ex(double invprimes, double *offset)
+{
+ double e = fabs((1.0 - *offset) - 1e-10);
+
+ if (invprimes >= e) {
+ double lasth;
+ double h = invprimes;
+
+ do {
+ lasth = h;
+ h *= invprimes;
+ } while (h >= e);
+
+ *offset += ((lasth + h) - 1.0);
+ }
+ else {
+ *offset += invprimes;
+ }
+
+ return *offset;
+}
+
+void BLI_halton_1D(unsigned int prime, double offset, int n, double *r)
+{
+ const double invprime = 1.0 / (double)prime;
+
+ for (int s = 0; s < n; s++) {
+ *r = halton_ex(invprime, &offset);
+ }
+}
+
+void BLI_halton_2D(unsigned int prime[2], double offset[2], int n, double *r)
+{
+ const double invprimes[2] = {1.0 / (double)prime[0], 1.0 / (double)prime[1]};
+
+ for (int s = 0; s < n; s++) {
+ for (int i = 0; i < 2; i++) {
+ r[i] = halton_ex(invprimes[i], &offset[i]);
+ }
+ }
+}
+
+void BLI_halton_3D(unsigned int prime[3], double offset[3], int n, double *r)
+{
+ const double invprimes[3] = {1.0 / (double)prime[0], 1.0 / (double)prime[1], 1.0 / (double)prime[2]};
+
+ for (int s = 0; s < n; s++) {
+ for (int i = 0; i < 3; i++) {
+ r[i] = halton_ex(invprimes[i], &offset[i]);
+ }
+ }
+}
+
+void BLI_halton_2D_sequence(unsigned int prime[2], double offset[2], int n, double *r)
+{
+ const double invprimes[2] = {1.0 / (double)prime[0], 1.0 / (double)prime[1]};
+
+ for (int s = 0; s < n; s++) {
+ for (int i = 0; i < 2; i++) {
+ r[s * 2 + i] = halton_ex(invprimes[i], &offset[i]);
+ }
+ }
+}
+
+
+/* From "Sampling with Hammersley and Halton Points" TT Wong
+ * Appendix: Source Code 1 */
+BLI_INLINE double radical_inverse(unsigned int n)
+{
+ double u = 0;
+
+ /* This reverse the bitwise representation
+ * around the decimal point. */
+ for (double p = 0.5; n; p *= 0.5, n >>= 1) {
+ if (n & 1) {
+ u += p;
+ }
+ }
+
+ return u;
+}
+
+void BLI_hammersley_1D(unsigned int n, double *r)
+{
+ *r = radical_inverse(n);
+}
+
+void BLI_hammersley_2D_sequence(unsigned int n, double *r)
+{
+ for (unsigned int s = 0; s < n; s++) {
+ r[s * 2 + 0] = (double)(s + 0.5) / (double)n;
+ r[s * 2 + 1] = radical_inverse(s);
+ }
+}
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index a48c8b074dd..e31659c35d9 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -389,11 +389,7 @@ LinkNode *BLI_file_read_as_lines(const char *name)
for (i = 0; i <= size; i++) {
if (i == size || buf[i] == '\n') {
char *line = BLI_strdupn(&buf[last], i - last);
-
BLI_linklist_append(&lines, line);
- /* faster to build singly-linked list in reverse order */
- /* alternatively, could process buffer in reverse order so
- * list ends up right way round to start with */
last = i + 1;
}
}
diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c
index 863622f2546..ecb977c6e61 100644
--- a/source/blender/blenlib/intern/system.c
+++ b/source/blender/blenlib/intern/system.c
@@ -50,8 +50,8 @@ int BLI_cpu_support_sse2(void)
"pushl %%ebx\n\t"
"cpuid\n\t"
"popl %%ebx\n\t"
- : "=d" (d)
- : "a" (1));
+ : "=d" (d)
+ : "a" (1));
return (d & 0x04000000) != 0;
#elif (defined(_MSC_VER) && defined(_M_IX86))
/* also check cpuid for MSVC x86 */
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index e050f3148b8..eb7f186702b 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -32,6 +32,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_mempool.h"
#include "BLI_task.h"
#include "BLI_threads.h"
@@ -1003,8 +1004,7 @@ BLI_INLINE bool parallel_range_next_iter_get(
ParallelRangeState * __restrict state,
int * __restrict iter, int * __restrict count)
{
- uint32_t uval = atomic_fetch_and_add_uint32((uint32_t *)(&state->iter), state->chunk_size);
- int previter = *(int32_t *)&uval;
+ int previter = atomic_fetch_and_add_int32(&state->iter, state->chunk_size);
*iter = previter;
*count = max_ii(0, min_ii(state->chunk_size, state->stop - previter));
@@ -1124,7 +1124,7 @@ static void task_parallel_range_ex(
}
num_tasks = min_ii(num_tasks, (stop - start) / state.chunk_size);
- atomic_fetch_and_add_uint32((uint32_t *)(&state.iter), 0);
+ atomic_fetch_and_add_int32(&state.iter, 0);
if (use_userdata_chunk) {
userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks);
@@ -1355,3 +1355,89 @@ void BLI_task_parallel_listbase(
BLI_spin_end(&state.lock);
}
+
+
+typedef struct ParallelMempoolState {
+ void *userdata;
+ TaskParallelMempoolFunc func;
+} ParallelMempoolState;
+
+static void parallel_mempool_func(
+ TaskPool * __restrict pool,
+ void *taskdata,
+ int UNUSED(threadid))
+{
+ ParallelMempoolState * __restrict state = BLI_task_pool_userdata(pool);
+ BLI_mempool_iter *iter = taskdata;
+ MempoolIterData *item;
+
+ while ((item = BLI_mempool_iterstep(iter)) != NULL) {
+ state->func(state->userdata, item);
+ }
+}
+
+/**
+ * This function allows to parallelize for loops over Mempool items.
+ *
+ * \param pool The iterable BLI_mempool to loop over.
+ * \param userdata Common userdata passed to all instances of \a func.
+ * \param func Callback function.
+ * \param use_threading If \a true, actually split-execute loop in threads, else just do a sequential forloop
+ * (allows caller to use any kind of test to switch on parallelization or not).
+ *
+ * \note There is no static scheduling here.
+ */
+void BLI_task_parallel_mempool(
+ BLI_mempool *mempool,
+ void *userdata,
+ TaskParallelMempoolFunc func,
+ const bool use_threading)
+{
+ TaskScheduler *task_scheduler;
+ TaskPool *task_pool;
+ ParallelMempoolState state;
+ int i, num_threads, num_tasks;
+
+ if (BLI_mempool_count(mempool) == 0) {
+ return;
+ }
+
+ if (!use_threading) {
+ BLI_mempool_iter iter;
+ BLI_mempool_iternew(mempool, &iter);
+
+ for (void *item = BLI_mempool_iterstep(&iter); item != NULL; item = BLI_mempool_iterstep(&iter)) {
+ func(userdata, item);
+ }
+ return;
+ }
+
+ task_scheduler = BLI_task_scheduler_get();
+ task_pool = BLI_task_pool_create(task_scheduler, &state);
+ num_threads = BLI_task_scheduler_num_threads(task_scheduler);
+
+ /* The idea here is to prevent creating task for each of the loop iterations
+ * and instead have tasks which are evenly distributed across CPU cores and
+ * pull next item to be crunched using the threaded-aware BLI_mempool_iter.
+ */
+ num_tasks = num_threads * 2;
+
+ state.userdata = userdata;
+ state.func = func;
+
+ BLI_mempool_iter *mempool_iterators = BLI_mempool_iter_threadsafe_create(mempool, (size_t)num_tasks);
+
+ for (i = 0; i < num_tasks; i++) {
+ /* Use this pool's pre-allocated tasks. */
+ BLI_task_pool_push_from_thread(task_pool,
+ parallel_mempool_func,
+ &mempool_iterators[i], false,
+ TASK_PRIORITY_HIGH,
+ task_pool->thread_id);
+ }
+
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
+
+ BLI_mempool_iter_threadsafe_free(mempool_iterators);
+}
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index abf611d1245..2f961701801 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -472,8 +472,10 @@ void BLI_mutex_free(ThreadMutex *mutex)
void BLI_spin_init(SpinLock *spin)
{
-#ifdef __APPLE__
+#if defined(__APPLE__)
*spin = OS_SPINLOCK_INIT;
+#elif defined(_MSC_VER)
+ *spin = 0;
#else
pthread_spin_init(spin, 0);
#endif
@@ -481,8 +483,14 @@ void BLI_spin_init(SpinLock *spin)
void BLI_spin_lock(SpinLock *spin)
{
-#ifdef __APPLE__
+#if defined(__APPLE__)
OSSpinLockLock(spin);
+#elif defined(_MSC_VER)
+ while (InterlockedExchangeAcquire(spin, 1)) {
+ while (*spin) {
+ /* pass */
+ }
+ }
#else
pthread_spin_lock(spin);
#endif
@@ -490,21 +498,24 @@ void BLI_spin_lock(SpinLock *spin)
void BLI_spin_unlock(SpinLock *spin)
{
-#ifdef __APPLE__
+#if defined(__APPLE__)
OSSpinLockUnlock(spin);
+#elif defined(_MSC_VER)
+ _ReadWriteBarrier();
+ *spin = 0;
#else
pthread_spin_unlock(spin);
#endif
}
-#ifndef __APPLE__
-void BLI_spin_end(SpinLock *spin)
+#if defined(__APPLE__) || defined(_MSC_VER)
+void BLI_spin_end(SpinLock *UNUSED(spin))
{
- pthread_spin_destroy(spin);
}
#else
-void BLI_spin_end(SpinLock *UNUSED(spin))
+void BLI_spin_end(SpinLock *spin)
{
+ pthread_spin_destroy(spin);
}
#endif
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 646cf978453..fb45fdc8136 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -7298,7 +7298,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
sseq->scopes.sep_waveform_ibuf = NULL;
sseq->scopes.vector_ibuf = NULL;
sseq->scopes.histogram_ibuf = NULL;
-
+ sseq->compositor = NULL;
}
else if (sl->spacetype == SPACE_BUTS) {
SpaceButs *sbuts = (SpaceButs *)sl;
diff --git a/source/blender/blentranslation/msgfmt/msgfmt.c b/source/blender/blentranslation/msgfmt/msgfmt.c
index 3abce7b1d3f..49f850f200c 100644
--- a/source/blender/blentranslation/msgfmt/msgfmt.c
+++ b/source/blender/blentranslation/msgfmt/msgfmt.c
@@ -184,7 +184,8 @@ typedef struct Offset {
} Offset;
/* Return the generated binary output. */
-static char *generate(GHash *messages, size_t *r_output_size) {
+static char *generate(GHash *messages, size_t *r_output_size)
+{
const uint32_t num_keys = BLI_ghash_size(messages);
/* Get list of sorted keys. */
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index ea24da86626..5245d24a075 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../blentranslation
../makesdna
../../../intern/guardedalloc
+ ../../../intern/atomic
../../../intern/eigen
../../../extern/rangetree
)
@@ -39,6 +40,7 @@ set(INC_SYS
)
set(SRC
+ # Naming convention for BMesh operators is: bmo_*action*_*details*.c
operators/bmo_beautify.c
operators/bmo_bevel.c
operators/bmo_bisect_plane.c
@@ -67,6 +69,7 @@ set(SRC
operators/bmo_poke.c
operators/bmo_primitive.c
operators/bmo_removedoubles.c
+ operators/bmo_rotate_edges.c
operators/bmo_similar.c
operators/bmo_smooth_laplacian.c
operators/bmo_split_edges.c
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index 00f8eb6df40..96b2eb17c4c 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -36,12 +36,13 @@
#include "DNA_meshdata_types.h"
#include "BLI_alloca.h"
+#include "BLI_linklist.h"
#include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_task.h"
#include "BKE_customdata.h"
#include "BKE_multires.h"
-#include "BLI_memarena.h"
-#include "BLI_linklist.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
@@ -401,13 +402,78 @@ static void bm_loop_flip_disp(
disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d;
}
+
+typedef struct BMLoopInterpMultiresData {
+ BMLoop *l_dst;
+ BMLoop *l_src_first;
+ int cd_loop_mdisp_offset;
+
+ MDisps *md_dst;
+ const float *f_src_center;
+
+ float *axis_x, *axis_y;
+ float *v1, *v4;
+ float *e1, *e2;
+
+ int res;
+ float d;
+} BMLoopInterpMultiresData;
+
+static void loop_interp_multires_cb(void *userdata, int ix)
+{
+ BMLoopInterpMultiresData *data = userdata;
+
+ BMLoop *l_first = data->l_src_first;
+ BMLoop *l_dst = data->l_dst;
+ const int cd_loop_mdisp_offset = data->cd_loop_mdisp_offset;
+
+ MDisps *md_dst = data->md_dst;
+ const float *f_src_center = data->f_src_center;
+
+ float *axis_x = data->axis_x;
+ float *axis_y = data->axis_y;
+
+ float *v1 = data->v1;
+ float *v4 = data->v4;
+ float *e1 = data->e1;
+ float *e2 = data->e2;
+
+ const int res = data->res;
+ const float d = data->d;
+
+ float x = d * ix, y;
+ int iy;
+ for (y = 0.0f, iy = 0; iy < res; y += d, iy++) {
+ BMLoop *l_iter = l_first;
+ float co1[3], co2[3], co[3];
+
+ madd_v3_v3v3fl(co1, v1, e1, y);
+ madd_v3_v3v3fl(co2, v4, e2, y);
+ interp_v3_v3v3(co, co1, co2, x);
+
+ do {
+ MDisps *md_src;
+ float src_axis_x[3], src_axis_y[3];
+ float uv[2];
+
+ md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset);
+
+ if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) {
+ old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]);
+ bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]);
+
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+}
+
void BM_loop_interp_multires_ex(
BMesh *UNUSED(bm), BMLoop *l_dst, const BMFace *f_src,
const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset)
{
MDisps *md_dst;
- float d, v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3];
- int ix, res;
+ float v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3];
float axis_x[3], axis_y[3];
/* ignore 2-edged faces */
@@ -433,38 +499,15 @@ void BM_loop_interp_multires_ex(
mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y);
- res = (int)sqrt(md_dst->totdisp);
- d = 1.0f / (float)(res - 1);
-#pragma omp parallel for if (res > 3)
- for (ix = 0; ix < res; ix++) {
- float x = d * ix, y;
- int iy;
- for (y = 0.0f, iy = 0; iy < res; y += d, iy++) {
- BMLoop *l_iter;
- BMLoop *l_first;
- float co1[3], co2[3], co[3];
-
- madd_v3_v3v3fl(co1, v1, e1, y);
- madd_v3_v3v3fl(co2, v4, e2, y);
- interp_v3_v3v3(co, co1, co2, x);
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
- do {
- MDisps *md_src;
- float src_axis_x[3], src_axis_y[3];
- float uv[2];
-
- md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset);
-
- if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) {
- old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]);
- bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]);
-
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
+ const int res = (int)sqrt(md_dst->totdisp);
+ BMLoopInterpMultiresData data = {
+ .l_dst = l_dst, .l_src_first = BM_FACE_FIRST_LOOP(f_src),
+ .cd_loop_mdisp_offset = cd_loop_mdisp_offset,
+ .md_dst = md_dst, .f_src_center = f_src_center,
+ .axis_x = axis_x, .axis_y = axis_y, .v1 = v1, .v4 = v4, .e1 = e1, .e2 = e2,
+ .res = res, .d = 1.0f / (float)(res - 1)
+ };
+ BLI_task_parallel_range(0, res, &data, loop_interp_multires_cb, res > 5);
}
/**
diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h
index e68440021e6..88985d639cf 100644
--- a/source/blender/bmesh/intern/bmesh_iterators_inline.h
+++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h
@@ -182,4 +182,38 @@ BLI_INLINE void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *da
}
}
+/**
+ * \brief Parallel (threaded) iterator, only available for most basic itertypes (verts/edges/faces of mesh).
+ *
+ * Uses BLI_task_parallel_mempool to iterate over all items of underlying matching mempool.
+ *
+ * \note You have to include BLI_task.h before BMesh includes to be able to use this function!
+ */
+
+#ifdef __BLI_TASK_H__
+
+ATTR_NONNULL(1)
+BLI_INLINE void BM_iter_parallel(
+ BMesh *bm, const char itype, TaskParallelMempoolFunc func, void *userdata, const bool use_threading)
+{
+ /* inlining optimizes out this switch when called with the defined type */
+ switch ((BMIterType)itype) {
+ case BM_VERTS_OF_MESH:
+ BLI_task_parallel_mempool(bm->vpool, userdata, func, use_threading);
+ break;
+ case BM_EDGES_OF_MESH:
+ BLI_task_parallel_mempool(bm->epool, userdata, func, use_threading);
+ break;
+ case BM_FACES_OF_MESH:
+ BLI_task_parallel_mempool(bm->fpool, userdata, func, use_threading);
+ break;
+ default:
+ /* should never happen */
+ BLI_assert(0);
+ break;
+ }
+}
+
+#endif /* __BLI_TASK_H__ */
+
#endif /* __BMESH_ITERATORS_INLINE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 7f2032d5f53..432c82afe4a 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -57,7 +57,6 @@ static void recount_totsels(BMesh *bm)
tots[1] = &bm->totedgesel;
tots[2] = &bm->totfacesel;
-#pragma omp parallel for schedule(static) if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
for (i = 0; i < 3; i++) {
BMIter iter;
BMElem *ele;
@@ -253,44 +252,34 @@ void BM_mesh_select_mode_flush_ex(BMesh *bm, const short selectmode)
if (selectmode & SCE_SELECT_VERTEX) {
/* both loops only set edge/face flags and read off verts */
-#pragma omp parallel sections if (bm->totedge + bm->totface >= BM_OMP_LIMIT)
- {
-#pragma omp section
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
+ BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
+ !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
{
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
- BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
- {
- BM_elem_flag_enable(e, BM_ELEM_SELECT);
- }
- else {
- BM_elem_flag_disable(e, BM_ELEM_SELECT);
- }
- }
+ BM_elem_flag_enable(e, BM_ELEM_SELECT);
}
-#pragma omp section
- {
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- bool ok = true;
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- ok = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
+ else {
+ BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ }
+ }
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ bool ok = true;
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
ok = false;
+ break;
}
-
- BM_elem_flag_set(f, BM_ELEM_SELECT, ok);
- }
+ } while ((l_iter = l_iter->next) != l_first);
}
+ else {
+ ok = false;
+ }
+
+ BM_elem_flag_set(f, BM_ELEM_SELECT, ok);
}
- /* end sections */
}
else if (selectmode & SCE_SELECT_EDGE) {
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
@@ -375,42 +364,31 @@ void BM_mesh_select_flush(BMesh *bm)
bool ok;
- /* we can use 2 sections here because the second loop isnt checking edge selection */
-#pragma omp parallel sections if (bm->totedge + bm->totface >= BM_OMP_LIMIT)
- {
-#pragma omp section
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
+ BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
+ !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
{
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
- BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
- {
- BM_elem_flag_enable(e, BM_ELEM_SELECT);
- }
- }
+ BM_elem_flag_enable(e, BM_ELEM_SELECT);
}
-
-#pragma omp section
- {
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- ok = true;
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- ok = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
+ }
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ ok = true;
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
ok = false;
+ break;
}
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ ok = false;
+ }
- if (ok) {
- BM_elem_flag_enable(f, BM_ELEM_SELECT);
- }
- }
+ if (ok) {
+ BM_elem_flag_enable(f, BM_ELEM_SELECT);
}
}
@@ -1107,8 +1085,6 @@ void BM_mesh_elem_hflag_disable_test(
{
/* fast path for deselect all, avoid topology loops
* since we know all will be de-selected anyway. */
-
-#pragma omp parallel for schedule(static) if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
for (i = 0; i < 3; i++) {
BMIter iter;
BMElem *ele;
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 2ff670c770e..67db51446df 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -35,6 +35,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_stack.h"
+#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
@@ -42,6 +43,8 @@
#include "BKE_mesh.h"
#include "BKE_multires.h"
+#include "atomic_ops.h"
+
#include "intern/bmesh_private.h"
/* used as an extern, defined in bmesh.h */
@@ -112,37 +115,24 @@ void BM_mesh_elem_toolflags_ensure(BMesh *bm)
bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totedge, 512, BLI_MEMPOOL_NOP);
bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totface, 512, BLI_MEMPOOL_NOP);
-#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
- {
-#pragma omp section
- {
- BLI_mempool *toolflagpool = bm->vtoolflagpool;
- BMIter iter;
- BMVert_OFlag *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- ele->oflags = BLI_mempool_calloc(toolflagpool);
- }
- }
-#pragma omp section
- {
- BLI_mempool *toolflagpool = bm->etoolflagpool;
- BMIter iter;
- BMEdge_OFlag *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- ele->oflags = BLI_mempool_calloc(toolflagpool);
- }
- }
-#pragma omp section
- {
- BLI_mempool *toolflagpool = bm->ftoolflagpool;
- BMIter iter;
- BMFace_OFlag *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- ele->oflags = BLI_mempool_calloc(toolflagpool);
- }
- }
+ BMIter iter;
+ BMVert_OFlag *v_olfag;
+ BLI_mempool *toolflagpool = bm->vtoolflagpool;
+ BM_ITER_MESH (v_olfag, &iter, bm, BM_VERTS_OF_MESH) {
+ v_olfag->oflags = BLI_mempool_calloc(toolflagpool);
+ }
+
+ BMEdge_OFlag *e_olfag;
+ toolflagpool = bm->etoolflagpool;
+ BM_ITER_MESH (e_olfag, &iter, bm, BM_EDGES_OF_MESH) {
+ e_olfag->oflags = BLI_mempool_calloc(toolflagpool);
}
+ BMFace_OFlag *f_olfag;
+ toolflagpool = bm->ftoolflagpool;
+ BM_ITER_MESH (f_olfag, &iter, bm, BM_FACES_OF_MESH) {
+ f_olfag->oflags = BLI_mempool_calloc(toolflagpool);
+ }
bm->totflags = 1;
}
@@ -318,96 +308,163 @@ void BM_mesh_free(BMesh *bm)
MEM_freeN(bm);
}
+
/**
* Helpers for #BM_mesh_normals_update and #BM_verts_calc_normal_vcos
*/
-static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const float (*vcos)[3])
+
+typedef struct BMEdgesCalcVectorsData {
+ /* Read-only data. */
+ const float (*vcos)[3];
+
+ /* Read-write data, but no need to protect it, no concurrency to fear here. */
+ float (*edgevec)[3];
+} BMEdgesCalcVectorsData;
+
+
+static void mesh_edges_calc_vectors_cb(void *userdata, MempoolIterData *mp_e)
{
- BMIter eiter;
- BMEdge *e;
- int index;
+ BMEdgesCalcVectorsData *data = userdata;
+ BMEdge *e = (BMEdge *)mp_e;
- if (vcos) {
- BM_mesh_elem_index_ensure(bm, BM_VERT);
+ if (e->l) {
+ const float *v1_co = data->vcos ? data->vcos[BM_elem_index_get(e->v1)] : e->v1->co;
+ const float *v2_co = data->vcos ? data->vcos[BM_elem_index_get(e->v2)] : e->v2->co;
+ sub_v3_v3v3(data->edgevec[BM_elem_index_get(e)], v2_co, v1_co);
+ normalize_v3(data->edgevec[BM_elem_index_get(e)]);
}
+ else {
+ /* the edge vector will not be needed when the edge has no radial */
+ }
+}
- BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, index) {
- BM_elem_index_set(e, index); /* set_inline */
+static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const float (*vcos)[3])
+{
+ BM_mesh_elem_index_ensure(bm, BM_EDGE | (vcos ? BM_VERT : 0));
- if (e->l) {
- const float *v1_co = vcos ? vcos[BM_elem_index_get(e->v1)] : e->v1->co;
- const float *v2_co = vcos ? vcos[BM_elem_index_get(e->v2)] : e->v2->co;
- sub_v3_v3v3(edgevec[index], v2_co, v1_co);
- normalize_v3(edgevec[index]);
- }
- else {
- /* the edge vector will not be needed when the edge has no radial */
- }
+ BMEdgesCalcVectorsData data = {
+ .vcos = vcos,
+ .edgevec = edgevec
+ };
+
+ BM_iter_parallel(bm, BM_EDGES_OF_MESH, mesh_edges_calc_vectors_cb, &data, bm->totedge >= BM_OMP_LIMIT);
+}
+
+
+typedef struct BMVertsCalcNormalsData {
+ /* Read-only data. */
+ const float (*fnos)[3];
+ const float (*edgevec)[3];
+ const float (*vcos)[3];
+
+ /* Read-write data, protected by an atomic-based fake spinlock-like system... */
+ float (*vnos)[3];
+} BMVertsCalcNormalsData;
+
+static void mesh_verts_calc_normals_accum_cb(void *userdata, MempoolIterData *mp_f)
+{
+ BMVertsCalcNormalsData *data = userdata;
+ BMFace *f = (BMFace *)mp_f;
+
+ const float *f_no = data->fnos ? data->fnos[BM_elem_index_get(f)] : f->no;
+
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const float *e1diff, *e2diff;
+ float dotprod;
+ float fac;
+
+ /* calculate the dot product of the two edges that
+ * meet at the loop's vertex */
+ e1diff = data->edgevec[BM_elem_index_get(l_iter->prev->e)];
+ e2diff = data->edgevec[BM_elem_index_get(l_iter->e)];
+ dotprod = dot_v3v3(e1diff, e2diff);
+
+ /* edge vectors are calculated from e->v1 to e->v2, so
+ * adjust the dot product if one but not both loops
+ * actually runs from from e->v2 to e->v1 */
+ if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) {
+ dotprod = -dotprod;
+ }
+
+ fac = saacos(-dotprod);
+
+ /* accumulate weighted face normal into the vertex's normal */
+ float *v_no = data->vnos ? data->vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no;
+
+ /* This block is a lockless threadsafe madd_v3_v3fl.
+ * It uses the first float of the vector as a sort of cheap spinlock,
+ * assuming FLT_MAX is a safe 'illegal' value that cannot be set here otherwise.
+ * It also assumes that collisions between threads are highly unlikely,
+ * else performances would be quite bad here. */
+ float virtual_lock = v_no[0];
+ while (true) {
+ /* This loops until following conditions are met:
+ * - v_no[0] has same value as virtual_lock (i.e. it did not change since last try).
+ * - v_no[0] was not FLT_MAX, i.e. it was not locked by another thread.
+ */
+ const float vl = atomic_cas_float(&v_no[0], virtual_lock, FLT_MAX);
+ if (vl == virtual_lock && vl != FLT_MAX) {
+ break;
+ }
+ virtual_lock = vl;
+ }
+ BLI_assert(v_no[0] == FLT_MAX);
+ /* Now we own that normal value, and can change it.
+ * But first scalar of the vector must not be changed yet, it's our lock! */
+ virtual_lock += f_no[0] * fac;
+ v_no[1] += f_no[1] * fac;
+ v_no[2] += f_no[2] * fac;
+ /* Second atomic operation to 'release' our lock on that vector and set its first scalar value. */
+ /* Note that we do not need to loop here, since we 'locked' v_no[0],
+ * nobody should have changed it in the mean time. */
+ virtual_lock = atomic_cas_float(&v_no[0], FLT_MAX, virtual_lock);
+ BLI_assert(virtual_lock == FLT_MAX);
+
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void mesh_verts_calc_normals_normalize_cb(void *userdata, MempoolIterData *mp_v)
+{
+ BMVertsCalcNormalsData *data = userdata;
+ BMVert *v = (BMVert *)mp_v;
+
+ float *v_no = data->vnos ? data->vnos[BM_elem_index_get(v)] : v->no;
+ if (UNLIKELY(normalize_v3(v_no) == 0.0f)) {
+ const float *v_co = data->vcos ? data->vcos[BM_elem_index_get(v)] : v->co;
+ normalize_v3_v3(v_no, v_co);
}
- bm->elem_index_dirty &= ~BM_EDGE;
}
static void bm_mesh_verts_calc_normals(
BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3],
const float (*vcos)[3], float (*vnos)[3])
{
- BM_mesh_elem_index_ensure(bm, (vnos) ? (BM_EDGE | BM_VERT) : BM_EDGE);
+ BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE) | ((vnos || vcos) ? BM_VERT : 0));
- /* add weighted face normals to vertices */
- {
- BMIter fiter;
- BMFace *f;
- int i;
-
- BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) {
- BMLoop *l_first, *l_iter;
- const float *f_no = fnos ? fnos[i] : f->no;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const float *e1diff, *e2diff;
- float dotprod;
- float fac;
- float *v_no = vnos ? vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no;
-
- /* calculate the dot product of the two edges that
- * meet at the loop's vertex */
- e1diff = edgevec[BM_elem_index_get(l_iter->prev->e)];
- e2diff = edgevec[BM_elem_index_get(l_iter->e)];
- dotprod = dot_v3v3(e1diff, e2diff);
-
- /* edge vectors are calculated from e->v1 to e->v2, so
- * adjust the dot product if one but not both loops
- * actually runs from from e->v2 to e->v1 */
- if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) {
- dotprod = -dotprod;
- }
+ BMVertsCalcNormalsData data = {
+ .fnos = fnos,
+ .edgevec = edgevec,
+ .vcos = vcos,
+ .vnos = vnos
+ };
- fac = saacos(-dotprod);
+ BM_iter_parallel(bm, BM_FACES_OF_MESH, mesh_verts_calc_normals_accum_cb, &data, bm->totface >= BM_OMP_LIMIT);
- /* accumulate weighted face normal into the vertex's normal */
- madd_v3_v3fl(v_no, f_no, fac);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
+ /* normalize the accumulated vertex normals */
+ BM_iter_parallel(bm, BM_VERTS_OF_MESH, mesh_verts_calc_normals_normalize_cb, &data, bm->totvert >= BM_OMP_LIMIT);
+}
- /* normalize the accumulated vertex normals */
- {
- BMIter viter;
- BMVert *v;
- int i;
-
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- float *v_no = vnos ? vnos[i] : v->no;
- if (UNLIKELY(normalize_v3(v_no) == 0.0f)) {
- const float *v_co = vcos ? vcos[i] : v->co;
- normalize_v3_v3(v_no, v_co);
- }
- }
- }
+static void mesh_faces_calc_normals_cb(void *UNUSED(userdata), MempoolIterData *mp_f)
+{
+ BMFace *f = (BMFace *)mp_f;
+
+ BM_face_normal_update(f);
}
+
/**
* \brief BMesh Compute Normals
*
@@ -417,43 +474,27 @@ void BM_mesh_normals_update(BMesh *bm)
{
float (*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__);
-#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
- {
-#pragma omp section
- {
- /* calculate all face normals */
- BMIter fiter;
- BMFace *f;
- int i;
-
- BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) {
- BM_elem_index_set(f, i); /* set_inline */
- BM_face_normal_update(f);
- }
- bm->elem_index_dirty &= ~BM_FACE;
- }
-#pragma omp section
- {
- /* Zero out vertex normals */
- BMIter viter;
- BMVert *v;
- int i;
-
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- BM_elem_index_set(v, i); /* set_inline */
- zero_v3(v->no);
- }
- bm->elem_index_dirty &= ~BM_VERT;
- }
-#pragma omp section
- {
- /* Compute normalized direction vectors for each edge.
- * Directions will be used for calculating the weights of the face normals on the vertex normals.
- */
- bm_mesh_edges_calc_vectors(bm, edgevec, NULL);
- }
+ /* Parallel mempool iteration does not allow to generate indices inline anymore... */
+ BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE));
+
+ /* calculate all face normals */
+ BM_iter_parallel(bm, BM_FACES_OF_MESH, mesh_faces_calc_normals_cb, NULL, bm->totface >= BM_OMP_LIMIT);
+
+ /* Zero out vertex normals */
+ BMIter viter;
+ BMVert *v;
+ int i;
+
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ BM_elem_index_set(v, i); /* set_inline */
+ zero_v3(v->no);
}
- /* end omp */
+ bm->elem_index_dirty &= ~BM_VERT;
+
+ /* Compute normalized direction vectors for each edge.
+ * Directions will be used for calculating the weights of the face normals on the vertex normals.
+ */
+ bm_mesh_edges_calc_vectors(bm, edgevec, NULL);
/* Add weighted face normals to vertices, and normalize vert normals. */
bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, NULL, NULL, NULL);
@@ -1104,94 +1145,78 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
BM_ELEM_INDEX_VALIDATE(bm, "Should Never Fail!", __func__);
#endif
- if (htype_needed == 0) {
+ if (0 && htype_needed == 0) {
goto finally;
}
- /* skip if we only need to operate on one element */
-#pragma omp parallel sections if ((!ELEM(htype_needed, BM_VERT, BM_EDGE, BM_FACE, BM_LOOP, BM_FACE | BM_LOOP)) && \
- (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT))
- {
-#pragma omp section
+ if (htype & BM_VERT) {
+ if (bm->elem_index_dirty & BM_VERT) {
+ BMIter iter;
+ BMElem *ele;
- {
- if (htype & BM_VERT) {
- if (bm->elem_index_dirty & BM_VERT) {
- BMIter iter;
- BMElem *ele;
-
- int index;
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, index) {
- BM_elem_index_set(ele, index); /* set_ok */
- }
- BLI_assert(index == bm->totvert);
- }
- else {
- // printf("%s: skipping vert index calc!\n", __func__);
- }
+ int index;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, index) {
+ BM_elem_index_set(ele, index); /* set_ok */
}
+ BLI_assert(index == bm->totvert);
+ }
+ else {
+ // printf("%s: skipping vert index calc!\n", __func__);
}
+ }
-#pragma omp section
- {
- if (htype & BM_EDGE) {
- if (bm->elem_index_dirty & BM_EDGE) {
- BMIter iter;
- BMElem *ele;
-
- int index;
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, index) {
- BM_elem_index_set(ele, index); /* set_ok */
- }
- BLI_assert(index == bm->totedge);
- }
- else {
- // printf("%s: skipping edge index calc!\n", __func__);
- }
+ if (htype & BM_EDGE) {
+ if (bm->elem_index_dirty & BM_EDGE) {
+ BMIter iter;
+ BMElem *ele;
+
+ int index;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, index) {
+ BM_elem_index_set(ele, index); /* set_ok */
}
+ BLI_assert(index == bm->totedge);
}
+ else {
+ // printf("%s: skipping edge index calc!\n", __func__);
+ }
+ }
-#pragma omp section
- {
- if (htype & (BM_FACE | BM_LOOP)) {
- if (bm->elem_index_dirty & (BM_FACE | BM_LOOP)) {
- BMIter iter;
- BMElem *ele;
-
- const bool update_face = (htype & BM_FACE) && (bm->elem_index_dirty & BM_FACE);
- const bool update_loop = (htype & BM_LOOP) && (bm->elem_index_dirty & BM_LOOP);
+ if (htype & (BM_FACE | BM_LOOP)) {
+ if (bm->elem_index_dirty & (BM_FACE | BM_LOOP)) {
+ BMIter iter;
+ BMElem *ele;
- int index;
- int index_loop = 0;
+ const bool update_face = (htype & BM_FACE) && (bm->elem_index_dirty & BM_FACE);
+ const bool update_loop = (htype & BM_LOOP) && (bm->elem_index_dirty & BM_LOOP);
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, index) {
- if (update_face) {
- BM_elem_index_set(ele, index); /* set_ok */
- }
+ int index;
+ int index_loop = 0;
- if (update_loop) {
- BMLoop *l_iter, *l_first;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, index) {
+ if (update_face) {
+ BM_elem_index_set(ele, index); /* set_ok */
+ }
- l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)ele);
- do {
- BM_elem_index_set(l_iter, index_loop++); /* set_ok */
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
+ if (update_loop) {
+ BMLoop *l_iter, *l_first;
- BLI_assert(index == bm->totface);
- if (update_loop) {
- BLI_assert(index_loop == bm->totloop);
- }
- }
- else {
- // printf("%s: skipping face/loop index calc!\n", __func__);
+ l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)ele);
+ do {
+ BM_elem_index_set(l_iter, index_loop++); /* set_ok */
+ } while ((l_iter = l_iter->next) != l_first);
}
}
+
+ BLI_assert(index == bm->totface);
+ if (update_loop) {
+ BLI_assert(index_loop == bm->totloop);
+ }
+ }
+ else {
+ // printf("%s: skipping face/loop index calc!\n", __func__);
}
}
-
finally:
bm->elem_index_dirty &= ~htype;
}
@@ -1363,28 +1388,16 @@ void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
}
}
- /* skip if we only need to operate on one element */
-#pragma omp parallel sections if ((!ELEM(htype_needed, BM_VERT, BM_EDGE, BM_FACE)) && \
- (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT))
- {
-#pragma omp section
- {
- if (htype_needed & BM_VERT) {
- BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)bm->vtable, bm->totvert);
- }
- }
-#pragma omp section
- {
- if (htype_needed & BM_EDGE) {
- BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)bm->etable, bm->totedge);
- }
- }
-#pragma omp section
- {
- if (htype_needed & BM_FACE) {
- BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)bm->ftable, bm->totface);
- }
- }
+ if (htype_needed & BM_VERT) {
+ BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)bm->vtable, bm->totvert);
+ }
+
+ if (htype_needed & BM_EDGE) {
+ BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)bm->etable, bm->totedge);
+ }
+
+ if (htype_needed & BM_FACE) {
+ BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)bm->ftable, bm->totface);
}
finally:
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 44445aae25a..0f672a9ff2a 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -550,37 +550,30 @@ static int bmo_mesh_flag_count(
{
int count_vert = 0, count_edge = 0, count_face = 0;
-#pragma omp parallel sections if ((bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) && \
- (ELEM(htype, BM_VERT, BM_EDGE, BM_FACE) == 0))
- {
-#pragma omp section
- if (htype & BM_VERT) {
- BMIter iter;
- BMVert *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
- count_vert++;
- }
+ if (htype & BM_VERT) {
+ BMIter iter;
+ BMVert *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
+ count_vert++;
}
}
-#pragma omp section
- if (htype & BM_EDGE) {
- BMIter iter;
- BMEdge *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- if (BMO_edge_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
- count_edge++;
- }
+ }
+ if (htype & BM_EDGE) {
+ BMIter iter;
+ BMEdge *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
+ count_edge++;
}
}
-#pragma omp section
- if (htype & BM_FACE) {
- BMIter iter;
- BMFace *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- if (BMO_face_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
- count_face++;
- }
+ }
+ if (htype & BM_FACE) {
+ BMIter iter;
+ BMFace *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ if (BMO_face_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
+ count_face++;
}
}
}
@@ -601,33 +594,25 @@ int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag)
void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char htype, const short oflag)
{
-
-#pragma omp parallel sections if ((bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) && \
- (ELEM(htype, BM_VERT, BM_EDGE, BM_FACE) == 0))
- {
-#pragma omp section
- if (htype & BM_VERT) {
- BMIter iter;
- BMVert *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- BMO_vert_flag_disable(bm, ele, oflag);
- }
+ if (htype & BM_VERT) {
+ BMIter iter;
+ BMVert *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ BMO_vert_flag_disable(bm, ele, oflag);
}
-#pragma omp section
- if (htype & BM_EDGE) {
- BMIter iter;
- BMEdge *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- BMO_edge_flag_disable(bm, ele, oflag);
- }
+ }
+ if (htype & BM_EDGE) {
+ BMIter iter;
+ BMEdge *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ BMO_edge_flag_disable(bm, ele, oflag);
}
-#pragma omp section
- if (htype & BM_FACE) {
- BMIter iter;
- BMFace *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- BMO_face_flag_disable(bm, ele, oflag);
- }
+ }
+ if (htype & BM_FACE) {
+ BMIter iter;
+ BMFace *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ BMO_face_flag_disable(bm, ele, oflag);
}
}
}
@@ -1236,57 +1221,38 @@ static void bmo_flag_layer_alloc(BMesh *bm)
bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, bm->totedge, 512, BLI_MEMPOOL_NOP);
bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, bm->totface, 512, BLI_MEMPOOL_NOP);
-#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
- {
-#pragma omp section
- {
- BMIter iter;
- BMVert_OFlag *ele;
- int i;
-
- BLI_mempool *newpool = bm->vtoolflagpool;
-
- /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
- void *oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(&ele->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
- }
- }
-#pragma omp section
- {
- BMIter iter;
- BMEdge_OFlag *ele;
- int i;
-
- BLI_mempool *newpool = bm->etoolflagpool;
-
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
- void *oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(&ele->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
- }
- }
-#pragma omp section
- {
- BMIter iter;
- BMFace_OFlag *ele;
- int i;
-
- BLI_mempool *newpool = bm->ftoolflagpool;
-
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
- void *oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(&ele->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
- }
- }
+ /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */
+ BMIter iter;
+ int i;
+
+ BMVert_OFlag *v_oflag;
+ BLI_mempool *newpool = bm->vtoolflagpool;
+ BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
+ void *oldflags = v_oflag->oflags;
+ v_oflag->oflags = BLI_mempool_calloc(newpool);
+ memcpy(v_oflag->oflags, oldflags, old_totflags_size);
+ BM_elem_index_set(&v_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
+ }
+
+ BMEdge_OFlag *e_oflag;
+ newpool = bm->etoolflagpool;
+ BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
+ void *oldflags = e_oflag->oflags;
+ e_oflag->oflags = BLI_mempool_calloc(newpool);
+ memcpy(e_oflag->oflags, oldflags, old_totflags_size);
+ BM_elem_index_set(&e_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
+ }
+
+ BMFace_OFlag *f_oflag;
+ newpool = bm->ftoolflagpool;
+ BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
+ void *oldflags = f_oflag->oflags;
+ f_oflag->oflags = BLI_mempool_calloc(newpool);
+ memcpy(f_oflag->oflags, oldflags, old_totflags_size);
+ BM_elem_index_set(&f_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
}
BLI_mempool_destroy(voldpool);
@@ -1315,57 +1281,38 @@ static void bmo_flag_layer_free(BMesh *bm)
bm->etoolflagpool = BLI_mempool_create(new_totflags_size, bm->totedge, 512, BLI_MEMPOOL_NOP);
bm->ftoolflagpool = BLI_mempool_create(new_totflags_size, bm->totface, 512, BLI_MEMPOOL_NOP);
-#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
- {
-#pragma omp section
- {
- BMIter iter;
- BMVert_OFlag *ele;
- int i;
-
- BLI_mempool *newpool = bm->vtoolflagpool;
-
- /* now go through and memcpy all the flag */
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
- void *oldflags = ele->oflags;
- ele->oflags = BLI_mempool_alloc(newpool);
- memcpy(ele->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(&ele->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
- }
- }
-#pragma omp section
- {
- BMIter iter;
- BMEdge_OFlag *ele;
- int i;
-
- BLI_mempool *newpool = bm->etoolflagpool;
-
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
- void *oldflags = ele->oflags;
- ele->oflags = BLI_mempool_alloc(newpool);
- memcpy(ele->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(&ele->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
- }
- }
-#pragma omp section
- {
- BMIter iter;
- BMFace_OFlag *ele;
- int i;
-
- BLI_mempool *newpool = bm->ftoolflagpool;
-
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
- void *oldflags = ele->oflags;
- ele->oflags = BLI_mempool_alloc(newpool);
- memcpy(ele->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(&ele->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
- }
- }
+ /* now go through and memcpy all the flag */
+ BMIter iter;
+ int i;
+
+ BMVert_OFlag *v_oflag;
+ BLI_mempool *newpool = bm->vtoolflagpool;
+ BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
+ void *oldflags = v_oflag->oflags;
+ v_oflag->oflags = BLI_mempool_alloc(newpool);
+ memcpy(v_oflag->oflags, oldflags, new_totflags_size);
+ BM_elem_index_set(&v_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
+ }
+
+ BMEdge_OFlag *e_oflag;
+ newpool = bm->etoolflagpool;
+ BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
+ void *oldflags = e_oflag->oflags;
+ e_oflag->oflags = BLI_mempool_alloc(newpool);
+ memcpy(e_oflag->oflags, oldflags, new_totflags_size);
+ BM_elem_index_set(&e_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
+ }
+
+ BMFace_OFlag *f_oflag;
+ newpool = bm->ftoolflagpool;
+ BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
+ void *oldflags = f_oflag->oflags;
+ f_oflag->oflags = BLI_mempool_alloc(newpool);
+ memcpy(f_oflag->oflags, oldflags, new_totflags_size);
+ BM_elem_index_set(&f_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
}
BLI_mempool_destroy(voldpool);
@@ -1383,38 +1330,32 @@ static void bmo_flag_layer_clear(BMesh *bm)
const int totflags_offset = bm->totflags - 1;
-#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
+ /* now go through and memcpy all the flag */
{
- /* now go through and memcpy all the flag */
-#pragma omp section
- {
- BMIter iter;
- BMVert_OFlag *ele;
- int i;
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
- ele->oflags[totflags_offset] = zero_flag;
- BM_elem_index_set(&ele->base, i); /* set_inline */
- }
+ BMIter iter;
+ BMVert_OFlag *ele;
+ int i;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
+ ele->oflags[totflags_offset] = zero_flag;
+ BM_elem_index_set(&ele->base, i); /* set_inline */
}
-#pragma omp section
- {
- BMIter iter;
- BMEdge_OFlag *ele;
- int i;
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
- ele->oflags[totflags_offset] = zero_flag;
- BM_elem_index_set(&ele->base, i); /* set_inline */
- }
+ }
+ {
+ BMIter iter;
+ BMEdge_OFlag *ele;
+ int i;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
+ ele->oflags[totflags_offset] = zero_flag;
+ BM_elem_index_set(&ele->base, i); /* set_inline */
}
-#pragma omp section
- {
- BMIter iter;
- BMFace_OFlag *ele;
- int i;
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
- ele->oflags[totflags_offset] = zero_flag;
- BM_elem_index_set(&ele->base, i); /* set_inline */
- }
+ }
+ {
+ BMIter iter;
+ BMFace_OFlag *ele;
+ int i;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
+ ele->oflags[totflags_offset] = zero_flag;
+ BM_elem_index_set(&ele->base, i); /* set_inline */
}
}
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index bf5fc18935d..66fcd739839 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -510,6 +510,18 @@ void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3])
}
/**
+ * expands bounds (min/max must be initialized).
+ */
+void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3])
+{
+ const BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ minmax_v3v3_v3(min, max, l_iter->v->co);
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+/**
* computes center of face in 3d. uses center of bounding box.
*/
void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3])
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index 4ec8ea59018..a40da2bfbfa 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -57,6 +57,8 @@ void BM_face_calc_center_mean_vcos(
float const (*vertexCos)[3]) ATTR_NONNULL();
void BM_face_calc_center_mean_weighted(const BMFace *f, float center[3]) ATTR_NONNULL();
+void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3]);
+
void BM_face_normal_update(BMFace *f) ATTR_NONNULL();
void BM_edge_normals_update(BMEdge *e) ATTR_NONNULL();
diff --git a/source/blender/bmesh/operators/bmo_rotate_edges.c b/source/blender/bmesh/operators/bmo_rotate_edges.c
new file mode 100644
index 00000000000..dd6bf77dd3c
--- /dev/null
+++ b/source/blender/bmesh/operators/bmo_rotate_edges.c
@@ -0,0 +1,272 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/operators/bmo_rotate_edge.c
+ * \ingroup bmesh
+ *
+ * Rotate edges topology that share two faces.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_heap.h"
+
+#include "bmesh.h"
+
+#include "intern/bmesh_operators_private.h" /* own include */
+
+#define EDGE_OUT 1
+#define FACE_MARK 1
+
+/**
+ * Rotate edges where every edge has it's own faces (we can rotate in any order).
+ */
+static void bm_rotate_edges_simple(
+ BMesh *bm, BMOperator *op,
+ const short check_flag, const bool use_ccw)
+{
+ BMOIter siter;
+ BMEdge *e;
+
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ /**
+ * this ends up being called twice, could add option to not to call check in
+ * #BM_edge_rotate to get some extra speed */
+ if (BM_edge_rotate_check(e)) {
+ BMEdge *e_rotate = BM_edge_rotate(bm, e, use_ccw, check_flag);
+ if (e_rotate != NULL) {
+ BMO_edge_flag_enable(bm, e_rotate, EDGE_OUT);
+ }
+ }
+ }
+}
+
+
+/**
+ * Edge length is just a way of ordering that's independent of order in the edges argument,
+ * we could use some other method since ideally all edges will be rotated,
+ * this just happens to be simple to calculate.
+ */
+static float bm_edge_calc_rotate_cost(const BMEdge *e)
+{
+ return -BM_edge_calc_length_squared(e);
+}
+
+/**
+ * Check if this edge is a boundary: Are more than one of the connected faces edges rotating too?
+ */
+static float bm_edge_rotate_is_boundary(const BMEdge *e)
+{
+ /* Number of adjacent shared faces. */
+ int count = 0;
+ BMLoop *l_radial_iter = e->l;
+ do {
+ /* Skip this edge. */
+ BMLoop *l_iter = l_radial_iter->next;
+ do {
+ BMEdge *e_iter = l_iter->e;
+ const int e_iter_index = BM_elem_index_get(e_iter);
+ if ((e_iter_index != -1)) {
+ if (count == 1) {
+ return false;
+ }
+ count += 1;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_radial_iter);
+ } while ((l_radial_iter = l_radial_iter->radial_next) != e->l);
+ return true;
+}
+
+/**
+ * Rotate edges where edges share faces,
+ * edges which could not rotate need to be re-considered after neighbors are rotated.
+ */
+static void bm_rotate_edges_shared(
+ BMesh *bm, BMOperator *op,
+ short check_flag, const bool use_ccw, const int edges_len)
+{
+ Heap *heap = BLI_heap_new_ex(edges_len);
+ HeapNode **eheap_table = MEM_mallocN(sizeof(*eheap_table) * edges_len, __func__);
+ int edges_len_rotate = 0;
+
+ {
+ BMIter iter;
+ BMEdge *e;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_index_set(e, -1); /* set_dirty! */
+ }
+ bm->elem_index_dirty |= BM_EDGE;
+ }
+
+ {
+ BMOIter siter;
+ BMEdge *e;
+ uint i;
+ BMO_ITER_INDEX (e, &siter, op->slots_in, "edges", BM_EDGE, i) {
+ BM_elem_index_set(e, BM_edge_is_manifold(e) ? i : -1); /* set_dirty! */
+ eheap_table[i] = NULL;
+ }
+ }
+
+ /* First operate on boundary edges, this is often all that's needed,
+ * regions that have no boundaries are handles after. */
+ enum {
+ PASS_TYPE_BOUNDARY = 0,
+ PASS_TYPE_ALL = 1,
+ PASS_TYPE_DONE = 2,
+ };
+ uint pass_type = PASS_TYPE_BOUNDARY;
+
+
+ while ((pass_type != PASS_TYPE_DONE) && (edges_len_rotate != edges_len)) {
+ BLI_assert(BLI_heap_is_empty(heap));
+ {
+ BMOIter siter;
+ BMEdge *e;
+ uint i;
+ BMO_ITER_INDEX (e, &siter, op->slots_in, "edges", BM_EDGE, i) {
+ BLI_assert(eheap_table[i] == NULL);
+
+ bool ok = (BM_elem_index_get(e) != -1) && BM_edge_rotate_check(e);
+
+ if (ok) {
+ if (pass_type == PASS_TYPE_BOUNDARY) {
+ ok = bm_edge_rotate_is_boundary(e);
+ }
+ }
+
+ if (ok) {
+ float cost = bm_edge_calc_rotate_cost(e);
+ if (pass_type == PASS_TYPE_BOUNDARY) {
+ /* Trick to ensure once started, non boundaries are handled before other boundary edges.
+ * This means the first longest boundary defines the starting point which is rotated
+ * until all its connected edges are exhausted and the next boundary is popped off the heap.
+ *
+ * Without this we may rotate from different starting points and meet in the middle
+ * with obviously uneven topology.
+ *
+ * Move from negative to positive value, inverting so large values are still handled first.
+ */
+ cost = cost != 0.0f ? -1.0f / cost : FLT_MAX;
+ }
+ eheap_table[i] = BLI_heap_insert(heap, cost, e);
+ }
+ }
+ }
+
+ if (BLI_heap_is_empty(heap)) {
+ pass_type += 1;
+ continue;
+ }
+
+ const int edges_len_rotate_prev = edges_len_rotate;
+ while (!BLI_heap_is_empty(heap)) {
+ BMEdge *e_best = BLI_heap_popmin(heap);
+ eheap_table[BM_elem_index_get(e_best)] = NULL;
+
+ /* No problem if this fails, re-evaluate if faces connected to this edge are touched. */
+ if (BM_edge_rotate_check(e_best)) {
+ BMEdge *e_rotate = BM_edge_rotate(bm, e_best, use_ccw, check_flag);
+ if (e_rotate != NULL) {
+ BMO_edge_flag_enable(bm, e_rotate, EDGE_OUT);
+
+ /* invalidate so we don't try touch this again. */
+ BM_elem_index_set(e_rotate, -1); /* set_dirty! */
+
+ edges_len_rotate += 1;
+
+ /* Note: we could validate all edges which have not been rotated
+ * (not just previously degenerate edges).
+ * However there is no real need - they can be left until they're popped off the queue. */
+
+ /* We don't know the exact topology after rotating the edge,
+ * so loop over all faces attached to the new edge, typically this will only be two faces. */
+ BMLoop *l_radial_iter = e_rotate->l;
+ do {
+ /* Skip this edge. */
+ BMLoop *l_iter = l_radial_iter->next;
+ do {
+ BMEdge *e_iter = l_iter->e;
+ const int e_iter_index = BM_elem_index_get(e_iter);
+ if ((e_iter_index != -1) && (eheap_table[e_iter_index] == NULL)) {
+ if (BM_edge_rotate_check(e_iter)) {
+ /* Previously degenerate, now valid. */
+ float cost = bm_edge_calc_rotate_cost(e_iter);
+ eheap_table[e_iter_index] = BLI_heap_insert(heap, cost, e_iter);
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_radial_iter);
+ } while ((l_radial_iter = l_radial_iter->radial_next) != e_rotate->l);
+ }
+ }
+ }
+
+ /* If no actions were taken, move onto the next pass. */
+ if (edges_len_rotate == edges_len_rotate_prev) {
+ pass_type += 1;
+ continue;
+ }
+ }
+
+ BLI_heap_free(heap, NULL);
+ MEM_freeN(eheap_table);
+}
+
+void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMEdge *e;
+ const int edges_len = BMO_slot_buffer_count(op->slots_in, "edges");
+ const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
+ const bool is_single = (edges_len == 1);
+ short check_flag = is_single ?
+ BM_EDGEROT_CHECK_EXISTS :
+ BM_EDGEROT_CHECK_EXISTS | BM_EDGEROT_CHECK_DEGENERATE;
+
+ bool is_simple = true;
+ if (is_single == false) {
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ BMFace *f_pair[2];
+ if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) {
+ for (uint i = 0; i < ARRAY_SIZE(f_pair); i += 1) {
+ if (BMO_face_flag_test(bm, f_pair[i], FACE_MARK)) {
+ is_simple = false;
+ break;
+ }
+ BMO_face_flag_enable(bm, f_pair[i], FACE_MARK);
+ }
+ if (is_simple == false) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (is_simple) {
+ bm_rotate_edges_simple(bm, op, use_ccw, check_flag);
+ }
+ else {
+ bm_rotate_edges_shared(bm, op, check_flag, use_ccw, edges_len);
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
+}
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index aa1e4bc7523..e9ee1e6e552 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -121,60 +121,6 @@ void bmo_reverse_faces_exec(BMesh *bm, BMOperator *op)
}
}
-void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op)
-{
- BMOIter siter;
- BMEdge *e, *e2;
- const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
- const bool is_single = BMO_slot_buffer_count(op->slots_in, "edges") == 1;
- short check_flag = is_single ?
- BM_EDGEROT_CHECK_EXISTS :
- BM_EDGEROT_CHECK_EXISTS | BM_EDGEROT_CHECK_DEGENERATE;
-
-#define EDGE_OUT 1
-#define FACE_TAINT 1
-
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- /**
- * this ends up being called twice, could add option to not to call check in
- * #BM_edge_rotate to get some extra speed */
- if (BM_edge_rotate_check(e)) {
- BMFace *fa, *fb;
- if (BM_edge_face_pair(e, &fa, &fb)) {
-
- /* check we're untouched */
- if (BMO_face_flag_test(bm, fa, FACE_TAINT) == false &&
- BMO_face_flag_test(bm, fb, FACE_TAINT) == false)
- {
-
- /* don't touch again (faces will be freed so run before rotating the edge) */
- BMO_face_flag_enable(bm, fa, FACE_TAINT);
- BMO_face_flag_enable(bm, fb, FACE_TAINT);
-
- if (!(e2 = BM_edge_rotate(bm, e, use_ccw, check_flag))) {
-
- BMO_face_flag_disable(bm, fa, FACE_TAINT);
- BMO_face_flag_disable(bm, fb, FACE_TAINT);
-#if 0
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Could not rotate edge");
- return;
-#endif
-
- continue;
- }
-
- BMO_edge_flag_enable(bm, e2, EDGE_OUT);
- }
- }
- }
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
-
-#undef EDGE_OUT
-#undef FACE_TAINT
-
-}
#define SEL_FLAG 1
#define SEL_ORIG 2
diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cpp b/source/blender/compositor/operations/COM_KeyingOperation.cpp
index e2566d2f4f0..fa0ef70fca6 100644
--- a/source/blender/compositor/operations/COM_KeyingOperation.cpp
+++ b/source/blender/compositor/operations/COM_KeyingOperation.cpp
@@ -67,15 +67,16 @@ void KeyingOperation::deinitExecution()
void KeyingOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- float pixelColor[4];
- float screenColor[4];
+ float pixel_color[4];
+ float screen_color[4];
- this->m_pixelReader->readSampled(pixelColor, x, y, sampler);
- this->m_screenReader->readSampled(screenColor, x, y, sampler);
+ this->m_pixelReader->readSampled(pixel_color, x, y, sampler);
+ this->m_screenReader->readSampled(screen_color, x, y, sampler);
- const int primary_channel = max_axis_v3(screenColor);
+ const int primary_channel = max_axis_v3(screen_color);
+ const float min_pixel_color = min_fff(pixel_color[0], pixel_color[1], pixel_color[2]);
- if (pixelColor[primary_channel] > 1.0f) {
+ if (min_pixel_color > 1.0f) {
/* overexposure doesn't happen on screen itself and usually happens
* on light sources in the shot, this need to be checked separately
* because saturation and falloff calculation is based on the fact
@@ -84,8 +85,8 @@ void KeyingOperation::executePixelSampled(float output[4], float x, float y, Pix
output[0] = 1.0f;
}
else {
- float saturation = get_pixel_saturation(pixelColor, this->m_screenBalance, primary_channel);
- float screen_saturation = get_pixel_saturation(screenColor, this->m_screenBalance, primary_channel);
+ float saturation = get_pixel_saturation(pixel_color, this->m_screenBalance, primary_channel);
+ float screen_saturation = get_pixel_saturation(screen_color, this->m_screenBalance, primary_channel);
if (saturation < 0) {
/* means main channel of pixel is different from screen,
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
index c915b7ef076..b268822f659 100644
--- a/source/blender/depsgraph/DEG_depsgraph_build.h
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -141,12 +141,12 @@ void DEG_add_scene_relation(struct DepsNodeHandle *node,
struct Scene *scene,
eDepsSceneComponentType component,
const char *description);
-void DEG_add_object_relation(struct DepsNodeHandle *node, struct
- Object *ob,
+void DEG_add_object_relation(struct DepsNodeHandle *node,
+ struct Object *object,
eDepsObjectComponentType component,
const char *description);
void DEG_add_bone_relation(struct DepsNodeHandle *handle,
- struct Object *ob,
+ struct Object *object,
const char *bone_name,
eDepsObjectComponentType component,
const char *description);
@@ -164,7 +164,7 @@ typedef bool (*DEG_CollobjFilterFunction)(struct Object *obj, struct ModifierDat
void DEG_add_collision_relations(struct DepsNodeHandle *handle,
struct Scene *scene,
- struct Object *ob,
+ struct Object *object,
struct Group *group,
int layer,
unsigned int modifier_type,
@@ -173,7 +173,7 @@ void DEG_add_collision_relations(struct DepsNodeHandle *handle,
const char *name);
void DEG_add_forcefield_relations(struct DepsNodeHandle *handle,
struct Scene *scene,
- struct Object *ob,
+ struct Object *object,
struct EffectorWeights *eff,
bool add_absorption,
int skip_forcefield,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 7ac94141f39..c4150e8af7a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -120,7 +120,7 @@ struct BuilderWalkUserData {
};
static void modifier_walk(void *user_data,
- struct Object * /*ob*/,
+ struct Object * /*object*/,
struct Object **obpoin,
int /*cb_flag*/)
{
@@ -190,9 +190,9 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
const char *name,
int name_tag)
{
- OperationDepsNode *op_node = comp_node->has_operation(opcode,
- name,
- name_tag);
+ OperationDepsNode *op_node = comp_node->find_operation(opcode,
+ name,
+ name_tag);
if (op_node == NULL) {
op_node = comp_node->add_operation(op, opcode, name, name_tag);
graph_->operations.push_back(op_node);
@@ -262,7 +262,7 @@ OperationDepsNode *DepsgraphNodeBuilder::find_operation_node(
int name_tag)
{
ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name);
- return comp_node->has_operation(opcode, name, name_tag);
+ return comp_node->find_operation(opcode, name, name_tag);
}
OperationDepsNode *DepsgraphNodeBuilder::find_operation_node(
@@ -309,12 +309,12 @@ void DepsgraphNodeBuilder::build_group(Base *base, Group *group)
}
}
-void DepsgraphNodeBuilder::build_object(Base *base, Object *ob)
+void DepsgraphNodeBuilder::build_object(Base *base, Object *object)
{
- const bool has_object = (ob->id.tag & LIB_TAG_DOIT);
+ const bool has_object = (object->id.tag & LIB_TAG_DOIT);
IDDepsNode *id_node = (has_object)
- ? graph_->find_id_node(&ob->id)
- : add_id_node(&ob->id);
+ ? graph_->find_id_node(&object->id)
+ : add_id_node(&object->id);
/* Update node layers.
* Do it for both new and existing ID nodes. This is so because several
* bases might be sharing same object.
@@ -322,7 +322,7 @@ void DepsgraphNodeBuilder::build_object(Base *base, Object *ob)
if (base != NULL) {
id_node->layers |= base->lay;
}
- if (ob->type == OB_CAMERA) {
+ if (object->type == OB_CAMERA) {
/* Camera should always be updated, it used directly by viewport.
*
* TODO(sergey): Make it only for active scene camera.
@@ -333,126 +333,124 @@ void DepsgraphNodeBuilder::build_object(Base *base, Object *ob)
if (has_object) {
return;
}
- ob->id.tag |= LIB_TAG_DOIT;
- ob->customdata_mask = 0;
-
- /* Standard components. */
- build_object_transform(ob);
-
- if (ob->parent != NULL) {
- build_object(NULL, ob->parent);
+ object->id.tag |= LIB_TAG_DOIT;
+ object->customdata_mask = 0;
+ /* Transform. */
+ build_object_transform(object);
+ /* Parent. */
+ if (object->parent != NULL) {
+ build_object(NULL, object->parent);
}
- if (ob->modifiers.first != NULL) {
+ /* Modifiers. */
+ if (object->modifiers.first != NULL) {
BuilderWalkUserData data;
data.builder = this;
- modifiers_foreachObjectLink(ob, modifier_walk, &data);
+ modifiers_foreachObjectLink(object, modifier_walk, &data);
}
- if (ob->constraints.first != NULL) {
+ /* Constraints. */
+ if (object->constraints.first != NULL) {
BuilderWalkUserData data;
data.builder = this;
- BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data);
+ BKE_constraints_id_loop(&object->constraints, constraint_walk, &data);
}
-
/* Object data. */
- if (ob->data != NULL) {
- /* type-specific data... */
- switch (ob->type) {
- case OB_MESH: /* Geometry */
- case OB_CURVE:
- case OB_FONT:
- case OB_SURF:
- case OB_MBALL:
- case OB_LATTICE:
- build_obdata_geom(ob);
- /* TODO(sergey): Only for until we support granular
- * update of curves.
- */
- if (ob->type == OB_FONT) {
- Curve *curve = (Curve *)ob->data;
- if (curve->textoncurve) {
- id_node->eval_flags |= DAG_EVAL_NEED_CURVE_PATH;
- }
- }
- break;
-
- case OB_ARMATURE: /* Pose */
- if (ID_IS_LINKED(ob) && ob->proxy_from != NULL) {
- build_proxy_rig(ob);
- }
- else {
- build_rig(ob);
- }
- break;
-
- case OB_LAMP: /* Lamp */
- build_lamp(ob);
- break;
-
- case OB_CAMERA: /* Camera */
- build_camera(ob);
- break;
-
- default:
- {
- ID *obdata = (ID *)ob->data;
- if ((obdata->tag & LIB_TAG_DOIT) == 0) {
- build_animdata(obdata);
- }
- break;
- }
- }
- }
-
+ build_object_data(object);
/* Build animation data,
*
* Do it now because it's possible object data will affect
* on object's level animation, for example in case of rebuilding
* pose for proxy.
*/
- build_animdata(&ob->id);
-
- /* particle systems */
- if (ob->particlesystem.first != NULL) {
- build_particles(ob);
+ build_animdata(&object->id);
+ /* Particle systems. */
+ if (object->particlesystem.first != NULL) {
+ build_particles(object);
}
-
/* Grease pencil. */
- if (ob->gpd != NULL) {
- build_gpencil(ob->gpd);
+ if (object->gpd != NULL) {
+ build_gpencil(object->gpd);
}
-
/* Object that this is a proxy for. */
- if (ob->proxy) {
- ob->proxy->proxy_from = ob;
- build_object(base, ob->proxy);
+ if (object->proxy) {
+ object->proxy->proxy_from = object;
+ build_object(base, object->proxy);
}
-
/* Object dupligroup. */
- if (ob->dup_group != NULL) {
- build_group(base, ob->dup_group);
+ if (object->dup_group != NULL) {
+ build_group(base, object->dup_group);
}
}
-void DepsgraphNodeBuilder::build_object_transform(Object *ob)
+void DepsgraphNodeBuilder::build_object_data(Object *object)
+{
+ if (object->data == NULL) {
+ return;
+ }
+ IDDepsNode *id_node = graph_->find_id_node(&object->id);
+ /* type-specific data... */
+ switch (object->type) {
+ case OB_MESH: /* Geometry */
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ case OB_MBALL:
+ case OB_LATTICE:
+ build_obdata_geom(object);
+ /* TODO(sergey): Only for until we support granular
+ * update of curves.
+ */
+ if (object->type == OB_FONT) {
+ Curve *curve = (Curve *)object->data;
+ if (curve->textoncurve) {
+ id_node->eval_flags |= DAG_EVAL_NEED_CURVE_PATH;
+ }
+ }
+ break;
+ case OB_ARMATURE:
+ if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
+ build_proxy_rig(object);
+ }
+ else {
+ build_rig(object);
+ }
+ break;
+ case OB_LAMP:
+ build_lamp(object);
+ break;
+ case OB_CAMERA:
+ build_camera(object);
+ break;
+ default:
+ {
+ ID *obdata = (ID *)object->data;
+ if ((obdata->tag & LIB_TAG_DOIT) == 0) {
+ build_animdata(obdata);
+ }
+ break;
+ }
+ }
+}
+
+void DepsgraphNodeBuilder::build_object_transform(Object *object)
{
OperationDepsNode *op_node;
/* local transforms (from transform channels - loc/rot/scale + deltas) */
- op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_object_eval_local_transform, _1, scene_, ob),
+ op_node = add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_local_transform, _1, scene_, object),
DEG_OPCODE_TRANSFORM_LOCAL);
op_node->set_as_entry();
/* object parent */
- if (ob->parent) {
- add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_object_eval_parent, _1, scene_, ob),
+ if (object->parent) {
+ add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_parent, _1, scene_, object),
DEG_OPCODE_TRANSFORM_PARENT);
}
/* object constraints */
- if (ob->constraints.first) {
- build_object_constraints(ob);
+ if (object->constraints.first) {
+ build_object_constraints(object);
}
/* Temporary uber-update node, which does everything.
@@ -462,13 +460,13 @@ void DepsgraphNodeBuilder::build_object_transform(Object *ob)
*
* TODO(sergey): Get rid of this node.
*/
- add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_object_eval_uber_transform, _1, scene_, ob),
+ add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_uber_transform, _1, scene_, object),
DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL);
/* object transform is done */
- op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_object_eval_done, _1, ob),
+ op_node = add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_done, _1, object),
DEG_OPCODE_TRANSFORM_FINAL);
op_node->set_as_exit();
}
@@ -490,11 +488,11 @@ void DepsgraphNodeBuilder::build_object_transform(Object *ob)
*
* -- Aligorith, August 2013
*/
-void DepsgraphNodeBuilder::build_object_constraints(Object *ob)
+void DepsgraphNodeBuilder::build_object_constraints(Object *object)
{
/* create node for constraint stack */
- add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_object_eval_constraints, _1, scene_, ob),
+ add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_constraints, _1, scene_, object),
DEG_OPCODE_TRANSFORM_CONSTRAINTS);
}
@@ -632,21 +630,21 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
/* objects - simulation participants */
if (rbw->group) {
LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) {
- Object *ob = go->ob;
+ Object *object = go->ob;
- if (!ob || (ob->type != OB_MESH))
+ if (!object || (object->type != OB_MESH))
continue;
/* 2) create operation for flushing results */
/* object's transform component - where the rigidbody operation lives */
- add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, ob),
+ add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, object),
DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY);
}
}
}
-void DepsgraphNodeBuilder::build_particles(Object *ob)
+void DepsgraphNodeBuilder::build_particles(Object *object)
{
/**
* Particle Systems Nodes
@@ -665,17 +663,17 @@ void DepsgraphNodeBuilder::build_particles(Object *ob)
/* component for all particle systems */
ComponentDepsNode *psys_comp =
- add_component_node(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES);
+ add_component_node(&object->id, DEG_NODE_TYPE_EVAL_PARTICLES);
add_operation_node(psys_comp,
function_bind(BKE_particle_system_eval_init,
_1,
scene_,
- ob),
+ object),
DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT);
/* particle systems */
- LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
+ LINKLIST_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
ParticleSettings *part = psys->part;
/* particle settings */
@@ -717,9 +715,9 @@ void DepsgraphNodeBuilder::build_shapekeys(Key *key)
/* ObData Geometry Evaluation */
// XXX: what happens if the datablock is shared!
-void DepsgraphNodeBuilder::build_obdata_geom(Object *ob)
+void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
{
- ID *obdata = (ID *)ob->data;
+ ID *obdata = (ID *)object->data;
OperationDepsNode *op_node;
/* TODO(sergey): This way using this object's properties as driver target
@@ -727,7 +725,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob)
*
* Does this depend on other nodes?
*/
- op_node = add_operation_node(&ob->id,
+ op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PARAMETERS_EVAL);
@@ -740,16 +738,16 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob)
*
* TODO(sergey): Get rid of this node.
*/
- op_node = add_operation_node(&ob->id,
+ op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_GEOMETRY,
- function_bind(BKE_object_eval_uber_data,
- _1,
- scene_,
- ob),
+ function_bind(BKE_object_eval_uber_data,
+ _1,
+ scene_,
+ object),
DEG_OPCODE_GEOMETRY_UBEREVAL);
op_node->set_as_exit();
- op_node = add_operation_node(&ob->id,
+ op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_GEOMETRY,
NULL,
DEG_OPCODE_PLACEHOLDER,
@@ -759,22 +757,22 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob)
// TODO: "Done" operation
/* Cloyth modifier. */
- LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) {
+ LINKLIST_FOREACH (ModifierData *, md, &object->modifiers) {
if (md->type == eModifierType_Cloth) {
- build_cloth(ob);
+ build_cloth(object);
}
}
/* materials */
- for (int a = 1; a <= ob->totcol; a++) {
- Material *ma = give_current_material(ob, a);
+ for (int a = 1; a <= object->totcol; a++) {
+ Material *ma = give_current_material(object, a);
if (ma != NULL) {
build_material(ma);
}
}
/* geometry collision */
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
+ if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
// add geometry collider relations
}
@@ -783,7 +781,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob)
}
/* ShapeKeys */
- Key *key = BKE_key_from_object(ob);
+ Key *key = BKE_key_from_object(object);
if (key) {
build_shapekeys(key);
}
@@ -793,10 +791,10 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob)
/* Nodes for result of obdata's evaluation, and geometry
* evaluation on object.
*/
- switch (ob->type) {
+ switch (object->type) {
case OB_MESH:
{
- //Mesh *me = (Mesh *)ob->data;
+ //Mesh *me = (Mesh *)object->data;
/* evaluation operations */
op_node = add_operation_node(obdata,
@@ -812,11 +810,12 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob)
case OB_MBALL:
{
- Object *mom = BKE_mball_basis_find(scene_, ob);
- /* Motherball - mom depends on children! */
- if (mom == ob) {
+ Object *mom = BKE_mball_basis_find(scene_, object);
+ /* NOTE: Only the motherball gets evaluated, it's children are
+ * having empty placeholders for the correct relations being built.
+ */
+ if (mom == object) {
/* metaball evaluation operations */
- /* NOTE: only the motherball gets evaluated! */
op_node = add_operation_node(obdata,
DEG_NODE_TYPE_GEOMETRY,
function_bind(BKE_mball_eval_geometry,
@@ -824,6 +823,13 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob)
(MetaBall *)obdata),
DEG_OPCODE_PLACEHOLDER,
"Geometry Eval");
+ }
+ else {
+ op_node = add_operation_node(obdata,
+ DEG_NODE_TYPE_GEOMETRY,
+ NULL,
+ DEG_OPCODE_PLACEHOLDER,
+ "Geometry Eval");
op_node->set_as_entry();
}
break;
@@ -854,7 +860,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob)
if (cu->taperobj != NULL) {
build_object(NULL, cu->taperobj);
}
- if (ob->type == OB_FONT && cu->textoncurve != NULL) {
+ if (object->type == OB_FONT && cu->textoncurve != NULL) {
build_object(NULL, cu->textoncurve);
}
break;
@@ -887,10 +893,10 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob)
}
/* Cameras */
-void DepsgraphNodeBuilder::build_camera(Object *ob)
+void DepsgraphNodeBuilder::build_camera(Object *object)
{
/* TODO: Link scene-camera links in somehow... */
- Camera *cam = (Camera *)ob->data;
+ Camera *cam = (Camera *)object->data;
ID *camera_id = &cam->id;
if (camera_id->tag & LIB_TAG_DOIT) {
return;
@@ -905,15 +911,15 @@ void DepsgraphNodeBuilder::build_camera(Object *ob)
if (cam->dof_ob != NULL) {
/* TODO(sergey): For now parametrs are on object level. */
- add_operation_node(&ob->id, DEG_NODE_TYPE_PARAMETERS, NULL,
+ add_operation_node(&object->id, DEG_NODE_TYPE_PARAMETERS, NULL,
DEG_OPCODE_PLACEHOLDER, "Camera DOF");
}
}
/* Lamps */
-void DepsgraphNodeBuilder::build_lamp(Object *ob)
+void DepsgraphNodeBuilder::build_lamp(Object *object)
{
- Lamp *la = (Lamp *)ob->data;
+ Lamp *la = (Lamp *)object->data;
ID *lamp_id = &la->id;
if (lamp_id->tag & LIB_TAG_DOIT) {
return;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index ec9fe6a40a2..2fa9ba01cc7 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -120,27 +120,28 @@ struct DepsgraphNodeBuilder {
void build_scene(Scene *scene);
void build_group(Base *base, Group *group);
- void build_object(Base *base, Object *ob);
- void build_object_transform(Object *ob);
- void build_object_constraints(Object *ob);
- void build_pose_constraints(Object *ob, bPoseChannel *pchan);
+ void build_object(Base *base, Object *object);
+ void build_object_data(Object *object);
+ void build_object_transform(Object *object);
+ void build_object_constraints(Object *object);
+ void build_pose_constraints(Object *object, bPoseChannel *pchan);
void build_rigidbody(Scene *scene);
- void build_particles(Object *ob);
+ void build_particles(Object *object);
void build_cloth(Object *object);
void build_animdata(ID *id);
OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
- void build_ik_pose(Object *ob,
+ void build_ik_pose(Object *object,
bPoseChannel *pchan,
bConstraint *con);
- void build_splineik_pose(Object *ob,
+ void build_splineik_pose(Object *object,
bPoseChannel *pchan,
bConstraint *con);
- void build_rig(Object *ob);
- void build_proxy_rig(Object *ob);
+ void build_rig(Object *object);
+ void build_proxy_rig(Object *object);
void build_shapekeys(Key *key);
- void build_obdata_geom(Object *ob);
- void build_camera(Object *ob);
- void build_lamp(Object *ob);
+ void build_obdata_geom(Object *object);
+ void build_camera(Object *object);
+ void build_lamp(Object *object);
void build_nodetree(bNodeTree *ntree);
void build_material(Material *ma);
void build_texture(Tex *tex);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
index a1f20b1c683..caf6f60165c 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
@@ -64,16 +64,16 @@ extern "C" {
namespace DEG {
-void DepsgraphNodeBuilder::build_pose_constraints(Object *ob, bPoseChannel *pchan)
+void DepsgraphNodeBuilder::build_pose_constraints(Object *object, bPoseChannel *pchan)
{
/* create node for constraint stack */
- add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
- function_bind(BKE_pose_constraints_evaluate, _1, scene_, ob, pchan),
+ add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
+ function_bind(BKE_pose_constraints_evaluate, _1, scene_, object, pchan),
DEG_OPCODE_BONE_CONSTRAINTS);
}
/* IK Solver Eval Steps */
-void DepsgraphNodeBuilder::build_ik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con)
+void DepsgraphNodeBuilder::build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con)
{
bKinematicConstraint *data = (bKinematicConstraint *)con->data;
@@ -83,20 +83,20 @@ void DepsgraphNodeBuilder::build_ik_pose(Object *ob, bPoseChannel *pchan, bConst
return;
}
- if (has_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
+ if (has_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
DEG_OPCODE_POSE_IK_SOLVER))
{
return;
}
/* Operation node for evaluating/running IK Solver. */
- add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
- function_bind(BKE_pose_iktree_evaluate, _1, scene_, ob, rootchan),
+ add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
+ function_bind(BKE_pose_iktree_evaluate, _1, scene_, object, rootchan),
DEG_OPCODE_POSE_IK_SOLVER);
}
/* Spline IK Eval Steps */
-void DepsgraphNodeBuilder::build_splineik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con)
+void DepsgraphNodeBuilder::build_splineik_pose(Object *object, bPoseChannel *pchan, bConstraint *con)
{
bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
@@ -106,15 +106,15 @@ void DepsgraphNodeBuilder::build_splineik_pose(Object *ob, bPoseChannel *pchan,
/* Operation node for evaluating/running Spline IK Solver.
* Store the "root bone" of this chain in the solver, so it knows where to start.
*/
- add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
- function_bind(BKE_pose_splineik_evaluate, _1, scene_, ob, rootchan),
+ add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
+ function_bind(BKE_pose_splineik_evaluate, _1, scene_, object, rootchan),
DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
}
/* Pose/Armature Bones Graph */
-void DepsgraphNodeBuilder::build_rig(Object *ob)
+void DepsgraphNodeBuilder::build_rig(Object *object)
{
- bArmature *arm = (bArmature *)ob->data;
+ bArmature *arm = (bArmature *)object->data;
OperationDepsNode *op_node;
/* animation and/or drivers linking posebones to base-armature used to define them
@@ -135,22 +135,22 @@ void DepsgraphNodeBuilder::build_rig(Object *ob)
}
/* Rebuild pose if not up to date. */
- if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
- BKE_pose_rebuild_ex(ob, arm, false);
+ if (object->pose == NULL || (object->pose->flag & POSE_RECALC)) {
+ BKE_pose_rebuild_ex(object, arm, false);
/* XXX: Without this animation gets lost in certain circumstances
* after loading file. Need to investigate further since it does
* not happen with simple scenes..
*/
- if (ob->adt) {
- ob->adt->recalc |= ADT_RECALC_ANIM;
+ if (object->adt) {
+ object->adt->recalc |= ADT_RECALC_ANIM;
}
}
/* speed optimization for animation lookups */
- if (ob->pose) {
- BKE_pose_channels_hash_make(ob->pose);
- if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
- BKE_pose_update_constraint_flags(ob->pose);
+ if (object->pose) {
+ BKE_pose_channels_hash_make(object->pose);
+ if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
+ BKE_pose_update_constraint_flags(object->pose);
}
}
@@ -177,46 +177,46 @@ void DepsgraphNodeBuilder::build_rig(Object *ob)
*/
/* pose eval context */
- op_node = add_operation_node(&ob->id,
+ op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
- function_bind(BKE_pose_eval_init, _1, scene_, ob, ob->pose),
+ function_bind(BKE_pose_eval_init, _1, scene_, object, object->pose),
DEG_OPCODE_POSE_INIT);
op_node->set_as_entry();
- op_node = add_operation_node(&ob->id,
+ op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
- function_bind(BKE_pose_eval_init_ik, _1, scene_, ob, ob->pose),
+ function_bind(BKE_pose_eval_init_ik, _1, scene_, object, object->pose),
DEG_OPCODE_POSE_INIT_IK);
- op_node = add_operation_node(&ob->id,
+ op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
- function_bind(BKE_pose_eval_flush, _1, scene_, ob, ob->pose),
+ function_bind(BKE_pose_eval_flush, _1, scene_, object, object->pose),
DEG_OPCODE_POSE_DONE);
op_node->set_as_exit();
/* bones */
- LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
/* node for bone eval */
- op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, NULL,
+ op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, NULL,
DEG_OPCODE_BONE_LOCAL);
op_node->set_as_entry();
- add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
- function_bind(BKE_pose_eval_bone, _1, scene_, ob, pchan),
+ add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
+ function_bind(BKE_pose_eval_bone, _1, scene_, object, pchan),
DEG_OPCODE_BONE_POSE_PARENT);
- add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
NULL, /* NOTE: dedicated noop for easier relationship construction */
DEG_OPCODE_BONE_READY);
- op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
function_bind(BKE_pose_bone_done, _1, pchan),
DEG_OPCODE_BONE_DONE);
op_node->set_as_exit();
/* constraints */
if (pchan->constraints.first != NULL) {
- build_pose_constraints(ob, pchan);
+ build_pose_constraints(object, pchan);
}
/**
@@ -233,11 +233,11 @@ void DepsgraphNodeBuilder::build_rig(Object *ob)
LINKLIST_FOREACH (bConstraint *, con, &pchan->constraints) {
switch (con->type) {
case CONSTRAINT_TYPE_KINEMATIC:
- build_ik_pose(ob, pchan, con);
+ build_ik_pose(object, pchan, con);
break;
case CONSTRAINT_TYPE_SPLINEIK:
- build_splineik_pose(ob, pchan, con);
+ build_splineik_pose(object, pchan, con);
break;
default:
@@ -247,41 +247,41 @@ void DepsgraphNodeBuilder::build_rig(Object *ob)
}
}
-void DepsgraphNodeBuilder::build_proxy_rig(Object *ob)
+void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
{
- ID *obdata = (ID *)ob->data;
+ ID *obdata = (ID *)object->data;
OperationDepsNode *op_node;
build_animdata(obdata);
- BLI_assert(ob->pose != NULL);
+ BLI_assert(object->pose != NULL);
/* speed optimization for animation lookups */
- BKE_pose_channels_hash_make(ob->pose);
- if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
- BKE_pose_update_constraint_flags(ob->pose);
+ BKE_pose_channels_hash_make(object->pose);
+ if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
+ BKE_pose_update_constraint_flags(object->pose);
}
- op_node = add_operation_node(&ob->id,
+ op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
- function_bind(BKE_pose_eval_proxy_copy, _1, ob),
+ function_bind(BKE_pose_eval_proxy_copy, _1, object),
DEG_OPCODE_POSE_INIT);
op_node->set_as_entry();
- LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
NULL, DEG_OPCODE_BONE_LOCAL);
op_node->set_as_entry();
- add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
NULL, DEG_OPCODE_BONE_READY);
- op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
NULL, DEG_OPCODE_BONE_DONE);
op_node->set_as_exit();
}
- op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE,
+ op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE,
NULL, DEG_OPCODE_POSE_DONE);
op_node->set_as_exit();
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
index 1ea44093cd7..a7b2906cefd 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
@@ -83,8 +83,8 @@ void DepsgraphNodeBuilder::build_scene(Scene *scene)
/* scene objects */
LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *ob = base->object;
- build_object(base, ob);
+ Object *object = base->object;
+ build_object(base, object);
}
/* rigidbody */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 3448525a50d..293f63e9db2 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -120,7 +120,7 @@ struct BuilderWalkUserData {
};
static void modifier_walk(void *user_data,
- struct Object * /*ob*/,
+ struct Object * /*object*/,
struct Object **obpoin,
int /*cb_flag*/)
{
@@ -175,6 +175,31 @@ static bool python_driver_depends_on_time(ChannelDriver *driver)
return false;
}
+static bool particle_system_depends_on_time(ParticleSystem *psys)
+{
+ ParticleSettings *part = psys->part;
+ /* Non-hair particles we always consider dependent on time. */
+ if (part->type != PART_HAIR) {
+ return true;
+ }
+ /* Dynamics always depends on time. */
+ if (psys->flag & PSYS_HAIR_DYNAMICS) {
+ return true;
+ }
+ /* TODO(sergey): Check what else makes hair dependent on time. */
+ return false;
+}
+
+static bool object_particles_depends_on_time(Object *object)
+{
+ LINKLIST_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
+ if (particle_system_depends_on_time(psys)) {
+ return true;
+ }
+ }
+ return false;
+}
+
/* **** General purpose functions **** */
RNAPathKey::RNAPathKey(ID *id, const char *path) :
@@ -199,7 +224,7 @@ DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain,
{
}
-TimeSourceDepsNode *DepsgraphRelationBuilder::find_node(
+TimeSourceDepsNode *DepsgraphRelationBuilder::get_node(
const TimeSourceKey &key) const
{
if (key.id) {
@@ -211,7 +236,7 @@ TimeSourceDepsNode *DepsgraphRelationBuilder::find_node(
}
}
-ComponentDepsNode *DepsgraphRelationBuilder::find_node(
+ComponentDepsNode *DepsgraphRelationBuilder::get_node(
const ComponentKey &key) const
{
IDDepsNode *id_node = graph_->find_id_node(key.id);
@@ -225,38 +250,23 @@ ComponentDepsNode *DepsgraphRelationBuilder::find_node(
return node;
}
-OperationDepsNode *DepsgraphRelationBuilder::find_node(
+OperationDepsNode *DepsgraphRelationBuilder::get_node(
const OperationKey &key) const
{
- IDDepsNode *id_node = graph_->find_id_node(key.id);
- if (!id_node) {
- fprintf(stderr, "find_node operation: Could not find ID\n");
- return NULL;
- }
-
- ComponentDepsNode *comp_node = id_node->find_component(key.component_type,
- key.component_name);
- if (!comp_node) {
- fprintf(stderr, "find_node operation: Could not find component\n");
- return NULL;
- }
-
- OperationDepsNode *op_node = comp_node->find_operation(key.opcode,
- key.name,
- key.name_tag);
- if (!op_node) {
+ OperationDepsNode *op_node = find_node(key);
+ if (op_node == NULL) {
fprintf(stderr, "find_node_operation: Failed for (%s, '%s')\n",
DEG_OPNAMES[key.opcode], key.name);
}
return op_node;
}
-DepsNode *DepsgraphRelationBuilder::find_node(const RNAPathKey &key) const
+DepsNode *DepsgraphRelationBuilder::get_node(const RNAPathKey &key) const
{
return graph_->find_node_from_pointer(&key.ptr, key.prop);
}
-OperationDepsNode *DepsgraphRelationBuilder::has_node(
+OperationDepsNode *DepsgraphRelationBuilder::find_node(
const OperationKey &key) const
{
IDDepsNode *id_node = graph_->find_id_node(key.id);
@@ -268,7 +278,12 @@ OperationDepsNode *DepsgraphRelationBuilder::has_node(
if (!comp_node) {
return NULL;
}
- return comp_node->has_operation(key.opcode, key.name, key.name_tag);
+ return comp_node->find_operation(key.opcode, key.name, key.name_tag);
+}
+
+bool DepsgraphRelationBuilder::has_node(const OperationKey &key) const
+{
+ return find_node(key) != NULL;
}
void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
@@ -302,10 +317,10 @@ void DepsgraphRelationBuilder::add_operation_relation(
}
}
-void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, Scene *scene, Object *ob, Group *group, int layer, bool dupli, const char *name)
+void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, Scene *scene, Object *object, Group *group, int layer, bool dupli, const char *name)
{
unsigned int numcollobj;
- Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, eModifierType_Collision, dupli);
+ Object **collobjs = get_collisionobjects_ext(scene, object, group, layer, &numcollobj, eModifierType_Collision, dupli);
for (unsigned int i = 0; i < numcollobj; i++)
{
@@ -322,19 +337,19 @@ void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key,
MEM_freeN(collobjs);
}
-void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name)
+void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, Scene *scene, Object *object, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name)
{
- ListBase *effectors = pdInitEffectors(scene, ob, psys, eff, false);
+ ListBase *effectors = pdInitEffectors(scene, object, psys, eff, false);
if (effectors) {
for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) {
- if (eff->ob != ob) {
+ if (eff->ob != object) {
ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(eff_key, key, name);
}
if (eff->psys) {
- if (eff->ob != ob) {
+ if (eff->ob != object) {
ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES);
add_relation(eff_key, key, name);
@@ -357,7 +372,7 @@ void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key,
}
if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
- add_collision_relations(key, scene, ob, NULL, eff->ob->lay, true, "Force Absorption");
+ add_collision_relations(key, scene, object, NULL, eff->ob->lay, true, "Force Absorption");
}
}
}
@@ -407,60 +422,63 @@ void DepsgraphRelationBuilder::build_group(Object *object, Group *group)
group_id->tag |= LIB_TAG_DOIT;
}
-void DepsgraphRelationBuilder::build_object(Object *ob)
+void DepsgraphRelationBuilder::build_object(Object *object)
{
- if (ob->id.tag & LIB_TAG_DOIT) {
+ if (object->id.tag & LIB_TAG_DOIT) {
return;
}
- ob->id.tag |= LIB_TAG_DOIT;
-
+ object->id.tag |= LIB_TAG_DOIT;
/* Object Transforms */
- eDepsOperation_Code base_op = (ob->parent) ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL;
- OperationKey base_op_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, base_op);
-
- OperationKey local_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
- OperationKey parent_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
- OperationKey final_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
-
- OperationKey ob_ubereval_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL);
-
- /* parenting */
- if (ob->parent != NULL) {
- /* parent relationship */
- build_object_parent(ob);
-
- /* local -> parent */
- add_relation(local_transform_key, parent_transform_key, "[ObLocal -> ObParent]");
- }
-
- if (ob->modifiers.first != NULL) {
+ eDepsOperation_Code base_op = (object->parent) ? DEG_OPCODE_TRANSFORM_PARENT
+ : DEG_OPCODE_TRANSFORM_LOCAL;
+ OperationKey base_op_key(&object->id, DEG_NODE_TYPE_TRANSFORM, base_op);
+ OperationKey local_transform_key(&object->id,
+ DEG_NODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_LOCAL);
+ OperationKey parent_transform_key(&object->id,
+ DEG_NODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_PARENT);
+ OperationKey final_transform_key(&object->id,
+ DEG_NODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_FINAL);
+ OperationKey ob_ubereval_key(&object->id,
+ DEG_NODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL);
+ /* Parenting. */
+ if (object->parent != NULL) {
+ /* Parent relationship. */
+ build_object_parent(object);
+ /* Local -> parent. */
+ add_relation(local_transform_key,
+ parent_transform_key,
+ "[ObLocal -> ObParent]");
+ }
+ /* Modifiers. */
+ if (object->modifiers.first != NULL) {
BuilderWalkUserData data;
data.builder = this;
- modifiers_foreachObjectLink(ob, modifier_walk, &data);
+ modifiers_foreachObjectLink(object, modifier_walk, &data);
}
- if (ob->constraints.first != NULL) {
+ /* Constraints. */
+ if (object->constraints.first != NULL) {
BuilderWalkUserData data;
data.builder = this;
- BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data);
+ BKE_constraints_id_loop(&object->constraints, constraint_walk, &data);
}
-
- /* object constraints */
- if (ob->constraints.first != NULL) {
- OperationKey constraint_key(&ob->id,
+ /* Object constraints. */
+ if (object->constraints.first != NULL) {
+ OperationKey constraint_key(&object->id,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_CONSTRAINTS);
-
- /* constraint relations */
- build_constraints(&ob->id,
+ /* Constraint relations. */
+ build_constraints(&object->id,
DEG_NODE_TYPE_TRANSFORM,
"",
- &ob->constraints,
+ &object->constraints,
NULL);
-
/* operation order */
add_relation(base_op_key, constraint_key, "[ObBase-> Constraint Stack]");
add_relation(constraint_key, final_transform_key, "[ObConstraints -> Done]");
-
// XXX
add_relation(constraint_key, ob_ubereval_key, "Temp Ubereval");
add_relation(ob_ubereval_key, final_transform_key, "Temp Ubereval");
@@ -470,7 +488,7 @@ void DepsgraphRelationBuilder::build_object(Object *ob)
* dependencies and avoid transitive relations which causes overhead.
* But once we get rid of uber eval node this will need reconsideration.
*/
- if (ob->rigidbody_object == NULL) {
+ if (object->rigidbody_object == NULL) {
/* Rigid body will hook up another node inbetween, so skip
* relation here to avoid transitive relation.
*/
@@ -478,105 +496,98 @@ void DepsgraphRelationBuilder::build_object(Object *ob)
}
add_relation(ob_ubereval_key, final_transform_key, "Temp Ubereval");
}
-
- /* AnimData */
- build_animdata(&ob->id);
-
+ /* Animation data */
+ build_animdata(&object->id);
// XXX: This should be hooked up by the build_animdata code
- if (needs_animdata_node(&ob->id)) {
- ComponentKey adt_key(&ob->id, DEG_NODE_TYPE_ANIMATION);
+ if (needs_animdata_node(&object->id)) {
+ ComponentKey adt_key(&object->id, DEG_NODE_TYPE_ANIMATION);
add_relation(adt_key, local_transform_key, "Object Animation");
}
-
- /* object data */
- if (ob->data) {
- ID *obdata_id = (ID *)ob->data;
-
- /* ob data animation */
- build_animdata(obdata_id);
-
- /* type-specific data... */
- switch (ob->type) {
- case OB_MESH: /* Geometry */
- case OB_CURVE:
- case OB_FONT:
- case OB_SURF:
- case OB_MBALL:
- case OB_LATTICE:
- {
- build_obdata_geom(ob);
- break;
- }
-
- case OB_ARMATURE: /* Pose */
- if (ID_IS_LINKED(ob) && ob->proxy_from != NULL) {
- build_proxy_rig(ob);
- }
- else {
- build_rig(ob);
- }
- break;
-
- case OB_LAMP: /* Lamp */
- build_lamp(ob);
- break;
-
- case OB_CAMERA: /* Camera */
- build_camera(ob);
- break;
- }
-
- Key *key = BKE_key_from_object(ob);
- if (key != NULL) {
- ComponentKey geometry_key((ID *)ob->data, DEG_NODE_TYPE_GEOMETRY);
- ComponentKey key_key(&key->id, DEG_NODE_TYPE_GEOMETRY);
- add_relation(key_key, geometry_key, "Shapekeys");
- }
- }
-
+ /* Object data. */
+ build_object_data(object);
/* Particle systems. */
- if (ob->particlesystem.first != NULL) {
- build_particles(ob);
+ if (object->particlesystem.first != NULL) {
+ build_particles(object);
}
-
/* Grease pencil. */
- if (ob->gpd != NULL) {
- build_gpencil(ob->gpd);
+ if (object->gpd != NULL) {
+ build_gpencil(object->gpd);
}
-
/* Object that this is a proxy for. */
- if (ob->proxy != NULL) {
- ob->proxy->proxy_from = ob;
- build_object(ob->proxy);
+ if (object->proxy != NULL) {
+ object->proxy->proxy_from = object;
+ build_object(object->proxy);
/* TODO(sergey): This is an inverted relation, matches old depsgraph
* behavior and need to be investigated if it still need to be inverted.
*/
- ComponentKey ob_pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
- ComponentKey proxy_pose_key(&ob->proxy->id, DEG_NODE_TYPE_EVAL_POSE);
+ ComponentKey ob_pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE);
+ ComponentKey proxy_pose_key(&object->proxy->id, DEG_NODE_TYPE_EVAL_POSE);
add_relation(ob_pose_key, proxy_pose_key, "Proxy");
}
-
/* Object dupligroup. */
- if (ob->dup_group != NULL) {
- build_group(ob, ob->dup_group);
+ if (object->dup_group != NULL) {
+ build_group(object, object->dup_group);
}
}
-void DepsgraphRelationBuilder::build_object_parent(Object *ob)
+void DepsgraphRelationBuilder::build_object_data(Object *object)
+{
+ if (object->data == NULL) {
+ return;
+ }
+ ID *obdata_id = (ID *)object->data;
+ /* Object data animation. */
+ build_animdata(obdata_id);
+ /* type-specific data. */
+ switch (object->type) {
+ case OB_MESH:
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ case OB_MBALL:
+ case OB_LATTICE:
+ {
+ build_obdata_geom(object);
+ break;
+ }
+ case OB_ARMATURE:
+ if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
+ build_proxy_rig(object);
+ }
+ else {
+ build_rig(object);
+ }
+ break;
+ case OB_LAMP:
+ build_lamp(object);
+ break;
+ case OB_CAMERA:
+ build_camera(object);
+ break;
+ }
+ Key *key = BKE_key_from_object(object);
+ if (key != NULL) {
+ ComponentKey geometry_key((ID *)object->data, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey key_key(&key->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(key_key, geometry_key, "Shapekeys");
+ }
+}
+
+void DepsgraphRelationBuilder::build_object_parent(Object *object)
{
/* XXX: for now, need to use the component key (not just direct to the parent op),
* or else the matrix doesn't get reset/
*/
// XXX: @sergey - it would be good if we got that backwards flushing working
// when tagging for updates.
- //OperationKey ob_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
- ComponentKey ob_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ //OperationKey ob_key(&object->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
+ ComponentKey ob_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
/* type-specific links */
- switch (ob->partype) {
+ switch (object->partype) {
case PARSKEL: /* Armature Deform (Virtual Modifier) */
{
- ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(parent_key, ob_key, "Armature Deform Parent");
break;
}
@@ -584,7 +595,7 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob)
case PARVERT1: /* Vertex Parent */
case PARVERT3:
{
- ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_GEOMETRY);
add_relation(parent_key, ob_key, "Vertex Parent");
/* XXX not sure what this is for or how you could be done properly - lukas */
@@ -593,17 +604,17 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob)
parent_node->customdata_mask |= CD_MASK_ORIGINDEX;
}
- ComponentKey transform_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey transform_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(transform_key, ob_key, "Vertex Parent TFM");
break;
}
case PARBONE: /* Bone Parent */
{
- ComponentKey parent_bone_key(&ob->parent->id,
+ ComponentKey parent_bone_key(&object->parent->id,
DEG_NODE_TYPE_BONE,
- ob->parsubstr);
- OperationKey parent_transform_key(&ob->parent->id,
+ object->parsubstr);
+ OperationKey parent_transform_key(&object->parent->id,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_FINAL);
add_relation(parent_bone_key, ob_key, "Bone Parent");
@@ -613,35 +624,35 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob)
default:
{
- if (ob->parent->type == OB_LATTICE) {
+ if (object->parent->type == OB_LATTICE) {
/* Lattice Deform Parent - Virtual Modifier */
// XXX: no virtual modifiers should be left!
- ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
- ComponentKey geom_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey geom_key(&object->parent->id, DEG_NODE_TYPE_GEOMETRY);
add_relation(parent_key, ob_key, "Lattice Deform Parent");
add_relation(geom_key, ob_key, "Lattice Deform Parent Geom");
}
- else if (ob->parent->type == OB_CURVE) {
- Curve *cu = (Curve *)ob->parent->data;
+ else if (object->parent->type == OB_CURVE) {
+ Curve *cu = (Curve *)object->parent->data;
if (cu->flag & CU_PATH) {
/* Follow Path */
- ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_GEOMETRY);
add_relation(parent_key, ob_key, "Curve Follow Parent");
- ComponentKey transform_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey transform_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(transform_key, ob_key, "Curve Follow TFM");
}
else {
/* Standard Parent */
- ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(parent_key, ob_key, "Curve Parent");
}
}
else {
/* Standard Parent */
- ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(parent_key, ob_key, "Parent");
}
break;
@@ -649,7 +660,7 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob)
}
/* exception case: parent is duplivert */
- if ((ob->type == OB_MBALL) && (ob->parent->transflag & OB_DUPLIVERTS)) {
+ if ((object->type == OB_MBALL) && (object->parent->transflag & OB_DUPLIVERTS)) {
//dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Duplivert");
}
}
@@ -982,11 +993,11 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
/* TODO: ideally, if this is for a constraint, it goes to said
* constraint.
*/
- Object *ob = (Object *)id;
+ Object *object = (Object *)id;
char *bone_name;
bone_name = BLI_str_quoted_substrN(rna_path, "pose.bones[");
- pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ pchan = BKE_pose_channel_find_name(object->pose, bone_name);
if (bone_name) {
MEM_freeN(bone_name);
@@ -1021,12 +1032,12 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
IDDepsNode *to_node = (IDDepsNode *)rel->to;
/* We only care about objects with pose data which use this. */
if (GS(to_node->id->name) == ID_OB) {
- Object *ob = (Object *)to_node->id;
- /* NOTE: ob->pose may be NULL. */
+ Object *object = (Object *)to_node->id;
+ /* NOTE: object->pose may be NULL. */
bPoseChannel *pchan = BKE_pose_channel_find_name(
- ob->pose, bone_name);
+ object->pose, bone_name);
if (pchan != NULL) {
- OperationKey bone_key(&ob->id,
+ OperationKey bone_key(&object->id,
DEG_NODE_TYPE_BONE,
pchan->name,
DEG_OPCODE_BONE_LOCAL);
@@ -1105,9 +1116,9 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
}
/* Special handling for directly-named bones. */
if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) {
- Object *ob = (Object *)dtar->id;
+ Object *object = (Object *)dtar->id;
bPoseChannel *target_pchan =
- BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
+ BKE_pose_channel_find_name(object->pose, dtar->pchan_name);
if (target_pchan != NULL) {
/* Get node associated with bone. */
// XXX: watch the space!
@@ -1148,11 +1159,11 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
/* Workaround for ensuring that local bone transforms don't end
* up having to wait for pose eval to finish (to prevent cycles).
*/
- Object *ob = (Object *)dtar->id;
+ Object *object = (Object *)dtar->id;
char *bone_name = BLI_str_quoted_substrN(dtar->rna_path,
"pose.bones[");
bPoseChannel *target_pchan =
- BKE_pose_channel_find_name(ob->pose, bone_name);
+ BKE_pose_channel_find_name(object->pose, bone_name);
if (bone_name != NULL) {
MEM_freeN(bone_name);
bone_name = NULL;
@@ -1242,8 +1253,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
/* objects - simulation participants */
if (rbw->group) {
LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) {
- Object *ob = go->ob;
- if (ob == NULL || ob->type != OB_MESH) {
+ Object *object = go->ob;
+ if (object == NULL || object->type != OB_MESH) {
continue;
}
@@ -1255,10 +1266,10 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
* XXX: there's probably a difference between passive and active
* - passive don't change, so may need to know full transform...
*/
- OperationKey rbo_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY);
+ OperationKey rbo_key(&object->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY);
- eDepsOperation_Code trans_opcode = ob->parent ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL;
- OperationKey trans_op(&ob->id, DEG_NODE_TYPE_TRANSFORM, trans_opcode);
+ eDepsOperation_Code trans_opcode = object->parent ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL;
+ OperationKey trans_op(&object->id, DEG_NODE_TYPE_TRANSFORM, trans_opcode);
add_relation(sim_key, rbo_key, "Rigidbody Sim Eval -> RBO Sync");
@@ -1270,8 +1281,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
* - Later, it might be good to include a constraint in the stack allowing us
* to control whether rigidbody eval gets interleaved into the constraint stack
*/
- if (ob->constraints.first) {
- OperationKey constraint_key(&ob->id,
+ if (object->constraints.first) {
+ OperationKey constraint_key(&object->id,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_CONSTRAINTS);
add_relation(rbo_key, constraint_key, "RBO Sync -> Ob Constraints");
@@ -1282,7 +1293,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
* NOTE: Currently we consider final here an ubereval node.
* If it is gone we'll need to reconsider relation here.
*/
- OperationKey uber_key(&ob->id,
+ OperationKey uber_key(&object->id,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL);
add_relation(rbo_key, uber_key, "RBO Sync -> Uber (Temp)");
@@ -1296,17 +1307,17 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
/* constraints */
if (rbw->constraints) {
LINKLIST_FOREACH (GroupObject *, go, &rbw->constraints->gobject) {
- Object *ob = go->ob;
- if (ob == NULL || !ob->rigidbody_constraint) {
+ Object *object = go->ob;
+ if (object == NULL || !object->rigidbody_constraint) {
continue;
}
- RigidBodyCon *rbc = ob->rigidbody_constraint;
+ RigidBodyCon *rbc = object->rigidbody_constraint;
/* final result of the constraint object's transform controls how the
* constraint affects the physics sim for these objects
*/
- ComponentKey trans_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey trans_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
OperationKey ob1_key(&rbc->ob1->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY);
OperationKey ob2_key(&rbc->ob2->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY);
@@ -1320,32 +1331,31 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
}
}
-void DepsgraphRelationBuilder::build_particles(Object *ob)
+void DepsgraphRelationBuilder::build_particles(Object *object)
{
TimeSourceKey time_src_key;
- OperationKey obdata_ubereval_key(&ob->id,
+ OperationKey obdata_ubereval_key(&object->id,
DEG_NODE_TYPE_GEOMETRY,
DEG_OPCODE_GEOMETRY_UBEREVAL);
- OperationKey eval_init_key(&ob->id,
+ OperationKey eval_init_key(&object->id,
DEG_NODE_TYPE_EVAL_PARTICLES,
DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT);
- /* TODO(sergey): Are all particle systems depends on time?
- * Hair without dynamics i.e.
- */
- add_relation(time_src_key, eval_init_key, "TimeSrc -> PSys");
+ if (object_particles_depends_on_time(object)) {
+ add_relation(time_src_key, eval_init_key, "TimeSrc -> PSys");
+ }
/* particle systems */
- LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
+ LINKLIST_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
ParticleSettings *part = psys->part;
/* particle settings */
build_animdata(&part->id);
/* this particle system */
- OperationKey psys_key(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PARTICLE_SYSTEM_EVAL, psys->name);
+ OperationKey psys_key(&object->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PARTICLE_SYSTEM_EVAL, psys->name);
/* XXX: if particle system is later re-enabled, we must do full rebuild? */
- if (!psys_check_enabled(ob, psys, G.is_rendering))
+ if (!psys_check_enabled(object, psys, G.is_rendering))
continue;
add_relation(eval_init_key, psys_key, "Init -> PSys");
@@ -1358,14 +1368,14 @@ void DepsgraphRelationBuilder::build_particles(Object *ob)
/* collisions */
if (part->type != PART_HAIR) {
- add_collision_relations(psys_key, scene_, ob, part->collision_group, ob->lay, true, "Particle Collision");
+ add_collision_relations(psys_key, scene_, object, part->collision_group, object->lay, true, "Particle Collision");
}
else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd && psys->clmd->coll_parms) {
- add_collision_relations(psys_key, scene_, ob, psys->clmd->coll_parms->group, ob->lay | scene_->lay, true, "Hair Collision");
+ add_collision_relations(psys_key, scene_, object, psys->clmd->coll_parms->group, object->lay | scene_->lay, true, "Hair Collision");
}
/* effectors */
- add_forcefield_relations(psys_key, scene_, ob, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
+ add_forcefield_relations(psys_key, scene_, object, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
/* boids */
if (part->boids) {
@@ -1397,7 +1407,7 @@ void DepsgraphRelationBuilder::build_particles(Object *ob)
* TODO(sergey): This relation should be altered once real granular update
* is implemented.
*/
- ComponentKey transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(transform_key, obdata_ubereval_key, "Partcile Eval");
/* pointcache */
@@ -1461,27 +1471,27 @@ void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
* re-evaluation of the individual instances of this geometry.
*/
// TODO: Materials and lighting should probably get their own component, instead of being lumped under geometry?
-void DepsgraphRelationBuilder::build_obdata_geom(Object *ob)
+void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
{
- ID *obdata = (ID *)ob->data;
+ ID *obdata = (ID *)object->data;
/* Init operation of object-level geometry evaluation. */
- OperationKey geom_init_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init");
+ OperationKey geom_init_key(&object->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init");
/* get nodes for result of obdata's evaluation, and geometry evaluation on object */
ComponentKey obdata_geom_key(obdata, DEG_NODE_TYPE_GEOMETRY);
- ComponentKey geom_key(&ob->id, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey geom_key(&object->id, DEG_NODE_TYPE_GEOMETRY);
/* link components to each other */
add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
/* Modifiers */
- if (ob->modifiers.first != NULL) {
- OperationKey obdata_ubereval_key(&ob->id,
+ if (object->modifiers.first != NULL) {
+ OperationKey obdata_ubereval_key(&object->id,
DEG_NODE_TYPE_GEOMETRY,
DEG_OPCODE_GEOMETRY_UBEREVAL);
- LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) {
+ LINKLIST_FOREACH (ModifierData *, md, &object->modifiers) {
const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
if (mti->updateDepsgraph) {
@@ -1490,11 +1500,11 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob)
md,
bmain_,
scene_,
- ob,
+ object,
reinterpret_cast< ::DepsNodeHandle* >(&handle));
}
- if (BKE_object_modifier_use_time(ob, md)) {
+ if (BKE_object_modifier_use_time(object, md)) {
TimeSourceKey time_src_key;
add_relation(time_src_key, obdata_ubereval_key, "Time Source");
@@ -1504,22 +1514,22 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob)
* for either the modifier needing time, or that it is animated.
*/
/* XXX: Remove this hack when these links are added as part of build_animdata() instead */
- if (modifier_dependsOnTime(md) == false && needs_animdata_node(&ob->id)) {
- ComponentKey animation_key(&ob->id, DEG_NODE_TYPE_ANIMATION);
+ if (modifier_dependsOnTime(md) == false && needs_animdata_node(&object->id)) {
+ ComponentKey animation_key(&object->id, DEG_NODE_TYPE_ANIMATION);
add_relation(animation_key, obdata_ubereval_key, "Modifier Animation");
}
}
if (md->type == eModifierType_Cloth) {
- build_cloth(ob, md);
+ build_cloth(object, md);
}
}
}
/* materials */
- if (ob->totcol) {
- for (int a = 1; a <= ob->totcol; a++) {
- Material *ma = give_current_material(ob, a);
+ if (object->totcol) {
+ for (int a = 1; a <= object->totcol; a++) {
+ Material *ma = give_current_material(object, a);
if (ma != NULL) {
build_material(ma);
}
@@ -1527,7 +1537,7 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob)
}
/* geometry collision */
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
+ if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
// add geometry collider relations
}
@@ -1535,9 +1545,9 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob)
*
* TODO(sergey): Get rid of this node.
*/
- if (ob->type != OB_ARMATURE) {
+ if (object->type != OB_ARMATURE) {
/* Armatures does no longer require uber node. */
- OperationKey obdata_ubereval_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL);
+ OperationKey obdata_ubereval_key(&object->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL);
add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval");
}
@@ -1552,33 +1562,41 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob)
add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done");
/* type-specific node/links */
- switch (ob->type) {
+ switch (object->type) {
case OB_MESH:
/* NOTE: This is compatibility code to support particle systems
*
* for viewport being properly rendered in final render mode.
* This relation is similar to what dag_object_time_update_flags()
- * was doing for mesh objects with particle system/
+ * was doing for mesh objects with particle system.
*
* Ideally we need to get rid of this relation.
*/
- if (ob->particlesystem.first != NULL) {
+ if (object_particles_depends_on_time(object)) {
TimeSourceKey time_key;
- OperationKey obdata_ubereval_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL);
+ OperationKey obdata_ubereval_key(&object->id,
+ DEG_NODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
add_relation(time_key, obdata_ubereval_key, "Legacy particle time");
}
break;
case OB_MBALL:
{
- Object *mom = BKE_mball_basis_find(scene_, ob);
+ Object *mom = BKE_mball_basis_find(scene_, object);
+ ComponentKey mom_geom_key(&mom->id, DEG_NODE_TYPE_GEOMETRY);
/* motherball - mom depends on children! */
- if (mom != ob) {
- /* non-motherball -> cannot be directly evaluated! */
- ComponentKey mom_key(&mom->id, DEG_NODE_TYPE_GEOMETRY);
- ComponentKey transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
- add_relation(geom_key, mom_key, "Metaball Motherball");
- add_relation(transform_key, mom_key, "Metaball Motherball");
+ if (mom == object) {
+ ComponentKey mom_transform_key(&mom->id,
+ DEG_NODE_TYPE_TRANSFORM);
+ add_relation(mom_transform_key,
+ mom_geom_key,
+ "Metaball Motherball Transform -> Geometry");
+ }
+ else {
+ ComponentKey transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(geom_key, mom_geom_key, "Metaball Motherball");
+ add_relation(transform_key, mom_geom_key, "Metaball Motherball");
}
break;
}
@@ -1600,7 +1618,7 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob)
build_object(cu->taperobj);
add_relation(taperob_key, geom_key, "Curve Taper");
}
- if (ob->type == OB_FONT) {
+ if (object->type == OB_FONT) {
if (cu->textoncurve) {
ComponentKey textoncurve_key(&cu->textoncurve->id, DEG_NODE_TYPE_GEOMETRY);
build_object(cu->textoncurve);
@@ -1622,7 +1640,7 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob)
}
/* ShapeKeys */
- Key *key = BKE_key_from_object(ob);
+ Key *key = BKE_key_from_object(object);
if (key) {
build_shapekeys(obdata, key);
}
@@ -1640,9 +1658,9 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob)
/* Cameras */
// TODO: Link scene-camera links in somehow...
-void DepsgraphRelationBuilder::build_camera(Object *ob)
+void DepsgraphRelationBuilder::build_camera(Object *object)
{
- Camera *cam = (Camera *)ob->data;
+ Camera *cam = (Camera *)object->data;
ID *camera_id = &cam->id;
if (camera_id->tag & LIB_TAG_DOIT) {
return;
@@ -1658,16 +1676,16 @@ void DepsgraphRelationBuilder::build_camera(Object *ob)
/* DOF */
if (cam->dof_ob) {
- ComponentKey ob_param_key(&ob->id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey ob_param_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(dof_ob_key, ob_param_key, "Camera DOF");
}
}
/* Lamps */
-void DepsgraphRelationBuilder::build_lamp(Object *ob)
+void DepsgraphRelationBuilder::build_lamp(Object *object)
{
- Lamp *la = (Lamp *)ob->data;
+ Lamp *la = (Lamp *)object->data;
ID *lamp_id = &la->id;
if (lamp_id->tag & LIB_TAG_DOIT) {
return;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 86227f4aaf8..68762043e5e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -186,8 +186,9 @@ struct DepsgraphRelationBuilder
void build_scene(Scene *scene);
void build_group(Object *object, Group *group);
- void build_object(Object *ob);
- void build_object_parent(Object *ob);
+ void build_object(Object *object);
+ void build_object_data(Object *object);
+ void build_object_parent(Object *object);
void build_constraints(ID *id,
eDepsNode_Type component_type,
const char *component_subdata,
@@ -197,22 +198,22 @@ struct DepsgraphRelationBuilder
void build_driver(ID *id, FCurve *fcurve);
void build_world(World *world);
void build_rigidbody(Scene *scene);
- void build_particles(Object *ob);
+ void build_particles(Object *object);
void build_cloth(Object *object, ModifierData *md);
- void build_ik_pose(Object *ob,
+ void build_ik_pose(Object *object,
bPoseChannel *pchan,
bConstraint *con,
RootPChanMap *root_map);
- void build_splineik_pose(Object *ob,
+ void build_splineik_pose(Object *object,
bPoseChannel *pchan,
bConstraint *con,
RootPChanMap *root_map);
- void build_rig(Object *ob);
- void build_proxy_rig(Object *ob);
+ void build_rig(Object *object);
+ void build_proxy_rig(Object *object);
void build_shapekeys(ID *obdata, Key *key);
- void build_obdata_geom(Object *ob);
- void build_camera(Object *ob);
- void build_lamp(Object *ob);
+ void build_obdata_geom(Object *object);
+ void build_camera(Object *object);
+ void build_lamp(Object *object);
void build_nodetree(bNodeTree *ntree);
void build_material(Material *ma);
void build_texture(Tex *tex);
@@ -225,14 +226,14 @@ struct DepsgraphRelationBuilder
void add_collision_relations(const OperationKey &key,
Scene *scene,
- Object *ob,
+ Object *object,
Group *group,
int layer,
bool dupli,
const char *name);
void add_forcefield_relations(const OperationKey &key,
Scene *scene,
- Object *ob,
+ Object *object,
ParticleSystem *psys,
EffectorWeights *eff,
bool add_absorption,
@@ -244,11 +245,13 @@ struct DepsgraphRelationBuilder
Depsgraph *getGraph();
protected:
- TimeSourceDepsNode *find_node(const TimeSourceKey &key) const;
- ComponentDepsNode *find_node(const ComponentKey &key) const;
+ TimeSourceDepsNode *get_node(const TimeSourceKey &key) const;
+ ComponentDepsNode *get_node(const ComponentKey &key) const;
+ OperationDepsNode *get_node(const OperationKey &key) const;
+ DepsNode *get_node(const RNAPathKey &key) const;
+
OperationDepsNode *find_node(const OperationKey &key) const;
- DepsNode *find_node(const RNAPathKey &key) const;
- OperationDepsNode *has_node(const OperationKey &key) const;
+ bool has_node(const OperationKey &key) const;
void add_time_relation(TimeSourceDepsNode *timesrc,
DepsNode *node_to,
@@ -292,7 +295,7 @@ struct DepsNodeHandle
template <typename KeyType>
OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType& key)
{
- DepsNode *node = find_node(key);
+ DepsNode *node = get_node(key);
return node != NULL ? node->get_exit_operation() : NULL;
}
@@ -301,8 +304,8 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
const KeyTo &key_to,
const char *description)
{
- DepsNode *node_from = find_node(key_from);
- DepsNode *node_to = find_node(key_to);
+ DepsNode *node_from = get_node(key_from);
+ DepsNode *node_to = get_node(key_to);
OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
if (op_from && op_to) {
@@ -311,7 +314,6 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
else {
if (!op_from) {
/* XXX TODO handle as error or report if needed */
- node_from = find_node(key_from);
fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n",
description, key_from.identifier().c_str());
}
@@ -336,14 +338,12 @@ void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from,
const KeyTo &key_to,
const char *description)
{
- TimeSourceDepsNode *time_from = find_node(key_from);
- DepsNode *node_to = find_node(key_to);
+ TimeSourceDepsNode *time_from = get_node(key_from);
+ DepsNode *node_to = get_node(key_to);
OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
- if (time_from && op_to) {
+ if (time_from != NULL && op_to != NULL) {
add_time_relation(time_from, op_to, description);
}
- else {
- }
}
template <typename KeyType>
@@ -352,10 +352,10 @@ void DepsgraphRelationBuilder::add_node_handle_relation(
const DepsNodeHandle *handle,
const char *description)
{
- DepsNode *node_from = find_node(key_from);
+ DepsNode *node_from = get_node(key_from);
OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
OperationDepsNode *op_to = handle->node->get_entry_operation();
- if (op_from && op_to) {
+ if (op_from != NULL && op_to != NULL) {
add_operation_relation(op_from, op_to, description);
}
else {
@@ -375,7 +375,7 @@ DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(
const KeyType &key,
const char *default_name)
{
- return DepsNodeHandle(this, find_node(key), default_name);
+ return DepsNodeHandle(this, get_node(key), default_name);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
index 6ff21393ed6..cdc98ad6b6a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
@@ -71,7 +71,7 @@ extern "C" {
namespace DEG {
/* IK Solver Eval Steps */
-void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
+void DepsgraphRelationBuilder::build_ik_pose(Object *object,
bPoseChannel *pchan,
bConstraint *con,
RootPChanMap *root_map)
@@ -86,10 +86,10 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
if (rootchan == NULL) {
return;
}
- OperationKey pchan_local_key(&ob->id, DEG_NODE_TYPE_BONE,
+ OperationKey pchan_local_key(&object->id, DEG_NODE_TYPE_BONE,
pchan->name, DEG_OPCODE_BONE_LOCAL);
- OperationKey init_ik_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT_IK);
- OperationKey solver_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE,
+ OperationKey init_ik_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT_IK);
+ OperationKey solver_key(&object->id, DEG_NODE_TYPE_EVAL_POSE,
rootchan->name,
DEG_OPCODE_POSE_IK_SOLVER);
@@ -107,10 +107,10 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
* testing IK solver.
*/
// FIXME: geometry targets...
- ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
+ ComponentKey pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE);
if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
/* TODO(sergey): This is only for until granular update stores intermediate result. */
- if (data->tar != ob) {
+ if (data->tar != object) {
/* different armature - can just read the results */
ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_BONE, data->subtarget);
add_relation(target_key, pose_key, con->name);
@@ -140,7 +140,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
add_relation(target_key, pose_key, con->name);
}
- if ((data->tar == ob) && (data->subtarget[0])) {
+ if ((data->tar == object) && (data->subtarget[0])) {
/* Prevent target's constraints from linking to anything from same
* chain that it controls.
*/
@@ -181,7 +181,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
bPoseChannel *parchan = pchan;
/* exclude tip from chain? */
if (!(data->flag & CONSTRAINT_IK_TIP)) {
- OperationKey tip_transforms_key(&ob->id, DEG_NODE_TYPE_BONE,
+ OperationKey tip_transforms_key(&object->id, DEG_NODE_TYPE_BONE,
parchan->name, DEG_OPCODE_BONE_LOCAL);
add_relation(solver_key, tip_transforms_key, "IK Solver Result");
parchan = pchan->parent;
@@ -189,7 +189,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
root_map->add_bone(parchan->name, rootchan->name);
- OperationKey parchan_transforms_key(&ob->id, DEG_NODE_TYPE_BONE,
+ OperationKey parchan_transforms_key(&object->id, DEG_NODE_TYPE_BONE,
parchan->name, DEG_OPCODE_BONE_READY);
add_relation(parchan_transforms_key, solver_key, "IK Solver Owner");
@@ -205,14 +205,14 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
* grab the result with IK solver results...
*/
if (parchan != pchan) {
- OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey parent_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
add_relation(parent_key, solver_key, "IK Chain Parent");
- OperationKey done_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ OperationKey done_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
add_relation(solver_key, done_key, "IK Chain Result");
}
else {
- OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ OperationKey final_transforms_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
add_relation(solver_key, final_transforms_key, "IK Solver Result");
}
parchan->flag |= POSE_DONE;
@@ -228,20 +228,20 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
parchan = parchan->parent;
}
- OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ OperationKey flush_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
add_relation(solver_key, flush_key, "PoseEval Result-Bone Link");
}
/* Spline IK Eval Steps */
-void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
+void DepsgraphRelationBuilder::build_splineik_pose(Object *object,
bPoseChannel *pchan,
bConstraint *con,
RootPChanMap *root_map)
{
bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
- OperationKey transforms_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey solver_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
+ OperationKey transforms_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey solver_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
/* attach owner to IK Solver too
* - assume that owner is always part of chain
@@ -257,12 +257,12 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
*/
// TODO: the bigggest point here is that we need the curve PATH and not just the general geometry...
ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_GEOMETRY);
- ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
+ ComponentKey pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE);
add_relation(target_key, pose_key, "[Curve.Path -> Spline IK] DepsRel");
}
pchan->flag |= POSE_DONE;
- OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ OperationKey final_transforms_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
add_relation(solver_key, final_transforms_key, "Spline IK Result");
root_map->add_bone(pchan->name, rootchan->name);
@@ -279,15 +279,15 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
* grab the result with IK solver results...
*/
if (parchan != pchan) {
- OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey parent_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
add_relation(parent_key, solver_key, "Spline IK Solver Update");
- OperationKey done_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ OperationKey done_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
add_relation(solver_key, done_key, "IK Chain Result");
}
parchan->flag |= POSE_DONE;
- OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ OperationKey final_transforms_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
add_relation(solver_key, final_transforms_key, "Spline IK Solver Result");
root_map->add_bone(parchan->name, rootchan->name);
@@ -297,22 +297,22 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
if ((segcount == data->chainlen) || (segcount > 255)) break; /* 255 is weak */
}
- OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ OperationKey flush_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
add_relation(solver_key, flush_key, "PoseEval Result-Bone Link");
}
/* Pose/Armature Bones Graph */
-void DepsgraphRelationBuilder::build_rig(Object *ob)
+void DepsgraphRelationBuilder::build_rig(Object *object)
{
/* Armature-Data */
- bArmature *arm = (bArmature *)ob->data;
+ bArmature *arm = (bArmature *)object->data;
// TODO: selection status?
/* attach links between pose operations */
- OperationKey init_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
- OperationKey init_ik_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT_IK);
- OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ OperationKey init_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
+ OperationKey init_ik_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT_IK);
+ OperationKey flush_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
add_relation(init_key, init_ik_key, "Pose Init -> Pose Init IK");
add_relation(init_ik_key, flush_key, "Pose Init IK -> Pose Cleanup");
@@ -324,8 +324,8 @@ void DepsgraphRelationBuilder::build_rig(Object *ob)
"Armature Eval");
add_relation(armature_key, init_key, "Data dependency");
- if (needs_animdata_node(&ob->id)) {
- ComponentKey animation_key(&ob->id, DEG_NODE_TYPE_ANIMATION);
+ if (needs_animdata_node(&object->id)) {
+ ComponentKey animation_key(&object->id, DEG_NODE_TYPE_ANIMATION);
add_relation(animation_key, init_key, "Rig Animation");
}
@@ -346,16 +346,16 @@ void DepsgraphRelationBuilder::build_rig(Object *ob)
*/
RootPChanMap root_map;
bool pose_depends_on_local_transform = false;
- LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
LINKLIST_FOREACH (bConstraint *, con, &pchan->constraints) {
switch (con->type) {
case CONSTRAINT_TYPE_KINEMATIC:
- build_ik_pose(ob, pchan, con, &root_map);
+ build_ik_pose(object, pchan, con, &root_map);
pose_depends_on_local_transform = true;
break;
case CONSTRAINT_TYPE_SPLINEIK:
- build_splineik_pose(ob, pchan, con, &root_map);
+ build_splineik_pose(object, pchan, con, &root_map);
pose_depends_on_local_transform = true;
break;
@@ -381,17 +381,17 @@ void DepsgraphRelationBuilder::build_rig(Object *ob)
/* TODO(sergey): Once partial updates are possible use relation between
* object transform and solver itself in it's build function.
*/
- ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
- ComponentKey local_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE);
+ ComponentKey local_transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(local_transform_key, pose_key, "Local Transforms");
}
/* links between operations for each bone */
- LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- OperationKey bone_local_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- OperationKey bone_pose_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
- OperationKey bone_ready_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey bone_done_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ OperationKey bone_local_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ OperationKey bone_pose_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
+ OperationKey bone_ready_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey bone_done_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
pchan->flag &= ~POSE_DONE;
@@ -413,17 +413,17 @@ void DepsgraphRelationBuilder::build_rig(Object *ob)
parent_key_opcode = DEG_OPCODE_BONE_DONE;
}
- OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
+ OperationKey parent_key(&object->id, DEG_NODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
add_relation(parent_key, bone_pose_key, "[Parent Bone -> Child Bone]");
}
/* constraints */
if (pchan->constraints.first != NULL) {
/* constraints stack and constraint dependencies */
- build_constraints(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
+ build_constraints(&object->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
/* pose -> constraints */
- OperationKey constraints_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
+ OperationKey constraints_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
add_relation(bone_pose_key, constraints_key, "Constraints Stack");
/* constraints -> ready */
@@ -447,14 +447,14 @@ void DepsgraphRelationBuilder::build_rig(Object *ob)
}
}
-void DepsgraphRelationBuilder::build_proxy_rig(Object *ob)
+void DepsgraphRelationBuilder::build_proxy_rig(Object *object)
{
- OperationKey pose_init_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
- OperationKey pose_done_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
- LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- OperationKey bone_local_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- OperationKey bone_ready_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey bone_done_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ OperationKey pose_init_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
+ OperationKey pose_done_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ OperationKey bone_local_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ OperationKey bone_ready_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey bone_done_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local");
add_relation(bone_local_key, bone_ready_key, "Local -> Ready");
add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
index bedcb5aa223..bface46c201 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
@@ -78,8 +78,8 @@ void DepsgraphRelationBuilder::build_scene(Scene *scene)
/* scene objects */
LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *ob = base->object;
- build_object(ob);
+ Object *object = base->object;
+ build_object(object);
}
/* rigidbody */
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index aa21f0995be..a17b083feb9 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -144,19 +144,19 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
return true;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
- Object *ob = (Object *)ptr->id.data;
+ Object *object = (Object *)ptr->id.data;
bConstraint *con = (bConstraint *)ptr->data;
/* object or bone? */
- if (BLI_findindex(&ob->constraints, con) != -1) {
+ if (BLI_findindex(&object->constraints, con) != -1) {
/* object transform */
// XXX: for now, we can't address the specific constraint or the constraint stack...
*type = DEG_NODE_TYPE_TRANSFORM;
return true;
}
- else if (ob->pose) {
+ else if (object->pose) {
bPoseChannel *pchan;
- for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ for (pchan = (bPoseChannel *)object->pose->chanbase.first; pchan; pchan = pchan->next) {
if (BLI_findindex(&pchan->constraints, con) != -1) {
/* bone transforms */
*type = DEG_NODE_TYPE_BONE;
@@ -180,7 +180,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
return true;
}
else if (ptr->type == &RNA_Object) {
- //Object *ob = (Object *)ptr->data;
+ //Object *object = (Object *)ptr->data;
/* Transforms props? */
if (prop) {
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index fb762505ed2..4b3d4190dcd 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -124,12 +124,12 @@ void DEG_add_scene_relation(DepsNodeHandle *handle,
}
void DEG_add_object_relation(DepsNodeHandle *handle,
- Object *ob,
+ Object *object,
eDepsObjectComponentType component,
const char *description)
{
DEG::eDepsNode_Type type = deg_build_object_component_type(component);
- DEG::ComponentKey comp_key(&ob->id, type);
+ DEG::ComponentKey comp_key(&object->id, type);
DEG::DepsNodeHandle *deg_handle = get_handle(handle);
deg_handle->builder->add_node_handle_relation(comp_key,
deg_handle,
@@ -150,13 +150,13 @@ void DEG_add_object_cache_relation(DepsNodeHandle *handle,
}
void DEG_add_bone_relation(DepsNodeHandle *handle,
- Object *ob,
+ Object *object,
const char *bone_name,
eDepsObjectComponentType component,
const char *description)
{
DEG::eDepsNode_Type type = deg_build_object_component_type(component);
- DEG::ComponentKey comp_key(&ob->id, type, bone_name);
+ DEG::ComponentKey comp_key(&object->id, type, bone_name);
DEG::DepsNodeHandle *deg_handle = get_handle(handle);
/* XXX: "Geometry Eval" might not always be true, but this only gets called
* from modifier building now.
@@ -314,7 +314,7 @@ void DEG_scene_graph_free(Scene *scene)
void DEG_add_collision_relations(DepsNodeHandle *handle,
Scene *scene,
- Object *ob,
+ Object *object,
Group *group,
int layer,
unsigned int modifier_type,
@@ -323,7 +323,7 @@ void DEG_add_collision_relations(DepsNodeHandle *handle,
const char *name)
{
unsigned int numcollobj;
- Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli);
+ Object **collobjs = get_collisionobjects_ext(scene, object, group, layer, &numcollobj, modifier_type, dupli);
for (unsigned int i = 0; i < numcollobj; i++) {
Object *ob1 = collobjs[i];
@@ -340,17 +340,17 @@ void DEG_add_collision_relations(DepsNodeHandle *handle,
void DEG_add_forcefield_relations(DepsNodeHandle *handle,
Scene *scene,
- Object *ob,
+ Object *object,
EffectorWeights *effector_weights,
bool add_absorption,
int skip_forcefield,
const char *name)
{
- ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false);
+ ListBase *effectors = pdInitEffectors(scene, object, NULL, effector_weights, false);
if (effectors) {
for (EffectorCache *eff = (EffectorCache*)effectors->first; eff; eff = eff->next) {
- if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) {
+ if (eff->ob != object && eff->pd->forcefield != skip_forcefield) {
DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_TRANSFORM, name);
if (eff->psys) {
@@ -376,7 +376,7 @@ void DEG_add_forcefield_relations(DepsNodeHandle *handle,
if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
DEG_add_collision_relations(handle,
scene,
- ob,
+ object,
NULL,
eff->ob->lay,
eModifierType_Collision,
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index 0adbadeebba..83fc756654f 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -178,6 +178,7 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
case DEG_NODE_TYPE_PARAMETERS:
case DEG_NODE_TYPE_SEQUENCER:
/* Ignore, does not translate to object component. */
+ BLI_assert(!"This should never happen!");
break;
case DEG_NODE_TYPE_ANIMATION:
object->recalc |= OB_RECALC_TIME;
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
index e87c87813e3..010f12409b4 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
@@ -87,8 +87,8 @@ bool ComponentDepsNode::OperationIDKey::operator==(
const OperationIDKey &other) const
{
return (opcode == other.opcode) &&
- (STREQ(name, other.name)) &&
- (name_tag == other.name_tag);
+ (STREQ(name, other.name)) &&
+ (name_tag == other.name_tag);
}
static unsigned int comp_node_hash_key(const void *key_v)
@@ -165,36 +165,62 @@ string ComponentDepsNode::identifier() const
OperationDepsNode *ComponentDepsNode::find_operation(OperationIDKey key) const
{
- OperationDepsNode *node = reinterpret_cast<OperationDepsNode *>(BLI_ghash_lookup(operations_map, &key));
- if (node != NULL) {
- return node;
+ OperationDepsNode *node;
+ if (operations_map != NULL) {
+ node = (OperationDepsNode *)BLI_ghash_lookup(operations_map, &key);
}
else {
- fprintf(stderr, "%s: find_operation(%s) failed\n",
- this->identifier().c_str(), key.identifier().c_str());
- BLI_assert(!"Request for non-existing operation, should not happen");
- return NULL;
+ BLI_assert(key.name_tag == -1);
+ foreach (OperationDepsNode *op_node, operations) {
+ if (op_node->opcode == key.opcode &&
+ STREQ(op_node->name, key.name))
+ {
+ node = op_node;
+ break;
+ }
+ }
}
+ return node;
}
OperationDepsNode *ComponentDepsNode::find_operation(eDepsOperation_Code opcode,
- const char *name,
- int name_tag) const
+ const char *name,
+ int name_tag) const
{
OperationIDKey key(opcode, name, name_tag);
return find_operation(key);
}
-OperationDepsNode *ComponentDepsNode::has_operation(OperationIDKey key) const
+OperationDepsNode *ComponentDepsNode::get_operation(OperationIDKey key) const
{
- return reinterpret_cast<OperationDepsNode *>(BLI_ghash_lookup(operations_map, &key));
+ OperationDepsNode *node = find_operation(key);
+ if (node == NULL) {
+ fprintf(stderr, "%s: find_operation(%s) failed\n",
+ this->identifier().c_str(), key.identifier().c_str());
+ BLI_assert(!"Request for non-existing operation, should not happen");
+ return NULL;
+ }
+ return node;
}
-OperationDepsNode *ComponentDepsNode::has_operation(eDepsOperation_Code opcode,
+OperationDepsNode *ComponentDepsNode::get_operation(eDepsOperation_Code opcode,
const char *name,
int name_tag) const
{
OperationIDKey key(opcode, name, name_tag);
+ return get_operation(key);
+}
+
+bool ComponentDepsNode::has_operation(OperationIDKey key) const
+{
+ return find_operation(key) != NULL;
+}
+
+bool ComponentDepsNode::has_operation(eDepsOperation_Code opcode,
+ const char *name,
+ int name_tag) const
+{
+ OperationIDKey key(opcode, name, name_tag);
return has_operation(key);
}
@@ -203,7 +229,7 @@ OperationDepsNode *ComponentDepsNode::add_operation(const DepsEvalOperationCb& o
const char *name,
int name_tag)
{
- OperationDepsNode *op_node = has_operation(opcode, name, name_tag);
+ OperationDepsNode *op_node = find_operation(opcode, name, name_tag);
if (!op_node) {
DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_OPERATION);
op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name);
@@ -333,40 +359,25 @@ void ComponentDepsNode::finalize_build()
operations_map = NULL;
}
-/* Parameter Component Defines ============================ */
-
-DEG_DEPSNODE_DEFINE(ParametersComponentDepsNode, DEG_NODE_TYPE_PARAMETERS, "Parameters Component");
-static DepsNodeFactoryImpl<ParametersComponentDepsNode> DNTI_PARAMETERS;
-
-/* Animation Component Defines ============================ */
-
-DEG_DEPSNODE_DEFINE(AnimationComponentDepsNode, DEG_NODE_TYPE_ANIMATION, "Animation Component");
-static DepsNodeFactoryImpl<AnimationComponentDepsNode> DNTI_ANIMATION;
-
-/* Transform Component Defines ============================ */
-
-DEG_DEPSNODE_DEFINE(TransformComponentDepsNode, DEG_NODE_TYPE_TRANSFORM, "Transform Component");
-static DepsNodeFactoryImpl<TransformComponentDepsNode> DNTI_TRANSFORM;
-
-/* Proxy Component Defines ================================ */
-
-DEG_DEPSNODE_DEFINE(ProxyComponentDepsNode, DEG_NODE_TYPE_PROXY, "Proxy Component");
-static DepsNodeFactoryImpl<ProxyComponentDepsNode> DNTI_PROXY;
-
-/* Geometry Component Defines ============================= */
+/* Register all components. =============================== */
-DEG_DEPSNODE_DEFINE(GeometryComponentDepsNode, DEG_NODE_TYPE_GEOMETRY, "Geometry Component");
-static DepsNodeFactoryImpl<GeometryComponentDepsNode> DNTI_GEOMETRY;
+#define DEG_COMPONENT_DEFINE(name, NAME) \
+ DEG_DEPSNODE_DEFINE(name ## ComponentDepsNode, \
+ DEG_NODE_TYPE_ ## NAME, \
+ #name " Component"); \
+static DepsNodeFactoryImpl<name ## ComponentDepsNode> DNTI_ ## NAME
-/* Sequencer Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(SequencerComponentDepsNode, DEG_NODE_TYPE_SEQUENCER, "Sequencer Component");
-static DepsNodeFactoryImpl<SequencerComponentDepsNode> DNTI_SEQUENCER;
-
-/* Pose Component ========================================= */
-
-DEG_DEPSNODE_DEFINE(PoseComponentDepsNode, DEG_NODE_TYPE_EVAL_POSE, "Pose Eval Component");
-static DepsNodeFactoryImpl<PoseComponentDepsNode> DNTI_EVAL_POSE;
+DEG_COMPONENT_DEFINE(Animation, ANIMATION);
+DEG_COMPONENT_DEFINE(Cache, CACHE);
+DEG_COMPONENT_DEFINE(Geometry, GEOMETRY);
+DEG_COMPONENT_DEFINE(Parameters, PARAMETERS);
+DEG_COMPONENT_DEFINE(Particles, EVAL_PARTICLES);
+DEG_COMPONENT_DEFINE(Proxy, PROXY);
+DEG_COMPONENT_DEFINE(Pose, EVAL_POSE);
+DEG_COMPONENT_DEFINE(Sequencer, SEQUENCER);
+DEG_COMPONENT_DEFINE(Shading, SHADING);
+DEG_COMPONENT_DEFINE(Transform, TRANSFORM);
/* Bone Component ========================================= */
@@ -383,28 +394,11 @@ void BoneComponentDepsNode::init(const ID *id, const char *subdata)
//this->name = subdata;
/* bone-specific node data */
- Object *ob = (Object *)id;
- this->pchan = BKE_pose_channel_find_name(ob->pose, subdata);
+ Object *object = (Object *)id;
+ this->pchan = BKE_pose_channel_find_name(object->pose, subdata);
}
-DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEG_NODE_TYPE_BONE, "Bone Component");
-static DepsNodeFactoryImpl<BoneComponentDepsNode> DNTI_BONE;
-
-/* Particles Component Defines ============================ */
-
-DEG_DEPSNODE_DEFINE(ParticlesComponentDepsNode, DEG_NODE_TYPE_EVAL_PARTICLES, "Particles Component");
-static DepsNodeFactoryImpl<ParticlesComponentDepsNode> DNTI_EVAL_PARTICLES;
-
-/* Shading Component Defines ============================ */
-
-DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEG_NODE_TYPE_SHADING, "Shading Component");
-static DepsNodeFactoryImpl<ShadingComponentDepsNode> DNTI_SHADING;
-
-/* Cache Component Defines ============================ */
-
-DEG_DEPSNODE_DEFINE(CacheComponentDepsNode, DEG_NODE_TYPE_CACHE, "Cache Component");
-static DepsNodeFactoryImpl<CacheComponentDepsNode> DNTI_CACHE;
-
+DEG_COMPONENT_DEFINE(Bone, BONE);
/* Node Types Register =================================== */
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h
index 4ef7dad3ac6..1c21a71737f 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h
@@ -74,18 +74,26 @@ struct ComponentDepsNode : public DepsNode {
string identifier() const;
- /* Find an existing operation, will throw an assert() if it does not exist. */
+ /* Find an existing operation, if requested operation does not exist
+ * NULL will be returned.
+ */
OperationDepsNode *find_operation(OperationIDKey key) const;
OperationDepsNode *find_operation(eDepsOperation_Code opcode,
- const char *name,
- int name_tag) const;
+ const char *name,
+ int name_tag) const;
- /* Check operation exists and return it. */
- OperationDepsNode *has_operation(OperationIDKey key) const;
- OperationDepsNode *has_operation(eDepsOperation_Code opcode,
+ /* Find an existing operation, will throw an assert() if it does not exist. */
+ OperationDepsNode *get_operation(OperationIDKey key) const;
+ OperationDepsNode *get_operation(eDepsOperation_Code opcode,
const char *name,
int name_tag) const;
+ /* Check operation exists and return it. */
+ bool has_operation(OperationIDKey key) const;
+ bool has_operation(eDepsOperation_Code opcode,
+ const char *name,
+ int name_tag) const;
+
/**
* Create a new node for representing an operation and add this to graph
* \warning If an existing node is found, it will be modified. This helps
@@ -158,33 +166,21 @@ struct ComponentDepsNode : public DepsNode {
/* ---------------------------------------- */
-struct ParametersComponentDepsNode : public ComponentDepsNode {
- DEG_DEPSNODE_DECLARE;
-};
-
-struct AnimationComponentDepsNode : public ComponentDepsNode {
- DEG_DEPSNODE_DECLARE;
-};
-
-struct TransformComponentDepsNode : public ComponentDepsNode {
- DEG_DEPSNODE_DECLARE;
-};
-
-struct ProxyComponentDepsNode : public ComponentDepsNode {
- DEG_DEPSNODE_DECLARE;
-};
-
-struct GeometryComponentDepsNode : public ComponentDepsNode {
- DEG_DEPSNODE_DECLARE;
-};
-
-struct SequencerComponentDepsNode : public ComponentDepsNode {
- DEG_DEPSNODE_DECLARE;
-};
-
-struct PoseComponentDepsNode : public ComponentDepsNode {
- DEG_DEPSNODE_DECLARE;
-};
+#define DEG_COMPONENT_DECLARE_GENERIC(name) \
+ struct name ## ComponentDepsNode : public ComponentDepsNode { \
+ DEG_DEPSNODE_DECLARE; \
+ }
+
+DEG_COMPONENT_DECLARE_GENERIC(Animation);
+DEG_COMPONENT_DECLARE_GENERIC(Cache);
+DEG_COMPONENT_DECLARE_GENERIC(Geometry);
+DEG_COMPONENT_DECLARE_GENERIC(Parameters);
+DEG_COMPONENT_DECLARE_GENERIC(Particles);
+DEG_COMPONENT_DECLARE_GENERIC(Proxy);
+DEG_COMPONENT_DECLARE_GENERIC(Pose);
+DEG_COMPONENT_DECLARE_GENERIC(Sequencer);
+DEG_COMPONENT_DECLARE_GENERIC(Shading);
+DEG_COMPONENT_DECLARE_GENERIC(Transform);
/* Bone Component */
struct BoneComponentDepsNode : public ComponentDepsNode {
@@ -195,19 +191,6 @@ struct BoneComponentDepsNode : public ComponentDepsNode {
DEG_DEPSNODE_DECLARE;
};
-struct ParticlesComponentDepsNode : public ComponentDepsNode {
- DEG_DEPSNODE_DECLARE;
-};
-
-struct ShadingComponentDepsNode : public ComponentDepsNode {
- DEG_DEPSNODE_DECLARE;
-};
-
-struct CacheComponentDepsNode : public ComponentDepsNode {
- DEG_DEPSNODE_DECLARE;
-};
-
-
void deg_register_component_depsnodes();
} // namespace DEG
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 25f1e206be5..82f24c91df1 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -34,11 +34,9 @@
#include "MEM_guardedalloc.h"
-#include "BKE_depsgraph.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
-#include "BKE_library.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@@ -52,11 +50,13 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
#include "BKE_context.h"
#include "BKE_mask.h"
#include "BKE_global.h"
+#include "BKE_library.h"
#include "UI_view2d.h"
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 30aaee8cbd9..04398e88499 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -133,10 +133,13 @@ int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, f
float cfra = (float)CFRA;
int changed_tot = 0;
- /* sanity check */
- if (markers == NULL)
+ /* sanity check - no markers, or locked markers */
+ if ((scene->toolsettings->lock_markers) ||
+ (markers == NULL))
+ {
return changed_tot;
-
+ }
+
/* affect selected markers - it's unlikely that we will want to affect all in this way? */
for (marker = markers->first; marker; marker = marker->next) {
if (marker->flag & SELECT) {
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 97f53561bfe..bf5d4ec0300 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -448,6 +448,18 @@ void sample_fcurve(FCurve *fcu)
/* check if selected, and which end this is */
if (BEZT_ISSEL_ANY(bezt)) {
if (start) {
+ /* If next bezt is also selected, don't start sampling yet,
+ * but instead wait for that one to reconsider, to avoid
+ * changing the curve when sampling consecutive segments
+ * (T53229)
+ */
+ if (i < fcu->totvert - 1) {
+ BezTriple *next = &fcu->bezt[i + 1];
+ if (BEZT_ISSEL_ANY(next)) {
+ continue;
+ }
+ }
+
/* set end */
end = bezt;
@@ -480,8 +492,8 @@ void sample_fcurve(FCurve *fcu)
i += (range - 1);
}
- /* bezt was selected, so it now marks the start of a whole new chain to search */
- start = bezt;
+ /* the current selection island has ended, so start again from scratch */
+ start = NULL;
end = NULL;
}
else {
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index e419100bd04..368d54fc3ad 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -944,9 +944,16 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
}
}
/* if only one bone, make this one active */
- if (totbone == 1 && first) arm->act_edbone = first;
+ if (totbone == 1 && first) {
+ arm->act_edbone = first;
+ }
+ else {
+ arm->act_edbone = newbone;
+ }
- if (totbone == 0) return OPERATOR_CANCELLED;
+ if (totbone == 0) {
+ return OPERATOR_CANCELLED;
+ }
/* Transform the endpoints */
ED_armature_sync_selection(arm->edbo);
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index ab9a3e068d0..a2fbfe645f7 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -1564,17 +1564,18 @@ void ARMATURE_OT_hide(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
}
-static int armature_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+static int armature_reveal_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
bArmature *arm = obedit->data;
EditBone *ebone;
+ const bool select = RNA_boolean_get(op->ptr, "select");
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if (arm->layer & ebone->layer) {
if (ebone->flag & BONE_HIDDEN_A) {
if (!(ebone->flag & BONE_UNSELECTABLE)) {
- ebone->flag |= (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ SET_FLAG_FROM_TEST(ebone->flag, select, (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL));
}
ebone->flag &= ~BONE_HIDDEN_A;
}
@@ -1593,7 +1594,7 @@ void ARMATURE_OT_reveal(wmOperatorType *ot)
/* identifiers */
ot->name = "Reveal Bones";
ot->idname = "ARMATURE_OT_reveal";
- ot->description = "Unhide all bones that have been tagged to be hidden in Edit Mode";
+ ot->description = "Reveal all bones hidden in Edit Mode";
/* api callbacks */
ot->exec = armature_reveal_exec;
@@ -1602,4 +1603,5 @@ void ARMATURE_OT_reveal(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 93185971492..07ff7f15ce4 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -38,7 +38,7 @@
#include "BLI_string_utils.h"
#include "BKE_context.h"
-//#include "BKE_deform.h"
+#include "BKE_action.h"
#include "BKE_report.h"
#include "BIF_gl.h"
@@ -801,6 +801,7 @@ enum {
SIMEDBONE_PREFIX,
SIMEDBONE_SUFFIX,
SIMEDBONE_LAYER,
+ SIMEDBONE_SHAPE,
};
static const EnumPropertyItem prop_similar_types[] = {
@@ -812,6 +813,7 @@ static const EnumPropertyItem prop_similar_types[] = {
{SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
{SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
{SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
+ {SIMEDBONE_SHAPE, "SHAPE", 0, "Shape", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -914,7 +916,27 @@ static void select_similar_suffix(bArmature *arm, EditBone *ebone_act)
}
}
-static void is_ancestor(EditBone * bone, EditBone * ancestor)
+/** Use for matching any pose channel data. */
+static void select_similar_data_pchan(
+ bArmature *arm, Object *obj, EditBone *ebone_active,
+ const size_t bytes_size, const int offset)
+{
+ const bPoseChannel *pchan_active = BKE_pose_channel_find_name(obj->pose, ebone_active->name);
+ const char *data_active = (const char *)POINTER_OFFSET(pchan_active, offset);
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ const bPoseChannel *pchan = BKE_pose_channel_find_name(obj->pose, ebone->name);
+ if (pchan) {
+ const char *data_test = (const char *)POINTER_OFFSET(pchan, offset);
+ if (memcmp(data_active, data_test, bytes_size) == 0) {
+ ED_armature_ebone_select_set(ebone, true);
+ }
+ }
+ }
+ }
+}
+
+static void is_ancestor(EditBone *bone, EditBone *ancestor)
{
if (bone->temp.ebone == ancestor || bone->temp.ebone == NULL)
return;
@@ -1006,6 +1028,11 @@ static int armature_select_similar_exec(bContext *C, wmOperator *op)
case SIMEDBONE_LAYER:
select_similar_layer(arm, ebone_act);
break;
+ case SIMEDBONE_SHAPE:
+ select_similar_data_pchan(
+ arm, obedit, ebone_act,
+ sizeof(void *), offsetof(bPoseChannel, custom));
+ break;
}
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index c49a370c286..acbf23ecf82 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -265,8 +265,8 @@ void POSE_OT_paths_calculate(wmOperatorType *ot)
static int pose_update_paths_poll(bContext *C)
{
if (ED_operator_posemode_exclusive(C)) {
- bPoseChannel *pchan = CTX_data_active_pose_bone(C);
- return (pchan && pchan->mpath);
+ Object *ob = CTX_data_active_object(C);
+ return (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
}
return false;
@@ -1098,16 +1098,18 @@ void POSE_OT_hide(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "");
}
-static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
+static int show_pose_bone_cb(Object *ob, Bone *bone, void *data)
{
+ const bool select = GET_INT_FROM_POINTER(data);
+
bArmature *arm = ob->data;
if (arm->layer & bone->layer) {
if (bone->flag & BONE_HIDDEN_P) {
- bone->flag &= ~BONE_HIDDEN_P;
if (!(bone->flag & BONE_UNSELECTABLE)) {
- bone->flag |= BONE_SELECTED;
+ SET_FLAG_FROM_TEST(bone->flag, select, BONE_SELECTED);
}
+ bone->flag &= ~BONE_HIDDEN_P;
}
}
@@ -1115,12 +1117,13 @@ static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
}
/* active object is armature in posemode, poll checked */
-static int pose_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+static int pose_reveal_exec(bContext *C, wmOperator *op)
{
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bArmature *arm = ob->data;
+ const bool select = RNA_boolean_get(op->ptr, "select");
- bone_looper(ob, arm->bonebase.first, NULL, show_pose_bone_cb);
+ bone_looper(ob, arm->bonebase.first, SET_INT_IN_POINTER(select), show_pose_bone_cb);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
@@ -1133,7 +1136,7 @@ void POSE_OT_reveal(wmOperatorType *ot)
/* identifiers */
ot->name = "Reveal Selected";
ot->idname = "POSE_OT_reveal";
- ot->description = "Unhide all bones that have been tagged to be hidden in Pose Mode";
+ ot->description = "Reveal all bones hidden in Pose Mode";
/* api callbacks */
ot->exec = pose_reveal_exec;
@@ -1141,6 +1144,8 @@ void POSE_OT_reveal(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/* ********************************************** */
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index 2d86610e065..3707b914ecb 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -484,12 +484,15 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
bPoseChannel *chan;
const bool flip = RNA_boolean_get(op->ptr, "flipped");
bool selOnly = RNA_boolean_get(op->ptr, "selected_mask");
+
/* Get KeyingSet to use. */
KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
+
/* Sanity checks. */
if (ELEM(NULL, ob, ob->pose)) {
return OPERATOR_CANCELLED;
}
+
/* Read copy buffer .blend file. */
char str[FILE_MAX];
Main *tmp_bmain = BKE_main_new();
@@ -505,6 +508,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
BKE_main_free(tmp_bmain);
return OPERATOR_CANCELLED;
}
+
Object *object_from = tmp_bmain->object.first;
bPose *pose_from = object_from->pose;
if (pose_from == NULL) {
@@ -512,6 +516,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
BKE_main_free(tmp_bmain);
return OPERATOR_CANCELLED;
}
+
/* If selOnly option is enabled, if user hasn't selected any bones,
* just go back to default behavior to be more in line with other
* pose tools.
@@ -521,6 +526,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
selOnly = false;
}
}
+
/* Safely merge all of the channels in the buffer pose into any
* existing pose.
*/
@@ -535,8 +541,15 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
}
}
BKE_main_free(tmp_bmain);
+
/* Update event for pose and deformation children. */
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+
+ /* Recalculate paths if any of the bones have paths... */
+ if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
+ ED_pose_recalculate_paths(scene, ob);
+ }
+
/* Notifiers for updates, */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 4916c206a85..fc363475608 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -2926,7 +2926,7 @@ void CURVE_OT_hide(wmOperatorType *ot)
/********************** reveal operator *********************/
-static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
+static int reveal_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
ListBase *editnurb = object_editcurve_get(obedit);
@@ -2934,6 +2934,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
BPoint *bp;
BezTriple *bezt;
int a;
+ const bool select = RNA_boolean_get(op->ptr, "select");
for (nu = editnurb->first; nu; nu = nu->next) {
nu->hide = 0;
@@ -2942,7 +2943,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
a = nu->pntsu;
while (a--) {
if (bezt->hide) {
- select_beztriple(bezt, SELECT, SELECT, HIDDEN);
+ select_beztriple(bezt, select, SELECT, HIDDEN);
bezt->hide = 0;
}
bezt++;
@@ -2953,7 +2954,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
a = nu->pntsu * nu->pntsv;
while (a--) {
if (bp->hide) {
- select_bpoint(bp, SELECT, SELECT, HIDDEN);
+ select_bpoint(bp, select, SELECT, HIDDEN);
bp->hide = 0;
}
bp++;
@@ -2972,7 +2973,7 @@ void CURVE_OT_reveal(wmOperatorType *ot)
/* identifiers */
ot->name = "Reveal Hidden";
ot->idname = "CURVE_OT_reveal";
- ot->description = "Show again hidden control points";
+ ot->description = "Reveal hidden control points";
/* api callbacks */
ot->exec = reveal_exec;
@@ -2980,6 +2981,8 @@ void CURVE_OT_reveal(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/********************** subdivide operator *********************/
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 93c9d21e717..5bd5c9c74b9 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -423,18 +423,59 @@ static int gp_reveal_poll(bContext *C)
return ED_gpencil_data_get_active(C) != NULL;
}
-static int gp_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+static void gp_reveal_select_frame(bContext *C, bGPDframe *frame, bool select)
+{
+ bGPDstroke *gps;
+ for (gps = frame->strokes.first; gps; gps = gps->next) {
+
+ /* only deselect strokes that are valid in this view */
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+
+ /* (de)select points */
+ int i;
+ bGPDspoint *pt;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ SET_FLAG_FROM_TEST(pt->flag, select, GP_SPOINT_SELECT);
+ }
+
+ /* (de)select stroke */
+ SET_FLAG_FROM_TEST(gps->flag, select, GP_STROKE_SELECT);
+ }
+ }
+}
+
+static int gp_reveal_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *gpl;
-
+ const bool select = RNA_boolean_get(op->ptr, "select");
+
/* sanity checks */
if (gpd == NULL)
return OPERATOR_CANCELLED;
- /* make all layers visible */
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- gpl->flag &= ~GP_LAYER_HIDE;
+
+ if (gpl->flag & GP_LAYER_HIDE) {
+ gpl->flag &= ~GP_LAYER_HIDE;
+
+ /* select or deselect if requested, only on hidden layers */
+ if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ if (select) {
+ /* select all strokes on active frame only (same as select all operator) */
+ if (gpl->actframe) {
+ gp_reveal_select_frame(C, gpl->actframe, true);
+ }
+ }
+ else {
+ /* deselect strokes on all frames (same as deselect all operator) */
+ bGPDframe *gpf;
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ gp_reveal_select_frame(C, gpf, false);
+ }
+ }
+ }
+ }
}
/* notifiers */
@@ -456,6 +497,9 @@ void GPENCIL_OT_reveal(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/* ***************** Lock/Unlock All Layers ************************ */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index cff198db6c0..f54356dfed3 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -2745,6 +2745,8 @@ static const EnumPropertyItem prop_gpencil_drawmodes[] = {
void GPENCIL_OT_draw(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Grease Pencil Draw";
ot->idname = "GPENCIL_OT_draw";
@@ -2761,11 +2763,12 @@ void GPENCIL_OT_draw(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
/* settings for drawing */
- PropertyRNA *prop;
ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements");
+
prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
/* NOTE: wait for input is enabled by default, so that all UI code can work properly without needing users to know about this */
- RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately");
+ prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index c867df2d01a..84698b33e25 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -75,7 +75,6 @@ struct BMFace *EDBM_verts_mirror_get_face(struct BMEditMesh *em, struct BMFace *
void EDBM_verts_mirror_cache_clear(struct BMEditMesh *em, struct BMVert *v);
void EDBM_verts_mirror_cache_end(struct BMEditMesh *em);
-void EDBM_mesh_ensure_valid_dm_hack(struct Scene *scene, struct BMEditMesh *em);
void EDBM_mesh_normals_update(struct BMEditMesh *em);
void EDBM_mesh_clear(struct BMEditMesh *em);
@@ -103,7 +102,7 @@ void undo_push_mesh(struct bContext *C, const char *name);
bool EDBM_vert_color_check(struct BMEditMesh *em);
void EDBM_mesh_hide(struct BMEditMesh *em, bool swap);
-void EDBM_mesh_reveal(struct BMEditMesh *em);
+void EDBM_mesh_reveal(struct BMEditMesh *em, bool select);
void EDBM_update_generic(struct BMEditMesh *em, const bool do_tessface, const bool is_destructive);
@@ -205,7 +204,7 @@ void paintface_select_linked(struct bContext *C, struct Object *ob, const int mv
bool paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]);
void paintface_hide(struct Object *ob, const bool unselected);
-void paintface_reveal(struct Object *ob);
+void paintface_reveal(struct Object *ob, const bool select);
void paintvert_deselect_all_visible(struct Object *ob, int action, bool flush_flags);
void paintvert_select_ungrouped(struct Object *ob, bool extend, bool flush_flags);
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 535683823bf..354a9655a48 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -101,7 +101,8 @@ void ED_uvedit_live_unwrap_end(short cancel);
void ED_uvedit_live_unwrap(struct Scene *scene, struct Object *obedit);
void ED_uvedit_pack_islands(struct Scene *scene, struct Object *ob, struct BMesh *bm, bool selected, bool correct_aspect, bool do_rotate);
-void ED_uvedit_unwrap_cube_project(struct Object *ob, struct BMesh *bm, float cube_size, bool use_select);
+void ED_uvedit_unwrap_cube_project(
+ struct BMesh *bm, float cube_size, bool use_select, const float center[3]);
/* single call up unwrap using scene settings, used for edge tag unwrapping */
void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 85fb0ee4447..2cc928117c5 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -367,15 +367,27 @@ void ED_view3d_draw_setup_view(
struct wmWindow *win, struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
float viewmat[4][4], float winmat[4][4], const struct rcti *rect);
+enum {
+ V3D_OFSDRAW_NONE = (0),
+
+ V3D_OFSDRAW_USE_BACKGROUND = (1 << 0),
+ V3D_OFSDRAW_USE_FULL_SAMPLE = (1 << 1),
+
+ /* Only works with ED_view3d_draw_offscreen_imbuf_simple(). */
+ V3D_OFSDRAW_USE_GPENCIL = (1 << 2),
+ V3D_OFSDRAW_USE_SOLID_TEX = (1 << 2),
+ V3D_OFSDRAW_USE_CAMERA_DOF = (1 << 3),
+};
+
struct ImBuf *ED_view3d_draw_offscreen_imbuf(
struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey,
- unsigned int flag, bool draw_background,
- int alpha_mode, int samples, bool full_samples, const char *viewname,
+ unsigned int flag, unsigned int draw_flags,
+ int alpha_mode, int samples, const char *viewname,
struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
struct Scene *scene, struct Object *camera, int width, int height,
- unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
- int alpha_mode, int samples, bool full_samples, const char *viewname,
+ unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode,
+ int samples, const char *viewname,
struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index be7eb2bf9ed..407c19a3860 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -658,87 +658,18 @@ void ED_mask_draw(const bContext *C,
draw_masklays(C, mask, draw_flag, draw_type, width, height, xscale * aspx, yscale * aspy);
}
-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 * __restrict pool, void *taskdata, int UNUSED(threadid))
+static float *mask_rasterize(Mask *mask, const int width, const int height)
{
- ThreadedMaskRasterizeState *state = (ThreadedMaskRasterizeState *) BLI_task_pool_userdata(pool);
- ThreadedMaskRasterizeData *data = (ThreadedMaskRasterizeData *) taskdata;
- int scanline;
- const float x_inv = 1.0f / (float)state->width;
- const float y_inv = 1.0f / (float)state->height;
- const float x_px_ofs = x_inv * 0.5f;
- const float y_px_ofs = y_inv * 0.5f;
-
- for (scanline = 0; scanline < data->num_scanlines; scanline++) {
- float xy[2];
- int x, y = data->start_scanline + scanline;
-
- xy[1] = ((float)y * y_inv) + y_px_ofs;
-
- for (x = 0; x < state->width; x++) {
- int index = y * state->width + x;
-
- xy[0] = ((float)x * x_inv) + x_px_ofs;
-
- 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");
+ float *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);
-
- 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);
+ BKE_maskrasterize_buffer(handle, width, height, buffer);
/* Free memory. */
- BLI_task_pool_free(task_pool);
BKE_maskrasterize_handle_free(handle);
return buffer;
@@ -802,7 +733,7 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
}
if (draw_flag & MASK_DRAWFLAG_OVERLAY) {
- float *buffer = threaded_mask_rasterize(mask, width, height);
+ float *buffer = mask_rasterize(mask, width, height);
int format;
if (overlay_mode == MASK_OVERLAY_ALPHACHANNEL) {
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 101ef70fb70..97d5ee1eff0 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -1937,16 +1937,17 @@ void MASK_OT_handle_type_set(wmOperatorType *ot)
/* ********* clear/set restrict view *********/
-static int mask_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
+static int mask_hide_view_clear_exec(bContext *C, wmOperator *op)
{
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
bool changed = false;
+ const bool select = RNA_boolean_get(op->ptr, "select");
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
if (masklay->restrictflag & OB_RESTRICT_VIEW) {
- ED_mask_layer_select_set(masklay, true);
+ ED_mask_layer_select_set(masklay, select);
masklay->restrictflag &= ~OB_RESTRICT_VIEW;
changed = true;
}
@@ -1977,6 +1978,8 @@ void MASK_OT_hide_view_clear(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 6c6c106b19a..87c8c55b0a1 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -42,7 +42,6 @@
#include "BKE_mesh.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
-#include "BKE_utildefines.h"
#include "BIF_gl.h"
@@ -139,7 +138,7 @@ void paintface_hide(Object *ob, const bool unselected)
}
-void paintface_reveal(Object *ob)
+void paintface_reveal(Object *ob, const bool select)
{
Mesh *me;
MPoly *mpoly;
@@ -152,8 +151,8 @@ void paintface_reveal(Object *ob)
a = me->totpoly;
while (a--) {
if (mpoly->flag & ME_HIDE) {
- mpoly->flag |= ME_FACE_SEL;
- mpoly->flag -= ME_HIDE;
+ SET_FLAG_FROM_TEST(mpoly->flag, select, ME_FACE_SEL);
+ mpoly->flag &= ~ME_HIDE;
}
mpoly++;
}
@@ -231,7 +230,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const unsigned int index,
for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++) {
if (BLI_BITMAP_TEST(poly_tag, a)) {
- BKE_BIT_TEST_SET(mp->flag, select, ME_FACE_SEL);
+ SET_FLAG_FROM_TEST(mp->flag, select, ME_FACE_SEL);
}
}
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 2af05a9ad8d..68fd4212004 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -335,11 +335,12 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
* ideally this will never happen and should be checked for above */
opdata->mcenter[0] = opdata->mcenter[1] = 0;
}
- edbm_bevel_calc_initial_length(op, event, false);
/* for OFFSET_VALUE only, the scale is the size of a pixel under the mouse in 3d space */
opdata->scale[OFFSET_VALUE] = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
+ edbm_bevel_calc_initial_length(op, event, false);
+
edbm_bevel_update_header(C, op);
if (!edbm_bevel_calc(op)) {
@@ -622,6 +623,7 @@ void MESH_OT_bevel(wmOperatorType *ot)
RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures");
prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 1.0f);
RNA_def_property_float_array_funcs_runtime(prop, NULL, NULL, mesh_ot_bevel_offset_range_func);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_int(ot->srna, "segments", 1, 1, SEGMENTS_HARD_MAX, "Segments", "Segments for curved edge", 1, 8);
RNA_def_float(ot->srna, "profile", 0.5f, PROFILE_HARD_MIN, 1.0f, "Profile",
"Controls profile shape (0.5 = round)", PROFILE_HARD_MIN, 1.0f);
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index f1c1e4105d0..b9192f58a1b 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -517,9 +517,6 @@ static int ringsel_init(bContext *C, wmOperator *op, bool do_cut)
lcd->num.unit_type[0] = B_UNIT_NONE;
lcd->num.unit_type[1] = B_UNIT_NONE;
- /* XXX, temp, workaround for [# ] */
- EDBM_mesh_ensure_valid_dm_hack(scene, lcd->em);
-
em_setup_viewcontext(C, &lcd->vc);
ED_region_tag_redraw(lcd->ar);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index bf25f7ee7d1..4b4f1b2afea 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -1531,7 +1531,9 @@ void MESH_OT_flip_normals(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* only accepts 1 selected edge, or 2 selected faces */
+/**
+ * Rotate the edges between selected faces, otherwise rotate the selected edges.
+ */
static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -1652,12 +1654,13 @@ void MESH_OT_hide(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
}
-static int edbm_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+static int edbm_reveal_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- EDBM_mesh_reveal(em);
+ const bool select = RNA_boolean_get(op->ptr, "select");
+
+ EDBM_mesh_reveal(em, select);
EDBM_update_generic(em, true, false);
@@ -1677,6 +1680,8 @@ void MESH_OT_reveal(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index c8151862b6c..44aca23e2cc 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -52,7 +52,7 @@
#include "BKE_editmesh.h"
#include "BKE_editmesh_bvh.h"
-#include "BKE_object.h" /* XXX. only for EDBM_mesh_ensure_valid_dm_hack() which will be removed */
+#include "BKE_object.h" /* XXX. only for EDBM_mesh_load(). */
#include "WM_api.h"
#include "WM_types.h"
@@ -107,21 +107,6 @@ void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess)
BKE_editmesh_tessface_calc(em);
}
-/* hack to workaround multiple operators being called within the same event loop without an update
- * see: [#31811] */
-void EDBM_mesh_ensure_valid_dm_hack(Scene *scene, BMEditMesh *em)
-{
- if ((((ID *)em->ob->data)->tag & LIB_TAG_ID_RECALC) ||
- (em->ob->recalc & OB_RECALC_DATA))
- {
- /* since we may not have done selection flushing */
- if ((em->ob->recalc & OB_RECALC_DATA) == 0) {
- DAG_id_tag_update(&em->ob->id, OB_RECALC_DATA);
- }
- BKE_object_handle_update(G.main->eval_ctx, scene, em->ob);
- }
-}
-
void EDBM_mesh_normals_update(BMEditMesh *em)
{
BM_mesh_normals_update(em->bm);
@@ -412,6 +397,7 @@ void EDBM_mesh_load(Object *ob)
* of freed data on scene update, especially in cases when there are dependency
* cycles.
*/
+ /*
for (Object *other_object = G.main->object.first;
other_object != NULL;
other_object = other_object->id.next)
@@ -420,6 +406,7 @@ void EDBM_mesh_load(Object *ob)
BKE_object_free_derived_caches(other_object);
}
}
+ */
}
/**
@@ -1225,7 +1212,7 @@ void EDBM_mesh_hide(BMEditMesh *em, bool swap)
}
-void EDBM_mesh_reveal(BMEditMesh *em)
+void EDBM_mesh_reveal(BMEditMesh *em, bool select)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -1240,7 +1227,6 @@ void EDBM_mesh_reveal(BMEditMesh *em)
/* Use tag flag to remember what was hidden before all is revealed.
* BM_ELEM_HIDDEN --> BM_ELEM_TAG */
-#pragma omp parallel for schedule(static) if (em->bm->totvert + em->bm->totedge + em->bm->totface >= BM_OMP_LIMIT)
for (i = 0; i < 3; i++) {
BMIter iter;
BMElem *ele;
@@ -1264,7 +1250,7 @@ void EDBM_mesh_reveal(BMEditMesh *em)
BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) {
if (BM_elem_flag_test(ele, BM_ELEM_TAG)) {
- BM_elem_select_set(em->bm, ele, true);
+ BM_elem_select_set(em->bm, ele, select);
}
}
}
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 009aa921e11..5b4078b98b7 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -542,19 +542,21 @@ void MBALL_OT_hide_metaelems(wmOperatorType *ot)
/***************************** Unhide operator *****************************/
/* Unhide all edited MetaElems */
-static int reveal_metaelems_exec(bContext *C, wmOperator *UNUSED(op))
+static int reveal_metaelems_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
MetaBall *mb = (MetaBall *)obedit->data;
- MetaElem *ml;
-
- ml = mb->editelems->first;
+ const bool select = RNA_boolean_get(op->ptr, "select");
+ bool changed = false;
- if (ml) {
- while (ml) {
+ for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
+ if (ml->flag & MB_HIDE) {
+ SET_FLAG_FROM_TEST(ml->flag, select, SELECT);
ml->flag &= ~MB_HIDE;
- ml = ml->next;
+ changed = true;
}
+ }
+ if (changed) {
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
DAG_id_tag_update(obedit->data, 0);
}
@@ -575,6 +577,9 @@ void MBALL_OT_reveal_metaelems(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/* Select MetaElement with mouse click (user can select radius circle or
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 4e949c82a9f..d7c7976c344 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -133,7 +133,7 @@ Object *ED_object_active_context(bContext *C)
/* ********* clear/set restrict view *********/
-static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
+static int object_hide_view_clear_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
ScrArea *sa = CTX_wm_area(C);
@@ -141,12 +141,13 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
Base *base;
bool changed = false;
+ const bool select = RNA_boolean_get(op->ptr, "select");
/* XXX need a context loop to handle such cases */
for (base = FIRSTBASE; base; base = base->next) {
if ((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) {
- base->flag |= SELECT;
+ SET_FLAG_FROM_TEST(base->flag, select, SELECT);
}
base->object->flag = base->flag;
base->object->restrictflag &= ~OB_RESTRICT_VIEW;
@@ -176,6 +177,8 @@ void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
static int object_hide_view_set_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c
index ac8d438d9e6..57053ddc020 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/object/object_lattice.c
@@ -57,7 +57,6 @@
#include "BKE_lattice.h"
#include "BKE_deform.h"
#include "BKE_report.h"
-#include "BKE_utildefines.h"
#include "ED_lattice.h"
#include "ED_object.h"
@@ -369,7 +368,7 @@ static int lattice_select_more_less(bContext *C, const bool select)
lattice_test_bitmap_uvw(lt, selpoints, u, v, w + 1, select) ||
lattice_test_bitmap_uvw(lt, selpoints, u, v, w - 1, select))
{
- BKE_BIT_TEST_SET(bp->f1, select, SELECT);
+ SET_FLAG_FROM_TEST(bp->f1, select, SELECT);
}
}
bp++;
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 5fe5a884354..9b9f77a1dbb 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -374,13 +374,6 @@ void ED_keymap_object(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "clear_delta", false);
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_location_clear", GKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "clear_delta", true);
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_rotation_clear", RKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "clear_delta", true);
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_scale_clear", SKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "clear_delta", true);
-
WM_keymap_verify_item(keymap, "OBJECT_OT_origin_clear", OKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 199d5e0fbfa..da66ec44235 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -1950,11 +1950,12 @@ void PARTICLE_OT_hide(wmOperatorType *ot)
/*************************** reveal operator **************************/
-static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
+static int reveal_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_active_object(C);
Scene *scene= CTX_data_scene(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ const bool select = RNA_boolean_get(op->ptr, "select");
POINT_P; KEY_K;
LOOP_POINTS {
@@ -1962,8 +1963,9 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
point->flag &= ~PEP_HIDE;
point->flag |= PEP_EDIT_RECALC;
- LOOP_KEYS
- key->flag |= PEK_SELECT;
+ LOOP_KEYS {
+ SET_FLAG_FROM_TEST(key->flag, select, PEK_SELECT);
+ }
}
}
@@ -1986,6 +1988,9 @@ void PARTICLE_OT_reveal(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/************************ select less operator ************************/
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index a27026878e1..1133b5f79d1 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -353,11 +353,15 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
ImBuf *ibuf_view;
const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL;
+ unsigned int draw_flags = V3D_OFSDRAW_NONE;
+ draw_flags |= (oglrender->ofs_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0;
+
if (view_context) {
+ draw_flags |= (draw_bgpic) ? V3D_OFSDRAW_USE_BACKGROUND : 0;
+
ibuf_view = ED_view3d_draw_offscreen_imbuf(
scene, v3d, ar, sizex, sizey,
- IB_rect, draw_bgpic,
- alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname,
+ IB_rect, draw_flags, alpha_mode, oglrender->ofs_samples, viewname,
oglrender->fx, oglrender->ofs, err_out);
/* for stamp only */
@@ -366,10 +370,11 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
}
}
else {
+ draw_flags |= (V3D_OFSDRAW_USE_GPENCIL | V3D_OFSDRAW_USE_BACKGROUND);
ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(
scene, scene->camera, oglrender->sizex, oglrender->sizey,
- IB_rect, OB_SOLID, false, true, true,
- alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname,
+ IB_rect, draw_flags, OB_SOLID,
+ alpha_mode, oglrender->ofs_samples, viewname,
oglrender->fx, oglrender->ofs, err_out);
camera = scene->camera;
}
@@ -679,6 +684,15 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
oglrender->fx = GPU_fx_compositor_create();
}
}
+ else if (is_sequencer) {
+ /* NOTE: We allow animation of DoF setting for flexibility in edits, so
+ * we can't check in advance whether we need FX compositor or not.
+ * We just always allocated it and make sure it doesn't add extra
+ * overhead rather than memory allocation here if it's not really
+ * needed.
+ */
+ oglrender->fx = GPU_fx_compositor_create();
+ }
/* create render */
oglrender->re = RE_NewSceneRender(scene);
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 0ee78d61fb8..337f7a1ef2b 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -33,13 +33,13 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
+#include "BLI_math_vector.h"
+#include "BLI_string.h"
+
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_paint.h"
-#include "BLI_math_vector.h"
-#include "BLI_string.h"
-
#include "ED_paint.h"
#include "ED_view3d.h"
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index d14b75149c9..6fa45f1932a 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -5460,7 +5460,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
ibuf = ED_view3d_draw_offscreen_imbuf(
scene, CTX_wm_view3d(C), CTX_wm_region(C),
- w, h, IB_rect, false, R_ALPHAPREMUL, 0, false, NULL,
+ w, h, IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
NULL, NULL, err_out);
if (!ibuf) {
/* Mostly happens when OpenGL offscreen buffer was failed to create, */
@@ -5904,7 +5904,7 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
}));
/* select all uv loops first - pack parameters needs this to make sure charts are registered */
ED_uvedit_select_all(bm);
- ED_uvedit_unwrap_cube_project(ob, bm, 1.0, false);
+ ED_uvedit_unwrap_cube_project(bm, 1.0, false, NULL);
/* set the margin really quickly before the packing operation*/
scene->toolsettings->uvcalc_margin = 0.001f;
ED_uvedit_pack_islands(scene, ob, bm, false, false, true);
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 8304e782b07..1c2ab442e95 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -749,10 +749,11 @@ void PAINT_OT_face_select_hide(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
}
-static int face_select_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+static int face_select_reveal_exec(bContext *C, wmOperator *op)
{
+ const bool select = RNA_boolean_get(op->ptr, "select");
Object *ob = CTX_data_active_object(C);
- paintface_reveal(ob);
+ paintface_reveal(ob, select);
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_FINISHED;
}
@@ -768,5 +769,5 @@ void PAINT_OT_face_select_reveal(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 985cca7c4af..df6bd01144d 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -64,6 +64,7 @@
#include "ED_anim_api.h"
#include "ED_keyframing.h"
#include "ED_screen.h"
+#include "ED_util.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -503,25 +504,28 @@ static void driver_remove_cb(bContext *C, void *ale_v, void *UNUSED(arg))
/* call API method to remove this driver */
ANIM_remove_driver(reports, id, fcu->rna_path, fcu->array_index, 0);
+ ED_undo_push(C, "Remove Driver");
}
/* callback to add a target variable to the active driver */
-static void driver_add_var_cb(bContext *UNUSED(C), void *driver_v, void *UNUSED(arg))
+static void driver_add_var_cb(bContext *C, void *driver_v, void *UNUSED(arg))
{
ChannelDriver *driver = (ChannelDriver *)driver_v;
/* add a new variable */
driver_add_new_variable(driver);
+ ED_undo_push(C, "Add Driver Variable");
}
/* callback to remove target variable from active driver */
-static void driver_delete_var_cb(bContext *UNUSED(C), void *driver_v, void *dvar_v)
+static void driver_delete_var_cb(bContext *C, void *driver_v, void *dvar_v)
{
ChannelDriver *driver = (ChannelDriver *)driver_v;
DriverVar *dvar = (DriverVar *)dvar_v;
/* remove the active variable */
driver_free_variable_ex(driver, dvar);
+ ED_undo_push(C, "Delete Driver Variable");
}
/* callback to report why a driver variable is invalid */
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 5c670a216d8..62275abcd02 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -333,13 +333,14 @@ static void GRAPH_OT_hide(wmOperatorType *ot)
/* ........ */
-static int graphview_curves_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+static int graphview_curves_reveal_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
ListBase anim_data = {NULL, NULL};
ListBase all_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
+ const bool select = RNA_boolean_get(op->ptr, "select");
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -364,8 +365,11 @@ static int graphview_curves_reveal_exec(bContext *C, wmOperator *UNUSED(op))
continue;
/* select if it is not visible */
- if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0)
- ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD);
+ if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0) {
+ ANIM_channel_setting_set(
+ &ac, ale, ACHANNEL_SETTING_SELECT,
+ select ? ACHANNEL_SETFLAG_ADD : ACHANNEL_SETFLAG_CLEAR);
+ }
/* change the visibility setting */
ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
@@ -397,6 +401,8 @@ static void GRAPH_OT_reveal(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/* ************************** registration - operator types **********************************/
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index d2897c7264b..51ccaf6800a 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -433,7 +433,7 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
uiItemS(layout);
- nr = (rl == NULL)? 1: 0;
+ nr = (rl == NULL) ? 1 : 0;
ListBase added_passes;
BLI_listbase_clear(&added_passes);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index f7df29ed2b6..24db8ba40fd 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1301,12 +1301,12 @@ static int image_open_exec(bContext *C, wmOperator *op)
if (iod->iuser) {
iuser = iod->iuser;
}
- else if (sa->spacetype == SPACE_IMAGE) {
+ else if (sa && sa->spacetype == SPACE_IMAGE) {
SpaceImage *sima = sa->spacedata.first;
ED_space_image_set(sima, scene, obedit, ima);
iuser = &sima->iuser;
}
- else if (sa->spacetype == SPACE_VIEW3D) {
+ else if (sa && sa->spacetype == SPACE_VIEW3D) {
View3D *v3d = sa->spacedata.first;
for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index ccc52f2dba8..ca7dbe4f73c 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -150,7 +150,13 @@ eOLDrawState tree_element_type_active(
TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive);
eOLDrawState tree_element_active(struct bContext *C, struct Scene *scene, SpaceOops *soops,
TreeElement *te, const eOLSetState set, const bool handle_all_types);
-int outliner_item_do_activate(struct bContext *C, int x, int y, bool extend, bool recursive);
+
+void outliner_item_do_activate_from_tree_element(
+ struct bContext *C, TreeElement *te, TreeStoreElem *tselem,
+ bool extend, bool recursive);
+int outliner_item_do_activate_from_cursor(
+ struct bContext *C, const int mval[2],
+ bool extend, bool recursive);
/* outliner_edit.c ---------------------------------------------- */
typedef void (*outliner_operation_cb)(
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 5cc83d3ee94..9f79b575966 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -816,7 +816,7 @@ eOLDrawState tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, Tr
{
switch (te->idcode) {
/* Note: ID_OB only if handle_all_type is true, else objects are handled specially to allow multiple
- * selection. See do_outliner_item_activate. */
+ * selection. See do_outliner_item_activate_from_cursor. */
case ID_OB:
if (handle_all_types) {
return tree_element_set_active_object(C, scene, soops, te, set, false);
@@ -892,10 +892,85 @@ eOLDrawState tree_element_type_active(
/* ================================================ */
-static bool do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops,
- TreeElement *te, bool extend, bool recursive, const float mval[2])
+/**
+ * Action when clicking to activate an item (typically under the mouse cursor),
+ * but don't do any cursor intersection checks.
+ *
+ * Needed to run from operators accessed from a menu.
+ */
+static void do_outliner_item_activate_tree_element(
+ bContext *C, Scene *scene, SpaceOops *soops,
+ TreeElement *te, TreeStoreElem *tselem,
+ bool extend, bool recursive)
+{
+ /* always makes active object, except for some specific types.
+ * Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want
+ * to switch out of edit mode (see T48328 for details). */
+ if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE)) {
+ tree_element_set_active_object(
+ C, scene, soops, te,
+ (extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
+ recursive && tselem->type == 0);
+ }
+
+ if (tselem->type == 0) { // the lib blocks
+ /* editmode? */
+ if (te->idcode == ID_SCE) {
+ if (scene != (Scene *)tselem->id) {
+ ED_screen_set_scene(C, CTX_wm_screen(C), (Scene *)tselem->id);
+ }
+ }
+ else if (te->idcode == ID_GR) {
+ Group *gr = (Group *)tselem->id;
+ GroupObject *gob;
+
+ if (extend) {
+ int sel = BA_SELECT;
+ for (gob = gr->gobject.first; gob; gob = gob->next) {
+ if (gob->ob->flag & SELECT) {
+ sel = BA_DESELECT;
+ break;
+ }
+ }
+
+ for (gob = gr->gobject.first; gob; gob = gob->next) {
+ ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel);
+ }
+ }
+ else {
+ BKE_scene_base_deselect_all(scene);
+
+ for (gob = gr->gobject.first; gob; gob = gob->next) {
+ if ((gob->ob->flag & SELECT) == 0)
+ ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
+ else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
+ WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
+ else { // rest of types
+ tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, false);
+ }
+
+ }
+ else {
+ tree_element_type_active(
+ C, scene, soops, te, tselem,
+ extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
+ recursive);
+ }
+}
+
+/**
+ * Activates tree items, also handles clicking on arrows.
+ */
+static bool do_outliner_item_activate_from_cursor(
+ bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops,
+ TreeElement *te, bool extend, bool recursive, const float mval[2])
{
-
if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
TreeStoreElem *tselem = TREESTORE(te);
bool openclose = false;
@@ -922,78 +997,49 @@ static bool do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, Sp
}
/* name and first icon */
else if (mval[0] > te->xs + UI_UNIT_X && mval[0] < te->xend) {
-
- /* always makes active object, except for some specific types.
- * Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want
- * to switch out of edit mode (see T48328 for details). */
- if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE)) {
- tree_element_set_active_object(C, scene, soops, te,
- (extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
- recursive && tselem->type == 0);
- }
-
- if (tselem->type == 0) { // the lib blocks
- /* editmode? */
- if (te->idcode == ID_SCE) {
- if (scene != (Scene *)tselem->id) {
- ED_screen_set_scene(C, CTX_wm_screen(C), (Scene *)tselem->id);
- }
- }
- else if (te->idcode == ID_GR) {
- Group *gr = (Group *)tselem->id;
- GroupObject *gob;
-
- if (extend) {
- int sel = BA_SELECT;
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if (gob->ob->flag & SELECT) {
- sel = BA_DESELECT;
- break;
- }
- }
-
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel);
- }
- }
- else {
- BKE_scene_base_deselect_all(scene);
-
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if ((gob->ob->flag & SELECT) == 0)
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT);
- }
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
- else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
- WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
- }
- else { // rest of types
- tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, false);
- }
-
- }
- else {
- tree_element_type_active(C, scene, soops, te, tselem,
- extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
- recursive);
- }
-
+ do_outliner_item_activate_tree_element(
+ C, scene, soops,
+ te, tselem,
+ extend, recursive);
return true;
}
}
for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_activate(C, scene, ar, soops, te, extend, recursive, mval)) {
+ if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, mval)) {
return true;
}
}
return false;
}
-int outliner_item_do_activate(bContext *C, int x, int y, bool extend, bool recursive)
+/**
+ * A version of #outliner_item_do_acticate_from_cursor that takes the tree element directly.
+ * and doesn't depend on the pointer position.
+ *
+ * This allows us to simulate clicking on an item without dealing with the mouse cursor.
+ */
+void outliner_item_do_activate_from_tree_element(
+ bContext *C, TreeElement *te, TreeStoreElem *tselem,
+ bool extend, bool recursive)
+{
+ Scene *scene = CTX_data_scene(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+
+ do_outliner_item_activate_tree_element(
+ C, scene, soops,
+ te, tselem,
+ extend, recursive);
+}
+
+/**
+ * Action to run when clicking in the outliner,
+ *
+ * May expend/collapse branches or activate items.
+ * */
+int outliner_item_do_activate_from_cursor(
+ bContext *C, const int mval[2],
+ bool extend, bool recursive)
{
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
@@ -1001,7 +1047,7 @@ int outliner_item_do_activate(bContext *C, int x, int y, bool extend, bool recur
TreeElement *te;
float fmval[2];
- UI_view2d_region_to_view(&ar->v2d, x, y, &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &fmval[0], &fmval[1]);
if (!ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF) &&
!(soops->flag & SO_HIDE_RESTRICTCOLS) &&
@@ -1011,7 +1057,9 @@ int outliner_item_do_activate(bContext *C, int x, int y, bool extend, bool recur
}
for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_activate(C, scene, ar, soops, te, extend, recursive, fmval)) break;
+ if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, fmval)) {
+ break;
+ }
}
if (te) {
@@ -1046,9 +1094,7 @@ static int outliner_item_activate(bContext *C, wmOperator *op, const wmEvent *ev
{
bool extend = RNA_boolean_get(op->ptr, "extend");
bool recursive = RNA_boolean_get(op->ptr, "recursive");
- int x = event->mval[0];
- int y = event->mval[1];
- return outliner_item_do_activate(C, x, y, extend, recursive);
+ return outliner_item_do_activate_from_cursor(C, event->mval, extend, recursive);
}
void OUTLINER_OT_item_activate(wmOperatorType *ot)
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 3321c2669d8..cf9deeaedf8 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -372,17 +372,14 @@ static void object_select_cb(
}
static void object_select_hierarchy_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *UNUSED(tselem), void *UNUSED(user_data))
+ bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *te,
+ TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
- /* From where do i get the x,y coordinate of the mouse event ? */
- wmWindow *win = CTX_wm_window(C);
- int x = win->eventstate->mval[0];
- int y = win->eventstate->mval[1];
- outliner_item_do_activate(C, x, y, true, true);
+ /* Don't extend because this toggles, which is nice for Ctrl-Click but not for a menu item.
+ * it's especially confusing when multiple items are selected since some toggle on/off. */
+ outliner_item_do_activate_from_tree_element(C, te, tselem, false, true);
}
-
static void object_deselect_cb(
bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te,
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 46f212e3679..258cbdfaffd 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -361,7 +361,7 @@ void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot)
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
- RNA_def_enum_funcs(prop, RNA_scene_itemf);
+ RNA_def_enum_funcs(prop, RNA_scene_without_active_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 160aa157189..bb7e2d75482 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -60,6 +60,7 @@
#include "BIF_glutil.h"
#include "GPU_basic_shader.h"
+#include "GPU_compositing.h"
#include "ED_anim_api.h"
#include "ED_gpencil.h"
@@ -908,7 +909,7 @@ void ED_sequencer_special_preview_clear(void)
ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int cfra, int frame_ofs, const char *viewname)
{
- SeqRenderData context;
+ SeqRenderData context = {0};
ImBuf *ibuf;
int rectx, recty;
float render_size;
@@ -935,6 +936,12 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int
rectx, recty, proxy_size,
&context);
context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
+ if (scene->r.seq_flag & R_SEQ_CAMERA_DOF) {
+ if (sseq->compositor == NULL) {
+ sseq->compositor = GPU_fx_compositor_create();
+ }
+ context.gpu_fx = sseq->compositor;
+ }
/* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled
* by Esc pressed somewhere in the past
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index f1d0f23f8af..6b50d3fecdf 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -60,6 +60,8 @@
#include "IMB_imbuf.h"
+#include "GPU_compositing.h"
+
#include "sequencer_intern.h" // own include
/**************************** common state *****************************/
@@ -218,6 +220,11 @@ static void sequencer_free(SpaceLink *sl)
if (scopes->histogram_ibuf)
IMB_freeImBuf(scopes->histogram_ibuf);
+
+ if (sseq->compositor != NULL) {
+ GPU_fx_compositor_destroy(sseq->compositor);
+ sseq->compositor = NULL;
+ }
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 56508ea989a..9e220f4b141 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -3286,14 +3286,16 @@ void ED_view3d_draw_setup_view(
*/
ImBuf *ED_view3d_draw_offscreen_imbuf(
Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey,
- unsigned int flag, bool draw_background,
- int alpha_mode, int samples, bool full_samples, const char *viewname,
+ unsigned int flag, unsigned int draw_flags,
+ int alpha_mode, int samples, const char *viewname,
/* output vars */
GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
{
RegionView3D *rv3d = ar->regiondata;
ImBuf *ibuf;
const bool draw_sky = (alpha_mode == R_ADDSKY);
+ const bool draw_background = (draw_flags & V3D_OFSDRAW_USE_BACKGROUND);
+ const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE);
/* view state */
GPUFXSettings fx_settings = v3d->fx_settings;
@@ -3309,7 +3311,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
if (own_ofs) {
/* bind */
- ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, err_out);
+ ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, err_out);
if (ofs == NULL) {
return NULL;
}
@@ -3354,7 +3356,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
}
}
- if ((samples && full_samples) == 0) {
+ if ((samples && use_full_sample) == 0) {
/* Single-pass render, common case */
ED_view3d_draw_offscreen(
scene, v3d, ar, sizex, sizey, NULL, winmat,
@@ -3454,8 +3456,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
*/
ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
Scene *scene, Object *camera, int width, int height,
- unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
- int alpha_mode, int samples, bool full_samples, const char *viewname,
+ unsigned int flag, unsigned int draw_flags, int drawtype,
+ int alpha_mode, int samples, const char *viewname,
GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
{
View3D v3d = {NULL};
@@ -3471,15 +3473,22 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
v3d.lay = scene->lay;
v3d.drawtype = drawtype;
v3d.flag2 = V3D_RENDER_OVERRIDE;
-
- if (use_gpencil)
- v3d.flag2 |= V3D_SHOW_GPENCIL;
- if (use_solid_tex)
+ if (draw_flags & V3D_OFSDRAW_USE_GPENCIL) {
+ v3d.flag2 |= V3D_SHOW_GPENCIL;
+ }
+ if (draw_flags & V3D_OFSDRAW_USE_SOLID_TEX) {
v3d.flag2 |= V3D_SOLID_TEX;
-
- if (draw_background)
+ }
+ if (draw_flags & V3D_OFSDRAW_USE_BACKGROUND) {
v3d.flag3 |= V3D_SHOW_WORLD;
+ }
+ if (draw_flags & V3D_OFSDRAW_USE_CAMERA_DOF) {
+ if (camera->type == OB_CAMERA) {
+ v3d.fx_settings.dof = &((Camera *)camera->data)->gpu_dof;
+ v3d.fx_settings.fx_flag |= GPU_FX_FLAG_DOF;
+ }
+ }
rv3d.persp = RV3D_CAMOB;
@@ -3507,9 +3516,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
return ED_view3d_draw_offscreen_imbuf(
- scene, &v3d, &ar, width, height, flag,
- draw_background, alpha_mode, samples, full_samples, viewname,
- fx, ofs, err_out);
+ scene, &v3d, &ar, width, height, flag, draw_flags,
+ alpha_mode, samples, viewname, fx, ofs, err_out);
}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 67597729d15..05cf552e5cc 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -70,8 +70,6 @@
#include "BKE_paint.h"
#include "BKE_editmesh.h"
#include "BKE_tracking.h"
-#include "BKE_utildefines.h"
-
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -726,7 +724,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv,
if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
{
- BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
+ SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
}
}
static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
@@ -1672,7 +1670,7 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con
BoxSelectUserData *data = userData;
if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
- BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
+ SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
}
}
static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
@@ -2498,7 +2496,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv,
CircleSelectUserData *data = userData;
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
- BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
+ SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
}
}
static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 179b68dd270..277e01d1e2b 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -82,7 +82,6 @@
#include "BKE_editmesh.h"
#include "BKE_tracking.h"
#include "BKE_mask.h"
-#include "BKE_utildefines.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -1208,7 +1207,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id)) &&
RNA_property_is_set(op->ptr, prop))
{
- BKE_BIT_TEST_SET(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM);
+ SET_FLAG_FROM_TEST(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM);
}
}
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index c369068fe05..d69588e91c6 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -3761,7 +3761,7 @@ static void UV_OT_hide(wmOperatorType *ot)
/****************** reveal operator ******************/
-static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+static int uv_reveal_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
Object *obedit = CTX_data_edit_object(C);
@@ -3777,12 +3777,14 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ const bool select = RNA_boolean_get(op->ptr, "select");
+
/* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and
* confuse our checks on selected verts. */
/* call the mesh function if we are in mesh sync sel */
if (ts->uv_flag & UV_SYNC_SELECTION) {
- EDBM_mesh_reveal(em);
+ EDBM_mesh_reveal(em, select);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -3794,7 +3796,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag |= MLOOPUV_VERTSEL;
+ SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
}
/* BM_face_select_set(em->bm, efa, true); */
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -3815,7 +3817,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
if (!totsel) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag |= MLOOPUV_VERTSEL;
+ SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
}
/* BM_face_select_set(em->bm, efa, true); */
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -3830,7 +3832,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag |= MLOOPUV_VERTSEL;
+ SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
}
}
/* BM_face_select_set(em->bm, efa, true); */
@@ -3846,7 +3848,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag |= MLOOPUV_VERTSEL;
+ SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
}
/* BM_face_select_set(em->bm, efa, true); */
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -3860,7 +3862,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->flag |= MLOOPUV_VERTSEL;
+ SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL);
}
}
/* BM_face_select_set(em->bm, efa, true); */
@@ -3888,6 +3890,8 @@ static void UV_OT_reveal(wmOperatorType *ot)
/* api callbacks */
ot->exec = uv_reveal_exec;
ot->poll = ED_operator_uvedit;
+
+ RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
/******************** set 3d cursor operator ********************/
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index b639a493b02..bc38a1cd3bb 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -868,46 +868,89 @@ void ED_uvedit_live_unwrap(Scene *scene, Object *obedit)
#define POLAR_ZX 0
#define POLAR_ZY 1
-static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result,
- Object *ob, BMEditMesh *em)
+static void uv_map_transform_calc_bounds(BMEditMesh *em, float r_min[3], float r_max[3])
{
- const int around = (v3d) ? v3d->around : V3D_AROUND_CENTER_BOUNDS;
+ BMFace *efa;
+ BMIter iter;
+ INIT_MINMAX(r_min, r_max);
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_face_calc_bounds_expand(efa, r_min, r_max);
+ }
+ }
+}
+
+static void uv_map_transform_calc_center_median(BMEditMesh *em, float r_center[3])
+{
+ BMFace *efa;
+ BMIter iter;
+ uint center_accum_num = 0;
+ zero_v3(r_center);
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ float center[3];
+ BM_face_calc_center_mean(efa, center);
+ add_v3_v3(r_center, center);
+ center_accum_num += 1;
+ }
+ }
+ mul_v3_fl(r_center, 1.0f / (float)center_accum_num);
+}
+static void uv_map_transform_center(
+ Scene *scene, View3D *v3d, Object *ob, BMEditMesh *em,
+ float r_center[3],
+ float r_bounds[2][3])
+{
/* only operates on the edit object - this is all that's needed now */
+ const int around = (v3d) ? v3d->around : V3D_AROUND_CENTER_BOUNDS;
+
+ float bounds[2][3];
+ INIT_MINMAX(bounds[0], bounds[1]);
+ bool is_minmax_set = false;
switch (around) {
case V3D_AROUND_CENTER_BOUNDS: /* bounding box center */
{
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- float min[3], max[3];
-
- INIT_MINMAX(min, max);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- minmax_v3v3_v3(min, max, l->v->co);
- }
- }
- }
- mid_v3_v3v3(result, min, max);
+ uv_map_transform_calc_bounds(em, bounds[0], bounds[1]);
+ is_minmax_set = true;
+ mid_v3_v3v3(r_center, bounds[0], bounds[1]);
+ break;
+ }
+ case V3D_AROUND_CENTER_MEAN:
+ {
+ uv_map_transform_calc_center_median(em, r_center);
break;
}
case V3D_AROUND_CURSOR: /* cursor center */
{
- const float *curs = ED_view3d_cursor3d_get(scene, v3d);
- /* shift to objects world */
- sub_v3_v3v3(result, curs, ob->obmat[3]);
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_v3_m4v3(r_center, ob->imat, ED_view3d_cursor3d_get(scene, v3d));
break;
}
+ case V3D_AROUND_ACTIVE:
+ {
+ BMEditSelection ese;
+ if (BM_select_history_active_get(em->bm, &ese)) {
+ BM_editselection_center(&ese, r_center);
+ break;
+ }
+ ATTR_FALLTHROUGH;
+ }
case V3D_AROUND_LOCAL_ORIGINS: /* object center */
- case V3D_AROUND_CENTER_MEAN: /* multiple objects centers, only one object here*/
default:
- zero_v3(result);
+ zero_v3(r_center);
break;
}
+
+ /* if this is passed, always set! */
+ if (r_bounds) {
+ if (!is_minmax_set) {
+ uv_map_transform_calc_bounds(em, bounds[0], bounds[1]);
+ }
+ copy_v3_v3(r_bounds[0], bounds[0]);
+ copy_v3_v3(r_bounds[1], bounds[1]);
+ }
}
static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Object *ob,
@@ -958,13 +1001,10 @@ static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Objec
mul_m4_series(result, rotup, rotside, viewmatrix, rotobj);
}
-static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float rotmat[4][4])
+static void uv_map_transform(bContext *C, wmOperator *op, float rotmat[4][4])
{
/* context checks are messy here, making it work in both 3d view and uv editor */
- Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
/* common operator properties */
int align = RNA_enum_get(op->ptr, "align");
@@ -972,8 +1012,6 @@ static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float
float radius = RNA_struct_find_property(op->ptr, "radius") ? RNA_float_get(op->ptr, "radius") : 1.0f;
float upangledeg, sideangledeg;
- uv_map_transform_center(scene, v3d, center, obedit, em);
-
if (direction == VIEW_ON_EQUATOR) {
upangledeg = 90.0f;
sideangledeg = 0.0f;
@@ -1476,6 +1514,7 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMFace *efa;
BMLoop *l;
@@ -1493,7 +1532,8 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- uv_map_transform(C, op, center, rotmat);
+ uv_map_transform(C, op, rotmat);
+ uv_map_transform_center(scene, v3d, obedit, em, center, NULL);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
@@ -1555,6 +1595,7 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMFace *efa;
BMLoop *l;
@@ -1572,12 +1613,13 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- uv_map_transform(C, op, center, rotmat);
+ uv_map_transform(C, op, rotmat);
+ uv_map_transform_center(scene, v3d, obedit, em, center, NULL);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
continue;
-
+
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -1616,68 +1658,79 @@ void UV_OT_cylinder_project(wmOperatorType *ot)
/******************* Cube Project operator ****************/
-void ED_uvedit_unwrap_cube_project(Object *ob, BMesh *bm, float cube_size, bool use_select)
+void ED_uvedit_unwrap_cube_project(BMesh *bm, float cube_size, bool use_select, const float center[3])
{
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
/* MTexPoly *tf; */ /* UNUSED */
MLoopUV *luv;
- float *loc, dx, dy;
+ float loc[3];
int cox, coy;
int cd_loop_uv_offset;
cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- loc = ob->obmat[3];
+ if (center) {
+ copy_v3_v3(loc, center);
+ }
+ else {
+ zero_v3(loc);
+ }
/* choose x,y,z axis for projection depending on the largest normal
* component, but clusters all together around the center of map. */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- int first = 1;
-
/* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT))
continue;
axis_dominant_v3(&cox, &coy, efa->no);
- dx = dy = 0;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- luv->uv[0] = 0.5f + 0.5f * cube_size * (loc[cox] + l->v->co[cox]);
- luv->uv[1] = 0.5f + 0.5f * cube_size * (loc[coy] + l->v->co[coy]);
-
- if (first) {
- dx = floor(luv->uv[0]);
- dy = floor(luv->uv[1]);
- first = 0;
- }
-
-
- luv->uv[0] -= dx;
- luv->uv[1] -= dy;
+ luv->uv[0] = 0.5f + 0.5f * cube_size * (l->v->co[cox] - loc[cox]);
+ luv->uv[1] = 0.5f + 0.5f * cube_size * (l->v->co[coy] - loc[coy]);
}
}
-
}
static int cube_project_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- float cube_size = RNA_float_get(op->ptr, "cube_size");
+ PropertyRNA *prop_cube_size = RNA_struct_find_property(op->ptr, "cube_size");
+ float cube_size = RNA_property_float_get(op->ptr, prop_cube_size);
+ float center[3];
+ float bounds[2][3];
+ float (*bounds_buf)[3] = NULL;
/* add uvs if they don't exist yet */
if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
return OPERATOR_CANCELLED;
}
- ED_uvedit_unwrap_cube_project(obedit, em->bm, cube_size, true);
+ if (!RNA_property_is_set(op->ptr, prop_cube_size)) {
+ bounds_buf = bounds;
+ }
+
+ uv_map_transform_center(scene, v3d, obedit, em, center, bounds_buf);
+
+ /* calculate based on bounds */
+ if (bounds_buf) {
+ float dims[3];
+ sub_v3_v3v3(dims, bounds[1], bounds[0]);
+ cube_size = max_fff(UNPACK3(dims));
+ cube_size = cube_size ? 2.0f / cube_size : 1.0f;
+ RNA_property_float_set(op->ptr, prop_cube_size, cube_size);
+ }
+
+ ED_uvedit_unwrap_cube_project(em->bm, cube_size, true, center);
+
uv_map_clip_correct(scene, obedit, em, op);
DAG_id_tag_update(obedit->data, 0);
diff --git a/source/blender/freestyle/intern/system/StringUtils.h b/source/blender/freestyle/intern/system/StringUtils.h
index e11798762e4..10748c45c19 100644
--- a/source/blender/freestyle/intern/system/StringUtils.h
+++ b/source/blender/freestyle/intern/system/StringUtils.h
@@ -35,7 +35,6 @@
#include <vector>
extern "C" {
-#include "BKE_utildefines.h"
#include "BLI_string.h"
#include "BLI_path_util.h"
}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 4ac69119a6c..0a63fc216a0 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -2971,7 +2971,10 @@ float calc_gradient(vec3 p, int gradient_type)
return atan(y, x) / (M_PI * 2) + 0.5;
}
else {
- float r = max(1.0 - sqrt(x * x + y * y + z * z), 0.0);
+ /* Bias a little bit for the case where p is a unit length vector,
+ * to get exactly zero instead of a small random value depending
+ * on float precision. */
+ float r = max(0.999999 - sqrt(x * x + y * y + z * z), 0.0);
if (gradient_type == 5) { /* quadratic sphere */
return r * r;
}
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index e1b3abcf2f6..009258079ee 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -843,9 +843,9 @@ static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, int
}
static void index_rebuild_ffmpeg_proc_decoded_frame(
- FFmpegIndexBuilderContext *context,
- AVPacket * curr_packet,
- AVFrame *in_frame)
+ FFmpegIndexBuilderContext *context,
+ AVPacket *curr_packet,
+ AVFrame *in_frame)
{
int i;
unsigned long long s_pos = context->seek_pos;
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 451869415e7..ca534e3e2a8 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -414,11 +414,13 @@ static bool imb_save_openexr_half(
frameBuffer.insert("R", Slice(HALF, (char *) &to->r, xstride, ystride));
frameBuffer.insert("G", Slice(HALF, (char *) &to->g, xstride, ystride));
frameBuffer.insert("B", Slice(HALF, (char *) &to->b, xstride, ystride));
- if (is_alpha)
+ if (is_alpha) {
frameBuffer.insert("A", Slice(HALF, (char *) &to->a, xstride, ystride));
- if (is_zbuf)
+ }
+ if (is_zbuf) {
frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)(ibuf->zbuf_float + (height - 1) * width),
- sizeof(float), sizeof(float) * -width));
+ sizeof(float), sizeof(float) * -width));
+ }
if (ibuf->rect_float) {
float *from;
@@ -509,11 +511,13 @@ static bool imb_save_openexr_float(
frameBuffer.insert("R", Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride));
frameBuffer.insert("G", Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride));
frameBuffer.insert("B", Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride));
- if (is_alpha)
+ if (is_alpha) {
frameBuffer.insert("A", Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride));
- if (is_zbuf)
+ }
+ if (is_zbuf) {
frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *) (ibuf->zbuf_float + (height - 1) * width),
- sizeof(float), sizeof(float) * -width));
+ sizeof(float), sizeof(float) * -width));
+ }
file.setFrameBuffer(frameBuffer);
file.writePixels(height);
@@ -1125,7 +1129,7 @@ void IMB_exr_read_channels(void *handle)
ExrChannel *echan;
for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
- if(echan->m->part_number != i) {
+ if (echan->m->part_number != i) {
continue;
}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 5250749fce3..923df70dd4d 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -339,7 +339,7 @@ enum {
* Also used internally in readfile.c to mark datablocks needing do_versions. */
LIB_TAG_NEW = 1 << 8,
/* RESET_BEFORE_USE free test flag.
- * TODO make it a RESET_AFTER_USE too. */
+ * TODO make it a RESET_AFTER_USE too. */
LIB_TAG_DOIT = 1 << 10,
/* RESET_AFTER_USE tag existing data before linking so we know what is new. */
LIB_TAG_PRE_EXISTING = 1 << 11,
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index b9f19a36072..90815b95d24 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1744,9 +1744,12 @@ typedef struct Scene {
#define R_USE_WS_SHADING 0x8000000 /* use world space interpretation of lighting data */
/* seq_flag */
-// #define R_SEQ_GL_PREV 1 // UNUSED, we just use setting from seq_prev_type now.
-// #define R_SEQ_GL_REND 2 // UNUSED, opengl render has its own operator now.
-#define R_SEQ_SOLID_TEX 4
+enum {
+ // R_SEQ_GL_PREV = (1 << 1), // UNUSED, we just use setting from seq_prev_type now.
+ // R_SEQ_GL_REND = (1 << 2), // UNUSED, opengl render has its own operator now.
+ R_SEQ_SOLID_TEX = (1 << 3),
+ R_SEQ_CAMERA_DOF = (1 << 4),
+};
/* displaymode */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index a0f77d61d1d..015583d898c 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -512,6 +512,9 @@ typedef struct SpaceSeq {
char multiview_eye; /* multiview current eye - for internal use */
char pad2[7];
+
+ struct GPUFX *compositor;
+ void *pad3;
} SpaceSeq;
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 2cea8715a65..17e30de4509 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -978,7 +978,7 @@ static int make_structDNA(const char *baseDirectory, FILE *file, FILE *file_offs
char str[SDNA_MAX_FILENAME_LENGTH], *cp;
int firststruct;
- if (debugSDNA > -1) {
+ if (debugSDNA > 0) {
fflush(stdout);
printf("Running makesdna at debug level %d\n", debugSDNA);
}
@@ -1074,7 +1074,7 @@ static int make_structDNA(const char *baseDirectory, FILE *file, FILE *file_offs
/* file writing */
- if (debugSDNA > -1) printf("Writing file ... ");
+ if (debugSDNA > 0) printf("Writing file ... ");
if (nr_names == 0 || nr_structs == 0) {
/* pass */
@@ -1184,7 +1184,7 @@ static int make_structDNA(const char *baseDirectory, FILE *file, FILE *file_offs
MEM_freeN(typelens_64);
MEM_freeN(structs);
- if (debugSDNA > -1) printf("done.\n");
+ if (debugSDNA > 0) printf("done.\n");
return(0);
}
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index b4b8dd7806e..0f4e20a02ab 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -237,6 +237,7 @@ const EnumPropertyItem *RNA_group_local_itemf(struct bContext *C, struct Pointer
const EnumPropertyItem *RNA_image_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
const EnumPropertyItem *RNA_image_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
const EnumPropertyItem *RNA_scene_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
+const EnumPropertyItem *RNA_scene_without_active_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
const EnumPropertyItem *RNA_scene_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
const EnumPropertyItem *RNA_movieclip_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
const EnumPropertyItem *RNA_movieclip_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 2c558e56412..ff081a56b61 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -46,6 +46,14 @@
# endif
#endif
+/**
+ * Variable to control debug output of makesrna.
+ * debugSRNA:
+ * - 0 = no output, except errors
+ * - 1 = detail actions
+ */
+static int debugSRNA = 0;
+
/* stub for BLI_abort() */
#ifndef NDEBUG
void BLI_system_backtrace(FILE *fp)
@@ -62,7 +70,9 @@ void BLI_system_backtrace(FILE *fp)
static int file_older(const char *file1, const char *file2)
{
struct stat st1, st2;
- /* printf("compare: %s %s\n", file1, file2); */
+ if (debugSRNA > 0) {
+ printf("compare: %s %s\n", file1, file2);
+ }
if (stat(file1, &st1)) return 0;
if (stat(file2, &st2)) return 0;
@@ -4134,7 +4144,9 @@ int main(int argc, char **argv)
return_status = 1;
}
else {
- fprintf(stderr, "Running makesrna\n");
+ if (debugSRNA > 0) {
+ fprintf(stderr, "Running makesrna\n");
+ }
makesrna_path = argv[0];
return_status = rna_preprocess(argv[1]);
}
diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c
index 0ae07874853..2ba067629a9 100644
--- a/source/blender/makesrna/intern/rna_animviz.c
+++ b/source/blender/makesrna/intern/rna_animviz.c
@@ -174,6 +174,7 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Bone Heads",
"For PoseBone paths, use the bone head location when calculating this path");
+ /* FIXME: Motion Paths are not currently editable... */
prop = RNA_def_property(srna, "is_modified", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_EDIT);
RNA_def_property_ui_text(prop, "Edit Path", "Path is being edited");
@@ -364,6 +365,12 @@ static void rna_def_animviz_paths(BlenderRNA *brna)
"(only for 'Around Current Frame' Onion-skinning method)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */
+
+ /* Readonly Property - Do any motion paths exist/need updating? (Mainly for bone paths) */
+ prop = RNA_def_property(srna, "has_motion_paths", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "path_bakeflag", MOTIONPATH_BAKE_HAS_PATHS);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* NOTE: This is really an internal state var for convenience, so don't allow edits! */
+ RNA_def_property_ui_text(prop, "Has Motion Paths", "Are there any bone paths that will need updating (read-only)");
}
/* --- */
diff --git a/source/blender/makesrna/intern/rna_cachefile.c b/source/blender/makesrna/intern/rna_cachefile.c
index 81b0c539e33..73928d377f1 100644
--- a/source/blender/makesrna/intern/rna_cachefile.c
+++ b/source/blender/makesrna/intern/rna_cachefile.c
@@ -34,11 +34,11 @@
#ifdef RNA_RUNTIME
+#include "BLI_string.h"
+
#include "BKE_cachefile.h"
#include "BKE_depsgraph.h"
-#include "BLI_string.h"
-
#include "DEG_depsgraph.h"
#include "WM_api.h"
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 68cd2902acd..981ae75e7c5 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -39,8 +39,11 @@
#ifdef RNA_RUNTIME
#include "BKE_camera.h"
-#include "BKE_object.h"
#include "BKE_depsgraph.h"
+#include "BKE_object.h"
+#include "BKE_sequencer.h"
+
+#include "WM_api.h"
static float rna_Camera_angle_get(PointerRNA *ptr)
{
@@ -94,6 +97,14 @@ static void rna_Camera_dependency_update(Main *bmain, Scene *UNUSED(scene), Poin
DAG_id_tag_update(&camera->id, 0);
}
+static void rna_Camera_dof_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+ /* TODO(sergey): Can be more selective here. */
+ BKE_sequencer_cache_cleanup();
+ BKE_sequencer_preprocessed_cache_cleanup();
+ WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
+}
+
#else
static void rna_def_camera_stereo_data(BlenderRNA *brna)
@@ -323,7 +334,7 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0f, 5000.0f, 1, 2);
RNA_def_property_ui_text(prop, "DOF Distance", "Distance to the focus point for depth of field");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update");
/* Stereo Settings */
prop = RNA_def_property(srna, "stereo", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index cb5d731efc5..cb71cf756ec 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -175,7 +175,7 @@ static void rna_ImageUser_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *
BKE_image_user_frame_calc(iuser, scene->r.cfra, 0);
- if(ptr->id.data) {
+ if (ptr->id.data) {
/* Update material or texture for render preview. */
DAG_id_tag_update(ptr->id.data, 0);
}
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index f4f4685d1bf..c266e0e7f31 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -52,13 +52,13 @@
#ifdef RNA_RUNTIME
+#include "BLI_math.h"
+
#include "DNA_movieclip_types.h"
#include "BKE_depsgraph.h"
#include "BKE_mask.h"
-#include "BLI_math.h"
-
#include "RNA_access.h"
#include "WM_api.h"
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 41758758178..18fd4c64242 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -577,99 +577,100 @@ static void rna_MeshColor_color1_get(PointerRNA *ptr, float *values)
{
MCol *mcol = (MCol *)ptr->data;
- values[2] = (&mcol[0].r)[0] / 255.0f;
- values[1] = (&mcol[0].r)[1] / 255.0f;
- values[0] = (&mcol[0].r)[2] / 255.0f;
+ values[3] = mcol[0].a / 255.0f;
+ values[2] = mcol[0].r / 255.0f;
+ values[1] = mcol[0].g / 255.0f;
+ values[0] = mcol[0].b / 255.0f;
}
static void rna_MeshColor_color1_set(PointerRNA *ptr, const float *values)
{
MCol *mcol = (MCol *)ptr->data;
- (&mcol[0].r)[2] = round_fl_to_uchar_clamp(values[0] * 255.0f);
- (&mcol[0].r)[1] = round_fl_to_uchar_clamp(values[1] * 255.0f);
- (&mcol[0].r)[0] = round_fl_to_uchar_clamp(values[2] * 255.0f);
- (&mcol[0].r)[3] = round_fl_to_uchar_clamp(values[3] * 255.0f);
+ mcol[0].a = round_fl_to_uchar_clamp(values[3] * 255.0f);
+ mcol[0].r = round_fl_to_uchar_clamp(values[2] * 255.0f);
+ mcol[0].g = round_fl_to_uchar_clamp(values[1] * 255.0f);
+ mcol[0].b = round_fl_to_uchar_clamp(values[0] * 255.0f);
}
static void rna_MeshColor_color2_get(PointerRNA *ptr, float *values)
{
MCol *mcol = (MCol *)ptr->data;
- values[3] = (&mcol[1].r)[3] / 255.0f;
- values[2] = (&mcol[1].r)[0] / 255.0f;
- values[1] = (&mcol[1].r)[1] / 255.0f;
- values[0] = (&mcol[1].r)[2] / 255.0f;
+ values[3] = mcol[1].a / 255.0f;
+ values[2] = mcol[1].r / 255.0f;
+ values[1] = mcol[1].g / 255.0f;
+ values[0] = mcol[1].b / 255.0f;
}
static void rna_MeshColor_color2_set(PointerRNA *ptr, const float *values)
{
MCol *mcol = (MCol *)ptr->data;
- (&mcol[1].r)[2] = round_fl_to_uchar_clamp(values[0] * 255.0f);
- (&mcol[1].r)[1] = round_fl_to_uchar_clamp(values[1] * 255.0f);
- (&mcol[1].r)[0] = round_fl_to_uchar_clamp(values[2] * 255.0f);
- (&mcol[1].r)[3] = round_fl_to_uchar_clamp(values[3] * 255.0f);
+ mcol[1].a = round_fl_to_uchar_clamp(values[3] * 255.0f);
+ mcol[1].r = round_fl_to_uchar_clamp(values[2] * 255.0f);
+ mcol[1].g = round_fl_to_uchar_clamp(values[1] * 255.0f);
+ mcol[1].b = round_fl_to_uchar_clamp(values[0] * 255.0f);
}
static void rna_MeshColor_color3_get(PointerRNA *ptr, float *values)
{
MCol *mcol = (MCol *)ptr->data;
- values[3] = (&mcol[2].r)[3] / 255.0f;
- values[2] = (&mcol[2].r)[0] / 255.0f;
- values[1] = (&mcol[2].r)[1] / 255.0f;
- values[0] = (&mcol[2].r)[2] / 255.0f;
+ values[3] = mcol[2].a / 255.0f;
+ values[2] = mcol[2].r / 255.0f;
+ values[1] = mcol[2].g / 255.0f;
+ values[0] = mcol[2].b / 255.0f;
}
static void rna_MeshColor_color3_set(PointerRNA *ptr, const float *values)
{
MCol *mcol = (MCol *)ptr->data;
- (&mcol[2].r)[2] = round_fl_to_uchar_clamp(values[0] * 255.0f);
- (&mcol[2].r)[1] = round_fl_to_uchar_clamp(values[1] * 255.0f);
- (&mcol[2].r)[0] = round_fl_to_uchar_clamp(values[2] * 255.0f);
- (&mcol[2].r)[3] = round_fl_to_uchar_clamp(values[3] * 255.0f);
+ mcol[2].a = round_fl_to_uchar_clamp(values[3] * 255.0f);
+ mcol[2].r = round_fl_to_uchar_clamp(values[2] * 255.0f);
+ mcol[2].g = round_fl_to_uchar_clamp(values[1] * 255.0f);
+ mcol[2].b = round_fl_to_uchar_clamp(values[0] * 255.0f);
}
static void rna_MeshColor_color4_get(PointerRNA *ptr, float *values)
{
MCol *mcol = (MCol *)ptr->data;
- values[2] = (&mcol[3].r)[0] / 255.0f;
- values[1] = (&mcol[3].r)[1] / 255.0f;
- values[0] = (&mcol[3].r)[2] / 255.0f;
- values[3] = (&mcol[3].r)[3] / 255.0f;
+ values[3] = mcol[3].a / 255.0f;
+ values[2] = mcol[3].r / 255.0f;
+ values[1] = mcol[3].g / 255.0f;
+ values[0] = mcol[3].b / 255.0f;
}
static void rna_MeshColor_color4_set(PointerRNA *ptr, const float *values)
{
MCol *mcol = (MCol *)ptr->data;
- (&mcol[3].r)[2] = round_fl_to_uchar_clamp(values[0] * 255.0f);
- (&mcol[3].r)[1] = round_fl_to_uchar_clamp(values[1] * 255.0f);
- (&mcol[3].r)[0] = round_fl_to_uchar_clamp(values[2] * 255.0f);
- (&mcol[3].r)[3] = round_fl_to_uchar_clamp(values[3] * 255.0f);
+ mcol[3].a = round_fl_to_uchar_clamp(values[3] * 255.0f);
+ mcol[3].r = round_fl_to_uchar_clamp(values[2] * 255.0f);
+ mcol[3].g = round_fl_to_uchar_clamp(values[1] * 255.0f);
+ mcol[3].b = round_fl_to_uchar_clamp(values[0] * 255.0f);
}
static void rna_MeshLoopColor_color_get(PointerRNA *ptr, float *values)
{
- MLoopCol *mcol = (MLoopCol *)ptr->data;
+ MLoopCol *mlcol = (MLoopCol *)ptr->data;
- values[0] = (&mcol->r)[0] / 255.0f;
- values[1] = (&mcol->r)[1] / 255.0f;
- values[2] = (&mcol->r)[2] / 255.0f;
- values[3] = (&mcol->r)[3] / 255.0f;
+ values[0] = mlcol->r / 255.0f;
+ values[1] = mlcol->g / 255.0f;
+ values[2] = mlcol->b / 255.0f;
+ values[3] = mlcol->a / 255.0f;
}
static void rna_MeshLoopColor_color_set(PointerRNA *ptr, const float *values)
{
- MLoopCol *mcol = (MLoopCol *)ptr->data;
+ MLoopCol *mlcol = (MLoopCol *)ptr->data;
- (&mcol->r)[0] = round_fl_to_uchar_clamp(values[0] * 255.0f);
- (&mcol->r)[1] = round_fl_to_uchar_clamp(values[1] * 255.0f);
- (&mcol->r)[2] = round_fl_to_uchar_clamp(values[2] * 255.0f);
- (&mcol->r)[3] = round_fl_to_uchar_clamp(values[3] * 255.0f);
+ mlcol->r = round_fl_to_uchar_clamp(values[0] * 255.0f);
+ mlcol->g = round_fl_to_uchar_clamp(values[1] * 255.0f);
+ mlcol->b = round_fl_to_uchar_clamp(values[2] * 255.0f);
+ mlcol->a = round_fl_to_uchar_clamp(values[3] * 255.0f);
}
static int rna_Mesh_texspace_editable(PointerRNA *ptr, const char **UNUSED(r_info))
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 7fc0ffeb747..53fe84707d1 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -675,6 +675,7 @@ static void rna_Particle_reset_dependency(Main *bmain, Scene *scene, PointerRNA
static void rna_Particle_change_type(Main *bmain, Scene *scene, PointerRNA *ptr)
{
particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET | PSYS_RECALC_TYPE);
+ DAG_relations_tag_update(bmain);
}
static void rna_Particle_change_physics(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -757,7 +758,7 @@ static void rna_Particle_target_redo(Main *UNUSED(bmain), Scene *UNUSED(scene),
}
}
-static void rna_Particle_hair_dynamics(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Particle_hair_dynamics_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Object *ob = (Object *)ptr->id.data;
ParticleSystem *psys = (ParticleSystem *)ptr->data;
@@ -769,10 +770,12 @@ static void rna_Particle_hair_dynamics(Main *bmain, Scene *scene, PointerRNA *pt
psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
rna_Particle_redo(bmain, scene, ptr);
}
- else
+ else {
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
+ }
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DAG_relations_tag_update(bmain);
}
static PointerRNA rna_particle_settings_get(PointerRNA *ptr)
{
@@ -3292,7 +3295,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_hair_dynamics", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_HAIR_DYNAMICS);
RNA_def_property_ui_text(prop, "Hair Dynamics", "Enable hair dynamics using cloth simulation");
- RNA_def_property_update(prop, 0, "rna_Particle_hair_dynamics");
+ RNA_def_property_update(prop, 0, "rna_Particle_hair_dynamics_update");
prop = RNA_def_property(srna, "cloth", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "clmd");
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index bc56ff251e8..fda92ff7c0d 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -990,6 +990,11 @@ static char *rna_RenderSettings_path(PointerRNA *UNUSED(ptr))
return BLI_sprintfN("render");
}
+static char *rna_BakeSettings_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_sprintfN("render.bake");
+}
+
static char *rna_ImageFormatSettings_path(PointerRNA *ptr)
{
ImageFormatData *imf = (ImageFormatData *)ptr->data;
@@ -2128,6 +2133,14 @@ static void rna_GPUDOFSettings_blades_set(PointerRNA *ptr, const int value)
dofsettings->num_blades = value;
}
+static void rna_GPUDOFSettings_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+ /* TODO(sergey): Can be more selective here. */
+ BKE_sequencer_cache_cleanup();
+ BKE_sequencer_preprocessed_cache_cleanup();
+ WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
+}
+
static void rna_Stereo3dFormat_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
ID *id = ptr->id.data;
@@ -4244,6 +4257,7 @@ static void rna_def_bake_data(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "BakeData");
RNA_def_struct_nested(brna, srna, "RenderSettings");
RNA_def_struct_ui_text(srna, "Bake Data", "Bake data for a Scene data-block");
+ RNA_def_struct_path_func(srna, "rna_BakeSettings_path");
prop = RNA_def_property(srna, "cage_object", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "cage");
@@ -4903,37 +4917,37 @@ static void rna_def_gpu_dof_fx(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Focus distance", "Viewport depth of field focus distance");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0f, 5000.0f, 1, 2);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
prop = RNA_def_property(srna, "focal_length", PROP_FLOAT, PROP_DISTANCE_CAMERA);
RNA_def_property_ui_text(prop, "Focal Length", "Focal length for dof effect");
RNA_def_property_range(prop, 1.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
prop = RNA_def_property(srna, "sensor", PROP_FLOAT, PROP_DISTANCE_CAMERA);
RNA_def_property_ui_text(prop, "Sensor", "Size of sensor");
RNA_def_property_range(prop, 1.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
prop = RNA_def_property(srna, "fstop", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "F-stop", "F-stop for dof effect");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
prop = RNA_def_property(srna, "blades", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "num_blades");
RNA_def_property_ui_text(prop, "Blades", "Blades for dof effect");
RNA_def_property_range(prop, 0, 16);
RNA_def_property_int_funcs(prop, NULL, "rna_GPUDOFSettings_blades_set", NULL);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
prop = RNA_def_property(srna, "use_high_quality", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "high_quality", 1);
RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
prop = RNA_def_property(srna, "is_hq_supported", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_gpu_is_hq_supported_get", NULL);
@@ -5461,7 +5475,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
};
static const EnumPropertyItem ffmpeg_crf_items[] = {
- {FFM_CRF_NONE, "NONE", 0, "None; use constant bit-rate",
+ {FFM_CRF_NONE, "NONE", 0, "None; use custom bitrate",
"Use constant bit rate, rather than constant output quality"},
{FFM_CRF_LOSSLESS, "LOSSLESS", 0, "Lossless", ""},
{FFM_CRF_PERC_LOSSLESS, "PERC_LOSSLESS", 0, "Perceptually lossless", ""},
@@ -6460,6 +6474,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Textured Solid", "Draw face-assigned textures in solid draw method");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update");
+ prop = RNA_def_property(srna, "use_sequencer_gl_dof", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_CAMERA_DOF);
+ RNA_def_property_ui_text(prop, "Depth of Field", "Use depth of field using the values from scene strip active camera");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update");
+
/* layers */
prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "layers", NULL);
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 28bd0f1b07f..9da27233e0e 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -27,6 +27,8 @@
#include <stdlib.h>
+#include "BLI_utildefines.h"
+
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -46,7 +48,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "BLI_utildefines.h"
#include "bmesh.h"
static const EnumPropertyItem particle_edit_hair_brush_items[] = {
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index 8e54c708c05..77d7f7833c6 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -29,6 +29,9 @@
#include <stdlib.h>
#include <limits.h>
+#include "BLI_sys_types.h"
+#include "BLI_threads.h"
+
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -38,8 +41,6 @@
#include "BKE_smoke.h"
#include "BKE_pointcache.h"
-#include "BLI_threads.h"
-
#include "DNA_modifier_types.h"
#include "DNA_object_force.h"
#include "DNA_object_types.h"
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 40d1cfdfcb0..b4cdb158526 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -337,7 +337,9 @@ static void ntree_shader_link_builtin_group_normal(
* some internal re-linking in order to avoid cycles.
*/
bNode *group_output_node = ntreeFindType(group_ntree, NODE_GROUP_OUTPUT);
- BLI_assert(group_output_node != NULL);
+ if (group_output_node == NULL) {
+ return;
+ }
bNodeSocket *group_output_node_displacement_socket =
nodeFindSocket(group_output_node,
SOCK_IN,
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c
index 006bd0cc8bb..8748c884a25 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c
@@ -66,7 +66,7 @@ static void node_shader_free_tex_pointdensity(bNode *node)
MEM_freeN(point_density);
}
-static void node_shader_copy_tex_pointdensity(bNodeTree * UNUSED(dest_ntree),
+static void node_shader_copy_tex_pointdensity(bNodeTree *UNUSED(dest_ntree),
bNode *dest_node,
bNode *src_node)
{
diff --git a/source/blender/physics/intern/eigen_utils.h b/source/blender/physics/intern/eigen_utils.h
index e4a4f306aeb..8a5a9dbf5e9 100644
--- a/source/blender/physics/intern/eigen_utils.h
+++ b/source/blender/physics/intern/eigen_utils.h
@@ -32,7 +32,7 @@
* \ingroup bph
*/
-#ifdef __GNUC__
+#if defined(__GNUC__) && !defined(__clang__)
# pragma GCC diagnostic push
/* XXX suppress verbose warnings in eigen */
# pragma GCC diagnostic ignored "-Wlogical-op"
diff --git a/source/blender/physics/intern/implicit_eigen.cpp b/source/blender/physics/intern/implicit_eigen.cpp
index ff4c705ed61..afe1b441632 100644
--- a/source/blender/physics/intern/implicit_eigen.cpp
+++ b/source/blender/physics/intern/implicit_eigen.cpp
@@ -39,7 +39,7 @@
#ifdef __GNUC__
# pragma GCC diagnostic push
/* XXX suppress verbose warnings in eigen */
-# pragma GCC diagnostic ignored "-Wlogical-op"
+//# pragma GCC diagnostic ignored "-Wlogical-op"
#endif
#ifndef IMPLICIT_ENABLE_EIGEN_DEBUG
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
index b01d3f89d4e..7984f625d96 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
@@ -370,12 +370,12 @@ PyObject *BPy_BMVertSkin_CreatePyObject(struct MVertSkin *mvertskin)
static void mloopcol_to_float(const MLoopCol *mloopcol, float r_col[3])
{
- rgb_uchar_to_float(r_col, (const unsigned char *)&mloopcol->r);
+ rgba_uchar_to_float(r_col, (const unsigned char *)&mloopcol->r);
}
static void mloopcol_from_float(MLoopCol *mloopcol, const float col[3])
{
- rgb_float_to_uchar((unsigned char *)&mloopcol->r, col);
+ rgba_float_to_uchar((unsigned char *)&mloopcol->r, col);
}
static unsigned char mathutils_bmloopcol_cb_index = -1;
@@ -436,8 +436,8 @@ static void bm_init_types_bmloopcol(void)
int BPy_BMLoopColor_AssignPyObject(struct MLoopCol *mloopcol, PyObject *value)
{
- float tvec[3];
- if (mathutils_array_parse(tvec, 3, 3, value, "BMLoopCol") != -1) {
+ float tvec[4];
+ if (mathutils_array_parse(tvec, 4, 4, value, "BMLoopCol") != -1) {
mloopcol_from_float(mloopcol, tvec);
return 0;
}
@@ -450,7 +450,7 @@ PyObject *BPy_BMLoopColor_CreatePyObject(struct MLoopCol *data)
{
PyObject *color_capsule;
color_capsule = PyCapsule_New(data, NULL, NULL);
- return Color_CreatePyObject_cb(color_capsule, mathutils_bmloopcol_cb_index, 0);
+ return Vector_CreatePyObject_cb(color_capsule, 4, mathutils_bmloopcol_cb_index, 0);
}
#undef MLOOPCOL_FROM_CAPSULE
diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c
index 3e147d29c90..e0ca3634261 100644
--- a/source/blender/python/intern/bpy_rna_array.c
+++ b/source/blender/python/intern/bpy_rna_array.c
@@ -28,13 +28,14 @@
#include <Python.h>
+#include "BLI_utildefines.h"
+
#include "RNA_types.h"
#include "bpy_rna.h"
#include "BKE_global.h"
-#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
+#include "MEM_guardedalloc.h"
#include "RNA_access.h"
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index c7b7b35474e..830f6a0bbf1 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -310,7 +310,7 @@ void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene
bool RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode);
bool RE_WriteRenderResult(
struct ReportList *reports, RenderResult *rr, const char *filename,
- struct ImageFormatData *imf, const char *view, const int layer);
+ struct ImageFormatData *imf, const char *view, int layer);
struct RenderResult *RE_MultilayerConvert(
void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 631503bdad5..88ccb9452ba 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -36,7 +36,6 @@
#include "MEM_guardedalloc.h"
-#include "BKE_appdir.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_hash_md5.h"
@@ -45,6 +44,7 @@
#include "BLI_string.h"
#include "BLI_threads.h"
+#include "BKE_appdir.h"
#include "BKE_image.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -925,6 +925,17 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil
}
}
+ /* We only store RGBA passes as half float, for
+ * others precision loss can be problematic. */
+ bool pass_half_float = half_float &&
+ (STREQ(rp->chan_id, "RGB") ||
+ STREQ(rp->chan_id, "RGBA") ||
+ STREQ(rp->chan_id, "R") ||
+ STREQ(rp->chan_id, "G") ||
+ STREQ(rp->chan_id, "B") ||
+ STREQ(rp->chan_id, "A"));
+
+
for (int a = 0; a < rp->channels; a++) {
/* Save Combined as RGBA if single layer save. */
char passname[EXR_PASS_MAXNAME];
@@ -940,10 +951,9 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil
layname[0] = '\0';
}
- /* Add channel. */
IMB_exr_add_channel(exrhandle, layname, passname, viewname,
rp->channels, rp->channels * rr->rectx, rp->rect + a,
- STREQ(rp->name, RE_PASSNAME_Z) ? false : half_float);
+ pass_half_float);
}
}
}
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 637ace9cd82..57f4219f23f 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -71,7 +71,6 @@
#include "DNA_windowmanager_types.h"
#include "BKE_appdir.h"
-#include "BKE_utildefines.h"
#include "BKE_autoexec.h"
#include "BKE_blender.h"
#include "BKE_blendfile.h"
@@ -327,12 +326,12 @@ static void wm_init_userdef(bContext *C, const bool read_userdef_from_memory)
BKE_sound_init(bmain);
/* needed so loading a file from the command line respects user-pref [#26156] */
- BKE_BIT_TEST_SET(G.fileflags, U.flag & USER_FILENOUI, G_FILE_NO_UI);
+ SET_FLAG_FROM_TEST(G.fileflags, U.flag & USER_FILENOUI, G_FILE_NO_UI);
/* set the python auto-execute setting from user prefs */
/* enabled by default, unless explicitly enabled in the command line which overrides */
if ((G.f & G_SCRIPT_OVERRIDE_PREF) == 0) {
- BKE_BIT_TEST_SET(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC);
+ SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC);
}
/* avoid re-saving for every small change to our prefs, allow overrides */
@@ -675,7 +674,7 @@ int wm_homefile_read(
BLI_assert((use_factory_settings && filepath_startup_override) == 0);
if ((G.f & G_SCRIPT_OVERRIDE_PREF) == 0) {
- BKE_BIT_TEST_SET(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC);
+ SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC);
}
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);
@@ -714,8 +713,8 @@ int wm_homefile_read(
if (!use_factory_settings && BLI_exists(filepath_userdef)) {
UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL);
if (userdef != NULL) {
- BKE_blender_userdef_set_data(userdef);
- MEM_freeN(userdef);
+ BKE_blender_userdef_data_set_and_free(userdef);
+ userdef = NULL;
skip_flags |= BLO_READ_SKIP_USERDEF;
printf("Read prefs: %s\n", filepath_userdef);
@@ -825,9 +824,8 @@ int wm_homefile_read(
read_userdef_from_memory = true;
}
if (userdef_template) {
- BKE_blender_userdef_set_app_template(userdef_template);
- BKE_blender_userdef_free_data(userdef_template);
- MEM_freeN(userdef_template);
+ BKE_blender_userdef_app_template_data_set_and_free(userdef_template);
+ userdef_template = NULL;
}
}
}
@@ -1031,14 +1029,14 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, BlendThumbnail **t
ibuf = ED_view3d_draw_offscreen_imbuf_simple(
scene, scene->camera,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, 0, false, NULL,
+ IB_rect, OB_SOLID, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
NULL, NULL, err_out);
}
else {
ibuf = ED_view3d_draw_offscreen_imbuf(
scene, v3d, ar,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, false, R_ALPHAPREMUL, 0, false, NULL,
+ IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
NULL, NULL, err_out);
}
@@ -1167,8 +1165,8 @@ static int wm_file_write(bContext *C, const char *filepath, int fileflags, Repor
G.save_over = 1; /* disable untitled.blend convention */
}
- BKE_BIT_TEST_SET(G.fileflags, fileflags & G_FILE_COMPRESS, G_FILE_COMPRESS);
- BKE_BIT_TEST_SET(G.fileflags, fileflags & G_FILE_AUTOPLAY, G_FILE_AUTOPLAY);
+ SET_FLAG_FROM_TEST(G.fileflags, fileflags & G_FILE_COMPRESS, G_FILE_COMPRESS);
+ SET_FLAG_FROM_TEST(G.fileflags, fileflags & G_FILE_AUTOPLAY, G_FILE_AUTOPLAY);
/* prevent background mode scripts from clobbering history */
if (do_history) {
@@ -1473,41 +1471,53 @@ static int wm_userpref_write_exec(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
char filepath[FILE_MAX];
const char *cfgdir;
- bool ok = false;
+ bool ok = true;
/* update keymaps in user preferences */
WM_keyconfig_update(wm);
if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) {
+ bool ok_write;
BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
printf("trying to save userpref at %s ", filepath);
- if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) {
+
+ if (U.app_template[0]) {
+ ok_write = BKE_blendfile_userdef_write_app_template(filepath, op->reports);
+ }
+ else {
+ ok_write = BKE_blendfile_userdef_write(filepath, op->reports);
+ }
+
+ if (ok_write) {
printf("ok\n");
- ok = true;
}
else {
printf("fail\n");
+ ok = false;
}
}
else {
BKE_report(op->reports, RPT_ERROR, "Unable to create userpref path");
}
- if (U.app_template[0] && (cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) {
- /* Also save app-template prefs */
- BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
- printf("trying to save app-template userpref at %s ", filepath);
- if (BKE_blendfile_userdef_write(filepath, op->reports) == 0) {
- printf("fail\n");
- ok = true;
+ if (U.app_template[0]) {
+ if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) {
+ /* Also save app-template prefs */
+ BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
+ printf("trying to save app-template userpref at %s ", filepath);
+ if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) {
+ printf("ok\n");
+ }
+ else {
+ printf("fail\n");
+ ok = false;
+ }
}
else {
- printf("ok\n");
+ BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path");
+ ok = false;
}
}
- else if (U.app_template[0]) {
- BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path");
- }
return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@@ -1555,7 +1565,7 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
/* This can be used when loading of a start-up file should only change
* the scene content but keep the blender UI as it is. */
wm_open_init_load_ui(op, true);
- BKE_BIT_TEST_SET(G.fileflags, !RNA_boolean_get(op->ptr, "load_ui"), G_FILE_NO_UI);
+ SET_FLAG_FROM_TEST(G.fileflags, !RNA_boolean_get(op->ptr, "load_ui"), G_FILE_NO_UI);
if (RNA_property_is_set(op->ptr, prop)) {
RNA_property_string_get(op->ptr, prop, filepath_buf);
@@ -2038,20 +2048,24 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
fileflags = G.fileflags & ~G_FILE_USERPREFS;
/* set compression flag */
- BKE_BIT_TEST_SET(fileflags, RNA_boolean_get(op->ptr, "compress"),
- G_FILE_COMPRESS);
- BKE_BIT_TEST_SET(fileflags, RNA_boolean_get(op->ptr, "relative_remap"),
- G_FILE_RELATIVE_REMAP);
- BKE_BIT_TEST_SET(fileflags,
- (RNA_struct_property_is_set(op->ptr, "copy") &&
- RNA_boolean_get(op->ptr, "copy")),
- G_FILE_SAVE_COPY);
+ SET_FLAG_FROM_TEST(
+ fileflags, RNA_boolean_get(op->ptr, "compress"),
+ G_FILE_COMPRESS);
+ SET_FLAG_FROM_TEST(
+ fileflags, RNA_boolean_get(op->ptr, "relative_remap"),
+ G_FILE_RELATIVE_REMAP);
+ SET_FLAG_FROM_TEST(
+ fileflags,
+ (RNA_struct_property_is_set(op->ptr, "copy") &&
+ RNA_boolean_get(op->ptr, "copy")),
+ G_FILE_SAVE_COPY);
#ifdef USE_BMESH_SAVE_AS_COMPAT
- BKE_BIT_TEST_SET(fileflags,
- (RNA_struct_find_property(op->ptr, "use_mesh_compat") &&
- RNA_boolean_get(op->ptr, "use_mesh_compat")),
- G_FILE_MESH_COMPAT);
+ SET_FLAG_FROM_TEST(
+ fileflags,
+ (RNA_struct_find_property(op->ptr, "use_mesh_compat") &&
+ RNA_boolean_get(op->ptr, "use_mesh_compat")),
+ G_FILE_MESH_COMPAT);
#else
# error "don't remove by accident"
#endif
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index e73ec2b081a..7608b015f49 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -569,7 +569,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
ED_file_exit(); /* for fsmenu */
UI_exit();
- BKE_blender_userdef_free_data(&U);
+ BKE_blender_userdef_data_free(&U, false);
RNA_exit(); /* should be after BPY_python_end so struct python slots are cleared */
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index fbd6d89e7bc..4674df9983b 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3852,14 +3852,29 @@ void wm_window_keymap(wmKeyConfig *keyconf)
gesture_straightline_modal_keymap(keyconf);
}
+/**
+ * Filter functions that can be used with rna_id_itemf() below.
+ * Should return false if 'id' should be excluded.
+ */
+static bool rna_id_enum_filter_single(ID *id, void *user_data)
+{
+ return (id != user_data);
+}
+
/* Generic itemf's for operators that take library args */
-static const EnumPropertyItem *rna_id_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), bool *r_free, ID *id, bool local)
+static const EnumPropertyItem *rna_id_itemf(
+ bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
+ bool *r_free, ID *id, bool local,
+ bool (*filter_ids)(ID *id, void *user_data), void *user_data)
{
EnumPropertyItem item_tmp = {0}, *item = NULL;
int totitem = 0;
int i = 0;
for (; id; id = id->next) {
+ if ((filter_ids != NULL) && filter_ids(user_data, id) == false) {
+ continue;
+ }
if (local == false || !ID_IS_LINKED(id)) {
item_tmp.identifier = item_tmp.name = id->name + 2;
item_tmp.value = i++;
@@ -3876,7 +3891,7 @@ static const EnumPropertyItem *rna_id_itemf(bContext *UNUSED(C), PointerRNA *UNU
/* can add more as needed */
const EnumPropertyItem *RNA_action_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->action.first : NULL, false);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->action.first : NULL, false, NULL, NULL);
}
#if 0 /* UNUSED */
const EnumPropertyItem *RNA_action_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
@@ -3887,45 +3902,51 @@ const EnumPropertyItem *RNA_action_local_itemf(bContext *C, PointerRNA *ptr, Pro
const EnumPropertyItem *RNA_group_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, false);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, false, NULL, NULL);
}
const EnumPropertyItem *RNA_group_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, true);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, true, NULL, NULL);
}
const EnumPropertyItem *RNA_image_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->image.first : NULL, false);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->image.first : NULL, false, NULL, NULL);
}
const EnumPropertyItem *RNA_image_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->image.first : NULL, true);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->image.first : NULL, true, NULL, NULL);
}
const EnumPropertyItem *RNA_scene_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, false);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, false, NULL, NULL);
}
const EnumPropertyItem *RNA_scene_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, true);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, true, NULL, NULL);
+}
+const EnumPropertyItem *RNA_scene_without_active_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ Scene *scene_active = C ? CTX_data_scene(C) : NULL;
+ return rna_id_itemf(
+ C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, true,
+ rna_id_enum_filter_single, scene_active);
}
-
const EnumPropertyItem *RNA_movieclip_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclip.first : NULL, false);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclip.first : NULL, false, NULL, NULL);
}
const EnumPropertyItem *RNA_movieclip_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclip.first : NULL, true);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclip.first : NULL, true, NULL, NULL);
}
const EnumPropertyItem *RNA_mask_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->mask.first : NULL, false);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->mask.first : NULL, false, NULL, NULL);
}
const EnumPropertyItem *RNA_mask_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->mask.first : NULL, true);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->mask.first : NULL, true, NULL, NULL);
}
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index d858097abef..64aab31ba22 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -488,7 +488,7 @@ int KX_SoundActuator::pyattr_set_3d_property(void *self, const struct KX_PYATTRI
if (actuator->m_handle)
AUD_Handle_setAttenuation(actuator->m_handle, prop_value);
- } else if (!!strcmp(prop, "cone_angle_inner")) {
+ } else if (!strcmp(prop, "cone_angle_inner")) {
actuator->m_3d.cone_inner_angle = prop_value;
if (actuator->m_handle)
AUD_Handle_setConeAngleInner(actuator->m_handle, prop_value);
diff --git a/source/tools b/source/tools
-Subproject b11375e89061303401376f7aeae42ac2fd64692
+Subproject e10a1b031b243482371c0673ee17aa3c0f53637
diff --git a/tests/gtests/blenlib/BLI_task_test.cc b/tests/gtests/blenlib/BLI_task_test.cc
new file mode 100644
index 00000000000..e6464164ecb
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_task_test.cc
@@ -0,0 +1,76 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+#include <string.h>
+
+#include "atomic_ops.h"
+
+extern "C" {
+#include "BLI_mempool.h"
+#include "BLI_task.h"
+#include "BLI_utildefines.h"
+};
+
+#define NUM_ITEMS 10000
+
+static void task_mempool_iter_func(void *userdata, MempoolIterData *item) {
+ int *data = (int *)item;
+ int *count = (int *)userdata;
+
+ EXPECT_TRUE(data != NULL);
+
+ *data += 1;
+ atomic_sub_and_fetch_uint32((uint32_t *)count, 1);
+}
+
+TEST(task, MempoolIter)
+{
+ int *data[NUM_ITEMS];
+ BLI_mempool *mempool = BLI_mempool_create(sizeof(*data[0]), NUM_ITEMS, 32, BLI_MEMPOOL_ALLOW_ITER);
+
+ int i;
+
+ /* 'Randomly' add and remove some items from mempool, to create a non-homogenous one. */
+ int num_items = 0;
+ for (i = 0; i < NUM_ITEMS; i++) {
+ data[i] = (int *)BLI_mempool_alloc(mempool);
+ *data[i] = i - 1;
+ num_items++;
+ }
+
+ for (i = 0; i < NUM_ITEMS; i += 3) {
+ BLI_mempool_free(mempool, data[i]);
+ data[i] = NULL;
+ num_items--;
+ }
+
+ for (i = 0; i < NUM_ITEMS; i += 7) {
+ if (data[i] == NULL) {
+ data[i] = (int *)BLI_mempool_alloc(mempool);
+ *data[i] = i - 1;
+ num_items++;
+ }
+ }
+
+ for (i = 0; i < NUM_ITEMS - 5; i += 23) {
+ for (int j = 0; j < 5; j++) {
+ if (data[i + j] != NULL) {
+ BLI_mempool_free(mempool, data[i + j]);
+ data[i + j] = NULL;
+ num_items--;
+ }
+ }
+ }
+
+ BLI_task_parallel_mempool(mempool, &num_items, task_mempool_iter_func, true);
+
+ /* Those checks should ensure us all items of the mempool were processed once, and only once - as expected. */
+ EXPECT_EQ(num_items, 0);
+ for (i = 0; i < NUM_ITEMS; i++) {
+ if (data[i] != NULL) {
+ EXPECT_EQ(*data[i], i);
+ }
+ }
+
+ BLI_mempool_destroy(mempool);
+}
diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt
index eff67f053e6..715b689387f 100644
--- a/tests/gtests/blenlib/CMakeLists.txt
+++ b/tests/gtests/blenlib/CMakeLists.txt
@@ -27,6 +27,7 @@ set(INC
../../../source/blender/blenlib
../../../source/blender/makesdna
../../../intern/guardedalloc
+ ../../../intern/atomic
)
include_directories(${INC})
@@ -55,6 +56,7 @@ BLENDER_TEST(BLI_polyfill2d "bf_blenlib")
BLENDER_TEST(BLI_stack "bf_blenlib")
BLENDER_TEST(BLI_string "bf_blenlib")
BLENDER_TEST(BLI_string_utf8 "bf_blenlib")
+BLENDER_TEST(BLI_task "bf_blenlib")
BLENDER_TEST_PERFORMANCE(BLI_ghash_performance "bf_blenlib")