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:
authorAntonio Vazquez <blendergit@gmail.com>2019-10-16 11:36:01 +0300
committerAntonio Vazquez <blendergit@gmail.com>2019-10-16 11:36:01 +0300
commitc2fbe46b0f0fde44b8a40d89601a195da27d28fb (patch)
treef66e3e50758acb36001e2774c6e4ede5fc8bead6
parent386ba094988fc793f8e060d15438566e5e2d2cae (diff)
parentdcf57e34f3866bba5ddd9cfdfe858a1a5eedc4c2 (diff)
Merge branch 'master' into temp-gpencil-drw-enginetemp-gpencil-drw-engine
-rw-r--r--.github/stale.yml22
-rw-r--r--CMakeLists.txt21
-rw-r--r--build_files/build_environment/CMakeLists.txt6
-rw-r--r--build_files/build_environment/cmake/check_software.cmake8
-rw-r--r--build_files/build_environment/cmake/ffmpeg.cmake8
-rw-r--r--build_files/build_environment/cmake/harvest.cmake6
-rw-r--r--build_files/build_environment/cmake/libglu.cmake40
-rw-r--r--build_files/build_environment/cmake/mesa.cmake54
-rw-r--r--build_files/build_environment/cmake/opus.cmake35
-rw-r--r--build_files/build_environment/cmake/versions.cmake12
-rw-r--r--build_files/build_environment/cmake/vpx.cmake2
-rwxr-xr-xbuild_files/build_environment/install_deps.sh36
-rw-r--r--build_files/buildbot/buildbot_utils.py2
-rw-r--r--build_files/buildbot/config/blender_linux.cmake23
-rw-r--r--build_files/buildbot/slave_pack.py20
-rw-r--r--build_files/buildbot/slave_update.py2
-rw-r--r--build_files/cmake/Modules/GTestTesting.cmake8
-rw-r--r--build_files/cmake/config/blender_full.cmake1
-rw-r--r--build_files/cmake/config/blender_lite.cmake1
-rw-r--r--build_files/cmake/config/blender_release.cmake1
-rw-r--r--build_files/cmake/macros.cmake11
-rw-r--r--build_files/cmake/platform/platform_apple.cmake23
-rw-r--r--build_files/cmake/platform/platform_unix.cmake44
-rw-r--r--build_files/cmake/platform/platform_win32.cmake46
-rwxr-xr-xbuild_files/utils/make_test.py3
-rwxr-xr-xbuild_files/utils/make_update.py113
-rwxr-xr-xbuild_files/utils/make_utils.py6
-rw-r--r--doc/doxygen/Doxyfile2
-rwxr-xr-xdoc/python_api/sphinx_doc_update.py38
-rw-r--r--extern/audaspace/src/devices/SoftwareDevice.cpp2
-rw-r--r--extern/cuew/src/cuew.c19
-rw-r--r--extern/quadriflow/CMakeLists.txt3
-rw-r--r--extern/quadriflow/patches/blender.patch16
-rw-r--r--extern/quadriflow/src/config.hpp5
-rw-r--r--intern/clog/clog.c1
-rw-r--r--intern/cycles/blender/blender_object.cpp5
-rw-r--r--intern/cycles/blender/blender_shader.cpp12
-rw-r--r--intern/cycles/device/device_cuda.cpp6
-rw-r--r--intern/cycles/device/device_optix.cpp14
-rw-r--r--intern/cycles/kernel/CMakeLists.txt24
-rw-r--r--intern/cycles/kernel/kernel_path.h2
-rw-r--r--intern/cycles/kernel/shaders/node_mix.osl4
-rw-r--r--intern/cycles/kernel/svm/svm_color_util.h4
-rw-r--r--intern/cycles/render/nodes.cpp14
-rw-r--r--intern/cycles/util/util_defines.h192
-rw-r--r--intern/cycles/util/util_static_assert.h16
-rw-r--r--intern/ghost/GHOST_C-api.h33
-rw-r--r--intern/ghost/GHOST_ISystem.h27
-rw-r--r--intern/ghost/GHOST_IWindow.h2
-rw-r--r--intern/ghost/GHOST_Types.h5
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp56
-rw-r--r--intern/ghost/intern/GHOST_System.h27
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h8
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm25
-rw-r--r--intern/ghost/intern/GHOST_SystemNULL.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp1
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h1
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp77
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h25
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp262
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h18
-rw-r--r--intern/ghost/intern/GHOST_Window.h5
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h7
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm41
-rw-r--r--intern/ghost/intern/GHOST_WindowNULL.h7
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp72
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h10
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp102
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h7
-rw-r--r--intern/mikktspace/mikktspace.c5
-rw-r--r--intern/numaapi/README.blender2
-rw-r--r--intern/numaapi/source/build_config.h27
-rw-r--r--intern/opensubdiv/internal/opensubdiv_topology_refiner.cc19
-rw-r--r--intern/opensubdiv/opensubdiv_topology_refiner_capi.h8
m---------release/datafiles/locale0
-rw-r--r--release/datafiles/userdef/userdef_default.c2
-rw-r--r--release/datafiles/userdef/userdef_default_theme.c3
-rw-r--r--release/freedesktop/org.blender.Blender.appdata.xml21
m---------release/scripts/addons0
m---------release/scripts/addons_contrib0
-rw-r--r--release/scripts/modules/bl_i18n_utils/settings.py1
-rw-r--r--release/scripts/modules/bpy_extras/mesh_utils.py31
-rw-r--r--release/scripts/modules/bpy_extras/node_shader_utils.py31
-rw-r--r--release/scripts/modules/bpy_types.py47
-rw-r--r--release/scripts/presets/keyconfig/blender.py5
-rw-r--r--release/scripts/presets/keyconfig/blender_27x.py5
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py65
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py6
-rw-r--r--release/scripts/startup/bl_operators/userpref.py3
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py7
-rw-r--r--release/scripts/startup/bl_operators/wm.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py16
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py38
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py11
-rw-r--r--release/scripts/startup/bl_ui/space_node.py9
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py3
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py15
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py6
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py67
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py3
-rw-r--r--release/scripts/templates_py/operator_mesh_add.py17
-rw-r--r--release/scripts/templates_py/operator_modal_draw.py1
-rw-r--r--release/scripts/templates_py/ui_tool_simple.py11
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc1
-rw-r--r--source/blender/blenkernel/BKE_action.h4
-rw-r--r--source/blender/blenkernel/BKE_appdir.h1
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h4
-rw-r--r--source/blender/blenkernel/BKE_brush.h1
-rw-r--r--source/blender/blenkernel/BKE_editmesh_bvh.h4
-rw-r--r--source/blender/blenkernel/BKE_gpencil_modifier.h6
-rw-r--r--source/blender/blenkernel/BKE_image.h6
-rw-r--r--source/blender/blenkernel/BKE_layer.h12
-rw-r--r--source/blender/blenkernel/BKE_mesh_remesh_voxel.h3
-rw-r--r--source/blender/blenkernel/BKE_modifier.h3
-rw-r--r--source/blender/blenkernel/BKE_node.h3
-rw-r--r--source/blender/blenkernel/BKE_paint.h10
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h40
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h10
-rw-r--r--source/blender/blenkernel/BKE_scene.h7
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h1
-rw-r--r--source/blender/blenkernel/BKE_subdiv_ccg.h59
-rw-r--r--source/blender/blenkernel/BKE_text.h1
-rw-r--r--source/blender/blenkernel/CMakeLists.txt9
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c4
-rw-r--r--source/blender/blenkernel/intern/action.c4
-rw-r--r--source/blender/blenkernel/intern/armature_update.c6
-rw-r--r--source/blender/blenkernel/intern/brush.c45
-rw-r--r--source/blender/blenkernel/intern/cloth.c2
-rw-r--r--source/blender/blenkernel/intern/collection.c5
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c13
-rw-r--r--source/blender/blenkernel/intern/displist.c8
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c2
-rw-r--r--source/blender/blenkernel/intern/font.c3
-rw-r--r--source/blender/blenkernel/intern/gpencil.c7
-rw-r--r--source/blender/blenkernel/intern/image.c4
-rw-r--r--source/blender/blenkernel/intern/layer.c115
-rw-r--r--source/blender/blenkernel/intern/library.c13
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_remesh_voxel.c13
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c6
-rw-r--r--source/blender/blenkernel/intern/mirror.c16
-rw-r--r--source/blender/blenkernel/intern/modifier.c17
-rw-r--r--source/blender/blenkernel/intern/movieclip.c4
-rw-r--r--source/blender/blenkernel/intern/nla.c4
-rw-r--r--source/blender/blenkernel/intern/node.c27
-rw-r--r--source/blender/blenkernel/intern/object.c2
-rw-r--r--source/blender/blenkernel/intern/object_update.c4
-rw-r--r--source/blender/blenkernel/intern/packedFile.c6
-rw-r--r--source/blender/blenkernel/intern/paint.c29
-rw-r--r--source/blender/blenkernel/intern/pbvh.c152
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c38
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h1
-rw-r--r--source/blender/blenkernel/intern/pbvh_parallel.cc145
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c56
-rw-r--r--source/blender/blenkernel/intern/scene.c17
-rw-r--r--source/blender/blenkernel/intern/seqcache.c3
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c2
-rw-r--r--source/blender/blenkernel/intern/seqmodifier.c3
-rw-r--r--source/blender/blenkernel/intern/seqprefetch.c49
-rw-r--r--source/blender/blenkernel/intern/sequencer.c3
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c1
-rw-r--r--source/blender/blenkernel/intern/smoke.c16
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg.c641
-rw-r--r--source/blender/blenkernel/intern/text.c60
-rw-r--r--source/blender/blenlib/BLI_compiler_compat.h34
-rw-r--r--source/blender/blenlib/BLI_fileops.h1
-rw-r--r--source/blender/blenlib/BLI_gsqueue.h2
-rw-r--r--source/blender/blenlib/BLI_math_geom.h6
-rw-r--r--source/blender/blenlib/intern/BLI_temporary_allocator.cc2
-rw-r--r--source/blender/blenlib/intern/BLI_timer.c1
-rw-r--r--source/blender/blenlib/intern/delaunay_2d.c126
-rw-r--r--source/blender/blenlib/intern/expr_pylike_eval.c8
-rw-r--r--source/blender/blenlib/intern/fileops.c193
-rw-r--r--source/blender/blenlib/intern/scanfill.c2
-rw-r--r--source/blender/blenlib/intern/storage.c1
-rw-r--r--source/blender/blenloader/intern/readfile.c10
-rw-r--r--source/blender/blenloader/intern/versioning_250.c12
-rw-r--r--source/blender/blenloader/intern/versioning_280.c42
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c40
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c26
-rw-r--r--source/blender/blenloader/intern/writefile.c31
-rw-r--r--source/blender/blentranslation/msgfmt/CMakeLists.txt4
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c2
-rw-r--r--source/blender/collada/AnimationImporter.cpp2
-rw-r--r--source/blender/collada/BCAnimationCurve.cpp2
-rw-r--r--source/blender/collada/ImageExporter.cpp2
-rw-r--r--source/blender/compositor/CMakeLists.txt1
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc3
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc8
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc6
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc53
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc29
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc44
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c1
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl14
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c4
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c38
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c111
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h3
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c1
-rw-r--r--source/blender/draw/engines/workbench/workbench_studiolight.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_volume.c2
-rw-r--r--source/blender/draw/intern/draw_armature.c1
-rw-r--r--source/blender/draw/intern/draw_cache.c5
-rw-r--r--source/blender/draw/intern/draw_cache_extract.h3
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.c8
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c107
-rw-r--r--source/blender/draw/intern/draw_common.c1
-rw-r--r--source/blender/draw/intern/draw_manager.c42
-rw-r--r--source/blender/draw/intern/draw_manager_data.c5
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c1
-rw-r--r--source/blender/draw/intern/draw_view.c38
-rw-r--r--source/blender/draw/intern/draw_view.h1
-rw-r--r--source/blender/draw/modes/object_mode.c108
-rw-r--r--source/blender/draw/modes/sculpt_mode.c3
-rw-r--r--source/blender/draw/modes/shaders/object_camera_image_frag.glsl2
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c2
-rw-r--r--source/blender/editors/animation/anim_filter.c4
-rw-r--r--source/blender/editors/animation/anim_markers.c67
-rw-r--r--source/blender/editors/animation/drivers.c2
-rw-r--r--source/blender/editors/animation/keyframes_draw.c3
-rw-r--r--source/blender/editors/animation/keyframing.c2
-rw-r--r--source/blender/editors/armature/pose_slide.c24
-rw-r--r--source/blender/editors/armature/pose_utils.c6
-rw-r--r--source/blender/editors/curve/editfont.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_ops_versioning.c4
-rw-r--r--source/blender/editors/include/ED_screen.h3
-rw-r--r--source/blender/editors/include/UI_resources.h1
-rw-r--r--source/blender/editors/interface/CMakeLists.txt1
-rw-r--r--source/blender/editors/interface/interface.c4
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c1
-rw-r--r--source/blender/editors/interface/interface_eyedropper_gpencil_color.c324
-rw-r--r--source/blender/editors/interface/interface_handlers.c12
-rw-r--r--source/blender/editors/interface/interface_icons.c1
-rw-r--r--source/blender/editors/interface/interface_icons_event.c7
-rw-r--r--source/blender/editors/interface/interface_intern.h3
-rw-r--r--source/blender/editors/interface/interface_ops.c1
-rw-r--r--source/blender/editors/interface/interface_region_popover.c3
-rw-r--r--source/blender/editors/interface/interface_widgets.c10
-rw-r--r--source/blender/editors/interface/resources.c4
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c1
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c1
-rw-r--r--source/blender/editors/mesh/editmesh_mask_extract.c21
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c12
-rw-r--r--source/blender/editors/mesh/mesh_data.c8
-rw-r--r--source/blender/editors/object/object_add.c36
-rw-r--r--source/blender/editors/object/object_bake_api.c8
-rw-r--r--source/blender/editors/object/object_edit.c10
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/object/object_remesh.c97
-rw-r--r--source/blender/editors/object/object_select.c4
-rw-r--r--source/blender/editors/physics/particle_edit.c6
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c8
-rw-r--r--source/blender/editors/physics/rigidbody_object.c2
-rw-r--r--source/blender/editors/render/render_internal.c2
-rw-r--r--source/blender/editors/render/render_preview.c4
-rw-r--r--source/blender/editors/render/render_shading.c14
-rw-r--r--source/blender/editors/render/render_view.c4
-rw-r--r--source/blender/editors/screen/area.c2
-rw-r--r--source/blender/editors/screen/screen_draw.c2
-rw-r--r--source/blender/editors/screen/screen_edit.c5
-rw-r--r--source/blender/editors/screen/screen_ops.c35
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c15
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c73
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h2
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c12
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c19
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c33
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c708
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h13
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c101
-rw-r--r--source/blender/editors/sound/sound_ops.c3
-rw-r--r--source/blender/editors/space_action/action_select.c150
-rw-r--r--source/blender/editors/space_clip/tracking_ops_solve.c6
-rw-r--r--source/blender/editors/space_file/file_ops.c82
-rw-r--r--source/blender/editors/space_file/filelist.c2
-rw-r--r--source/blender/editors/space_file/filesel.c14
-rw-r--r--source/blender/editors/space_image/image_ops.c7
-rw-r--r--source/blender/editors/space_image/image_undo.c30
-rw-r--r--source/blender/editors/space_nla/nla_select.c47
-rw-r--r--source/blender/editors/space_node/drawnode.c51
-rw-r--r--source/blender/editors/space_node/node_group.c106
-rw-r--r--source/blender/editors/space_node/node_select.c76
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c1
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c18
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c5
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c50
-rw-r--r--source/blender/editors/space_text/text_format_lua.c34
-rw-r--r--source/blender/editors/space_text/text_format_osl.c10
-rw-r--r--source/blender/editors/space_text/text_format_pov.c10
-rw-r--r--source/blender/editors/space_text/text_format_pov_ini.c6
-rw-r--r--source/blender/editors/space_text/text_format_py.c10
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c11
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_armature.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_camera.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_empty.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_forcefield.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_light.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c21
-rw-r--r--source/blender/editors/transform/transform.c8
-rw-r--r--source/blender/editors/transform/transform_convert.c10
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c2
-rw-r--r--source/blender/editors/transform/transform_generics.c12
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c35
-rw-r--r--source/blender/editors/transform/transform_orientations.c1
-rw-r--r--source/blender/editors/transform/transform_snap_object.c3
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.h9
-rw-r--r--source/blender/freestyle/intern/view_map/Interface1D.h10
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c16
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c11
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c1
-rw-r--r--source/blender/gpu/CMakeLists.txt2
-rw-r--r--source/blender/gpu/GPU_batch.h6
-rw-r--r--source/blender/gpu/GPU_buffers.h4
-rw-r--r--source/blender/gpu/GPU_extensions.h28
-rw-r--r--source/blender/gpu/GPU_platform.h75
-rw-r--r--source/blender/gpu/intern/gpu_batch.c15
-rw-r--r--source/blender/gpu/intern/gpu_batch_utils.c1
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c303
-rw-r--r--source/blender/gpu/intern/gpu_draw.c1
-rw-r--r--source/blender/gpu/intern/gpu_element.c2
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c90
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c5
-rw-r--r--source/blender/gpu/intern/gpu_platform.c229
-rw-r--r--source/blender/gpu/intern/gpu_private.h4
-rw-r--r--source/blender/gpu/intern/gpu_shader.c1
-rw-r--r--source/blender/gpu/intern/gpu_texture.c1
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl25
-rw-r--r--source/blender/imbuf/IMB_imbuf.h2
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c18
-rw-r--r--source/blender/imbuf/intern/imageprocess.c5
-rw-r--r--source/blender/imbuf/intern/rectop.c4
-rw-r--r--source/blender/makesdna/DNA_ID.h7
-rw-r--r--source/blender/makesdna/DNA_brush_types.h3
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h2
-rw-r--r--source/blender/makesdna/DNA_layer_types.h21
-rw-r--r--source/blender/makesdna/DNA_scene_types.h9
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h15
-rw-r--r--source/blender/makesrna/RNA_enum_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_access.c2
-rw-r--r--source/blender/makesrna/intern/rna_access_compare_override.c73
-rw-r--r--source/blender/makesrna/intern/rna_access_internal.h1
-rw-r--r--source/blender/makesrna/intern/rna_brush.c86
-rw-r--r--source/blender/makesrna/intern/rna_depsgraph.c9
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c31
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c6
-rw-r--r--source/blender/makesrna/intern/rna_layer.c38
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_material.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c2
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c15
-rw-r--r--source/blender/makesrna/intern/rna_pose.c8
-rw-r--r--source/blender/makesrna/intern/rna_rna.c9
-rw-r--r--source/blender/makesrna/intern/rna_scene.c3
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c6
-rw-r--r--source/blender/makesrna/intern/rna_screen.c6
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c34
-rw-r--r--source/blender/makesrna/intern/rna_space.c13
-rw-r--r--source/blender/makesrna/intern/rna_text.c74
-rw-r--r--source/blender/makesrna/intern/rna_text_api.c31
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c45
-rw-r--r--source/blender/makesrna/intern/rna_workspace_api.c2
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c20
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c19
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c17
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geometry.c37
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_coord.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c4
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops.c16
-rw-r--r--source/blender/python/generic/blf_py_api.c5
-rw-r--r--source/blender/python/generic/idprop_py_api.c6
-rw-r--r--source/blender/python/generic/imbuf_py_api.c2
-rw-r--r--source/blender/python/generic/py_capi_utils.c11
-rw-r--r--source/blender/python/gpu/gpu_py_offscreen.c2
-rw-r--r--source/blender/python/intern/bpy_app_translations.c8
-rw-r--r--source/blender/python/intern/bpy_library_load.c2
-rw-r--r--source/blender/python/intern/bpy_props.c23
-rw-r--r--source/blender/python/intern/bpy_rna.c56
-rw-r--r--source/blender/python/mathutils/mathutils_Color.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c4
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c2
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c2
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c66
-rw-r--r--source/blender/python/mathutils/mathutils_kdtree.c2
-rw-r--r--source/blender/windowmanager/CMakeLists.txt1
-rw-r--r--source/blender/windowmanager/WM_api.h17
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c47
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c32
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c5
-rw-r--r--source/blender/windowmanager/intern/wm_operator_props.c10
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c92
-rw-r--r--source/blender/windowmanager/intern/wm_platform_support.c219
-rw-r--r--source/blender/windowmanager/intern/wm_platform_support.h30
-rw-r--r--source/blender/windowmanager/intern/wm_splash_screen.c108
-rw-r--r--source/blender/windowmanager/intern/wm_window.c225
-rw-r--r--source/blender/windowmanager/intern/wm_window_private.h42
-rw-r--r--source/creator/CMakeLists.txt17
m---------source/tools0
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/gtests/blenlib/BLI_delaunay_2d_test.cc31
-rw-r--r--tests/gtests/blenlib/BLI_memiter_test.cc8
439 files changed, 7410 insertions, 3089 deletions
diff --git a/.github/stale.yml b/.github/stale.yml
new file mode 100644
index 00000000000..9c563f2dee0
--- /dev/null
+++ b/.github/stale.yml
@@ -0,0 +1,22 @@
+# Configuration for probot-stale - https://github.com/probot/stale
+# This file is used on Blender's GitHub mirror to automatically close any pull request
+# and invite contributors to join the official development platform on blender.org
+
+# Number of days of inactivity before an Issue or Pull Request becomes stale
+daysUntilStale: 1
+
+# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
+# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
+daysUntilClose: 1
+
+# Label to use when marking as stale
+staleLabel: stale
+
+# Comment to post when closing a stale Issue or Pull Request.
+closeComment: >
+ This issue has been automatically closed, because this repository is only
+ used as a mirror of git.blender.org. Blender development happens on
+ developer.blender.org.
+
+ To get started contributing code, please read:
+ https://wiki.blender.org/wiki/Process/Contributing_Code
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cddb93dd7ab..ba051b82671 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,6 +16,7 @@
#
# The Original Code is Copyright (C) 2006, Blender Foundation
# All rights reserved.
+#
# ***** END GPL LICENSE BLOCK *****
#-----------------------------------------------------------------------------
@@ -460,14 +461,14 @@ mark_as_advanced(WITH_CXX_GUARDEDALLOC)
option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" ON)
mark_as_advanced(WITH_ASSERT_ABORT)
-option(WITH_BOOST "Enable features depending on boost" ON)
+option(WITH_BOOST "Enable features depending on boost" ON)
+option(WITH_TBB "Enable features depending on TBB (OpenVDB, OpenImageDenoise, sculpt multithreading)" ON)
# Unit testsing
option(WITH_GTESTS "Enable GTest unit testing" OFF)
option(WITH_OPENGL_RENDER_TESTS "Enable OpenGL render related unit testing (Experimental)" OFF)
option(WITH_OPENGL_DRAW_TESTS "Enable OpenGL UI drawing related unit testing (Experimental)" OFF)
-
# Documentation
if(UNIX AND NOT APPLE)
option(WITH_DOC_MANPAGE "Create a manual page (Unix manpage)" OFF)
@@ -584,6 +585,11 @@ if("${CMAKE_GENERATOR}" MATCHES "Ninja")
mark_as_advanced(WITH_NINJA_POOL_JOBS)
endif()
+if(UNIX AND NOT APPLE)
+ option(WITH_CXX11_ABI "Use native C++11 ABI of compiler" ON)
+ mark_as_advanced(WITH_CXX11_ABI)
+endif()
+
# avoid using again
option_defaults_clear()
@@ -1395,13 +1401,16 @@ if(CMAKE_COMPILER_IS_GNUCC)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_LOGICAL_OP -Wlogical-op)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNDEF -Wundef)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_INIT_SELF -Winit-self) # needs -Wuninitialized
- ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_NULL -Wnonnull) # C only
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_TYPE_LIMITS -Wtype-limits)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_FORMAT_SIGN -Wformat-signedness)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_RESTRICT -Wrestrict)
+ # C-only.
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_NULL -Wnonnull)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ABSOLUTE_VALUE -Wabsolute-value)
+
# gcc 4.2 gives annoying warnings on every file with this
if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3")
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNINITIALIZED -Wuninitialized)
@@ -1638,6 +1647,12 @@ if(
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11")
endif()
+if(UNIX AND NOT APPLE)
+ if(NOT WITH_CXX11_ABI)
+ set(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -D_GLIBCXX_USE_CXX11_ABI=0")
+ endif()
+endif()
+
# Include warnings first, so its possible to disable them with user defined flags
# eg: -Wno-uninitialized
set(CMAKE_C_FLAGS "${C_WARNINGS} ${CMAKE_C_FLAGS} ${PLATFORM_CFLAGS}")
diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt
index 9756ad28454..c7d8de22890 100644
--- a/build_files/build_environment/CMakeLists.txt
+++ b/build_files/build_environment/CMakeLists.txt
@@ -128,6 +128,7 @@ if(NOT WIN32 OR ENABLE_MINGW64)
include(cmake/ogg.cmake)
include(cmake/vorbis.cmake)
include(cmake/theora.cmake)
+ include(cmake/opus.cmake)
include(cmake/vpx.cmake)
include(cmake/x264.cmake)
include(cmake/xvidcore.cmake)
@@ -157,4 +158,9 @@ if(UNIX)
include(cmake/sqlite.cmake)
endif()
+if(UNIX AND NOT APPLE)
+ include(cmake/libglu.cmake)
+ include(cmake/mesa.cmake)
+endif()
+
include(cmake/harvest.cmake)
diff --git a/build_files/build_environment/cmake/check_software.cmake b/build_files/build_environment/cmake/check_software.cmake
index 30dea754e20..f5774551879 100644
--- a/build_files/build_environment/cmake/check_software.cmake
+++ b/build_files/build_environment/cmake/check_software.cmake
@@ -17,10 +17,16 @@
# ***** END GPL LICENSE BLOCK *****
if(UNIX)
+ if(APPLE)
+ set(_libtoolize_name glibtoolize)
+ else()
+ set(_libtoolize_name libtoolize)
+ endif()
+
set(_required_software
autoconf
automake
- libtoolize
+ ${_libtoolize_name}
nasm
yasm
tclsh
diff --git a/build_files/build_environment/cmake/ffmpeg.cmake b/build_files/build_environment/cmake/ffmpeg.cmake
index 27d817e8948..9ff52914f53 100644
--- a/build_files/build_environment/cmake/ffmpeg.cmake
+++ b/build_files/build_environment/cmake/ffmpeg.cmake
@@ -16,10 +16,10 @@
#
# ***** END GPL LICENSE BLOCK *****
-set(FFMPEG_CFLAGS "-I${mingw_LIBDIR}/lame/include -I${mingw_LIBDIR}/openjpeg/include/ -I${mingw_LIBDIR}/ogg/include -I${mingw_LIBDIR}/vorbis/include -I${mingw_LIBDIR}/theora/include -I${mingw_LIBDIR}/vpx/include -I${mingw_LIBDIR}/x264/include -I${mingw_LIBDIR}/xvidcore/include -I${mingw_LIBDIR}/zlib/include")
-set(FFMPEG_LDFLAGS "-L${mingw_LIBDIR}/lame/lib -L${mingw_LIBDIR}/openjpeg/lib -L${mingw_LIBDIR}/ogg/lib -L${mingw_LIBDIR}/vorbis/lib -L${mingw_LIBDIR}/theora/lib -L${mingw_LIBDIR}/vpx/lib -L${mingw_LIBDIR}/x264/lib -L${mingw_LIBDIR}/xvidcore/lib -L${mingw_LIBDIR}/zlib/lib")
+set(FFMPEG_CFLAGS "-I${mingw_LIBDIR}/lame/include -I${mingw_LIBDIR}/openjpeg/include/ -I${mingw_LIBDIR}/ogg/include -I${mingw_LIBDIR}/vorbis/include -I${mingw_LIBDIR}/theora/include -I${mingw_LIBDIR}/opus/include -I${mingw_LIBDIR}/vpx/include -I${mingw_LIBDIR}/x264/include -I${mingw_LIBDIR}/xvidcore/include -I${mingw_LIBDIR}/zlib/include")
+set(FFMPEG_LDFLAGS "-L${mingw_LIBDIR}/lame/lib -L${mingw_LIBDIR}/openjpeg/lib -L${mingw_LIBDIR}/ogg/lib -L${mingw_LIBDIR}/vorbis/lib -L${mingw_LIBDIR}/theora/lib -L${mingw_LIBDIR}/opus/lib -L${mingw_LIBDIR}/vpx/lib -L${mingw_LIBDIR}/x264/lib -L${mingw_LIBDIR}/xvidcore/lib -L${mingw_LIBDIR}/zlib/lib")
set(FFMPEG_EXTRA_FLAGS --pkg-config-flags=--static --extra-cflags=${FFMPEG_CFLAGS} --extra-ldflags=${FFMPEG_LDFLAGS})
-set(FFMPEG_ENV PKG_CONFIG_PATH=${mingw_LIBDIR}/openjpeg/lib/pkgconfig:${mingw_LIBDIR}/x264/lib/pkgconfig:${mingw_LIBDIR}/vorbis/lib/pkgconfig:${mingw_LIBDIR}/ogg/lib/pkgconfig:${mingw_LIBDIR})
+set(FFMPEG_ENV PKG_CONFIG_PATH=${mingw_LIBDIR}/openjpeg/lib/pkgconfig:${mingw_LIBDIR}/x264/lib/pkgconfig:${mingw_LIBDIR}/vorbis/lib/pkgconfig:${mingw_LIBDIR}/ogg/lib/pkgconfig:${mingw_LIBDIR}:${mingw_LIBDIR}/vpx/lib/pkgconfig:${mingw_LIBDIR}/theora/lib/pkgconfig:${mingw_LIBDIR}/openjpeg/lib/pkgconfig:${mingw_LIBDIR}/opus/lib/pkgconfig:)
if(WIN32)
set(FFMPEG_ENV set ${FFMPEG_ENV} &&)
@@ -73,6 +73,7 @@ ExternalProject_Add(external_ffmpeg
--disable-libgsm
--disable-libspeex
--enable-libvpx
+ --enable-libopus
--prefix=${LIBDIR}/ffmpeg
--enable-libtheora
--enable-libvorbis
@@ -130,6 +131,7 @@ add_dependencies(
external_openjpeg
external_xvidcore
external_x264
+ external_opus
external_vpx
external_theora
external_vorbis
diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake
index 526e72e2e33..cc596b2c786 100644
--- a/build_files/build_environment/cmake/harvest.cmake
+++ b/build_files/build_environment/cmake/harvest.cmake
@@ -192,6 +192,7 @@ harvest(theora/lib ffmpeg/lib "*.a")
harvest(tiff/include tiff/include "*.h")
harvest(tiff/lib tiff/lib "*.a")
harvest(vorbis/lib ffmpeg/lib "*.a")
+harvest(opus/lib ffmpeg/lib "*.a")
harvest(vpx/lib ffmpeg/lib "*.a")
harvest(webp/lib ffmpeg/lib "*.a")
harvest(x264/lib ffmpeg/lib "*.a")
@@ -199,4 +200,9 @@ harvest(xvidcore/lib ffmpeg/lib "*.a")
harvest(embree/include embree/include "*.h")
harvest(embree/lib embree/lib "*.a")
+if(UNIX AND NOT APPLE)
+ harvest(libglu/lib mesa/lib "*.so*")
+ harvest(mesa/lib mesa/lib "*.so*")
+endif()
+
endif()
diff --git a/build_files/build_environment/cmake/libglu.cmake b/build_files/build_environment/cmake/libglu.cmake
new file mode 100644
index 00000000000..d1b7647eca3
--- /dev/null
+++ b/build_files/build_environment/cmake/libglu.cmake
@@ -0,0 +1,40 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(LIBGLU_CFLAGS "-static-libgcc")
+set(LIBGLU_CXXFLAGS "-static-libgcc -static-libstdc++ -Bstatic -lstdc++ -Bdynamic -l:libstdc++.a")
+set(LIBGLU_LDFLAGS "-pthread -static-libgcc -static-libstdc++ -Bstatic -lstdc++ -Bdynamic -l:libstdc++.a")
+
+set(LIBGLU_EXTRA_FLAGS
+ CFLAGS=${LIBGLU_CFLAGS}
+ CXXFLAGS=${LIBGLU_CXXFLAGS}
+ LDFLAGS=${LIBGLU_LDFLAGS}
+)
+
+ExternalProject_Add(external_libglu
+ URL ${LIBGLU_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${LIBGLU_HASH}
+ PREFIX ${BUILD_DIR}/libglu
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} &&
+ cd ${BUILD_DIR}/libglu/src/external_libglu/ &&
+ ${CONFIGURE_COMMAND_NO_TARGET} --prefix=${LIBDIR}/libglu ${LIBGLU_EXTRA_FLAGS}
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/libglu/src/external_libglu/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/libglu/src/external_libglu/ && make install
+ INSTALL_DIR ${LIBDIR}/libglu
+)
diff --git a/build_files/build_environment/cmake/mesa.cmake b/build_files/build_environment/cmake/mesa.cmake
new file mode 100644
index 00000000000..6994d1c5813
--- /dev/null
+++ b/build_files/build_environment/cmake/mesa.cmake
@@ -0,0 +1,54 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(MESA_CFLAGS "-static-libgcc")
+set(MESA_CXXFLAGS "-static-libgcc -static-libstdc++ -Bstatic -lstdc++ -Bdynamic -l:libstdc++.a")
+set(MESA_LDFLAGS "-L${LIBDIR}/zlib/lib -pthread -static-libgcc -static-libstdc++ -Bstatic -lstdc++ -Bdynamic -l:libstdc++.a -l:libz_pic.a")
+
+set(MESA_EXTRA_FLAGS
+ CFLAGS=${MESA_CFLAGS}
+ CXXFLAGS=${MESA_CXXFLAGS}
+ LDFLAGS=${MESA_LDFLAGS}
+ --enable-glx=gallium-xlib
+ --with-gallium-drivers=swrast
+ --disable-dri
+ --disable-gbm
+ --disable-egl
+ --disable-gles1
+ --disable-gles2
+ --disable-llvm-shared-libs
+ --with-llvm-prefix=${LIBDIR}/llvm
+)
+
+ExternalProject_Add(external_mesa
+ URL ${MESA_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${MESA_HASH}
+ PREFIX ${BUILD_DIR}/mesa
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} &&
+ cd ${BUILD_DIR}/mesa/src/external_mesa/ &&
+ ${CONFIGURE_COMMAND_NO_TARGET} --prefix=${LIBDIR}/mesa ${MESA_EXTRA_FLAGS}
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/mesa/src/external_mesa/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/mesa/src/external_mesa/ && make install
+ INSTALL_DIR ${LIBDIR}/mesa
+)
+
+add_dependencies(
+ external_mesa
+ ll
+)
diff --git a/build_files/build_environment/cmake/opus.cmake b/build_files/build_environment/cmake/opus.cmake
new file mode 100644
index 00000000000..abaad94fa28
--- /dev/null
+++ b/build_files/build_environment/cmake/opus.cmake
@@ -0,0 +1,35 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_opus
+ URL ${OPUS_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH SHA256=${OPUS_HASH}
+ PREFIX ${BUILD_DIR}/opus
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/opus/src/external_opus/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/opus
+ --disable-shared
+ --enable-static
+ --with-pic
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/opus/src/external_opus/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/opus/src/external_opus/ && make install
+ INSTALL_DIR ${LIBDIR}/opus
+)
+
+if(MSVC)
+ set_target_properties(external_opus PROPERTIES FOLDER Mingw)
+endif()
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index c3b713096d6..1c9e5c5a4f6 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -192,6 +192,10 @@ set(VPX_VERSION 1.7.0)
set(VPX_URI https://github.com/webmproject/libvpx/archive/v${VPX_VERSION}/libvpx-v${VPX_VERSION}.tar.gz)
set(VPX_HASH 1fec931eb5c94279ad219a5b6e0202358e94a93a90cfb1603578c326abfc1238)
+set(OPUS_VERSION 1.3.1)
+set(OPUS_URI https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz)
+set(OPUS_HASH 65b58e1e25b2a114157014736a3d9dfeaad8d41be1c8179866f144a2fb44ff9d)
+
set(X264_URI http://download.videolan.org/pub/videolan/x264/snapshots/x264-snapshot-20180811-2245-stable.tar.bz2)
set(X264_HASH ae8a868a0e236a348b35d79f3ee80294b169d1195408b689f9851383661ed7aa)
@@ -306,3 +310,11 @@ set(EMBREE_HASH 3d4a1147002ff43939d45140aa9d6fb8)
set(OIDN_VERSION 1.0.0)
set(OIDN_URI https://github.com/OpenImageDenoise/oidn/releases/download/v${OIDN_VERSION}/oidn-${OIDN_VERSION}.src.zip)
set(OIDN_HASH 19fe67b0164e8f020ac8a4f520defe60)
+
+set(LIBGLU_VERSION 9.0.1)
+set(LIBGLU_URI ftp://ftp.freedesktop.org/pub/mesa/glu/glu-${LIBGLU_VERSION}.tar.xz)
+set(LIBGLU_HASH 151aef599b8259efe9acd599c96ea2a3)
+
+set(MESA_VERSION 18.3.1)
+set(MESA_URI ftp://ftp.freedesktop.org/pub/mesa//mesa-${MESA_VERSION}.tar.xz)
+set(MESA_HASH d60828056d77bfdbae0970f9b15fb1be)
diff --git a/build_files/build_environment/cmake/vpx.cmake b/build_files/build_environment/cmake/vpx.cmake
index 1c3a7081b59..741493859e2 100644
--- a/build_files/build_environment/cmake/vpx.cmake
+++ b/build_files/build_environment/cmake/vpx.cmake
@@ -49,6 +49,8 @@ ExternalProject_Add(external_vpx
--disable-avx2
--disable-unit-tests
--disable-examples
+ --enable-vp8
+ --enable-vp9
${VPX_EXTRA_FLAGS}
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/vpx/src/external_vpx/ && make -j${MAKE_THREADS}
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/vpx/src/external_vpx/ && make install
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index f594add3a5b..fd3ebe241a2 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -431,6 +431,9 @@ X264_VERSION_MIN=0.118
VPX_USE=false
VPX_VERSION_MIN=0.9.7
VPX_DEV=""
+OPUS_USE=false
+OPUS_VERSION_MIN=1.1.1
+OPUS_DEV=""
MP3LAME_USE=false
MP3LAME_DEV=""
OPENJPEG_USE=false
@@ -2754,6 +2757,10 @@ compile_FFmpeg() {
extra="$extra --enable-libvpx"
fi
+ if [ "$OPUS_USE" = true ]; then
+ extra="$extra --enable-libopus"
+ fi
+
if [ "$MP3LAME_USE" = true ]; then
extra="$extra --enable-libmp3lame"
fi
@@ -2991,6 +2998,14 @@ install_DEB() {
install_packages_DEB $VPX_DEV
VPX_USE=true
fi
+
+ PRINT ""
+ OPUS_DEV="libopus-dev"
+ check_package_version_ge_DEB $OPUS_DEV $OPUS_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_DEB $OPUS_DEV
+ OPUS_USE=true
+ fi
fi
# Check cmake/glew versions and disable features for older distros.
@@ -3601,8 +3616,17 @@ install_RPM() {
install_packages_RPM $VPX_DEV
VPX_USE=true
fi
+
PRINT ""
install_packages_RPM libspnav-devel
+
+ PRINT ""
+ OPUS_DEV="libopus-devel"
+ check_package_version_ge_RPM $OPUS_DEV $OPUS_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_RPM $OPUS_DEV
+ OPUS_USE=true
+ fi
fi
PRINT ""
@@ -4077,6 +4101,14 @@ install_ARCH() {
install_packages_ARCH $VPX_DEV
VPX_USE=true
fi
+
+ PRINT ""
+ OPUS_DEV="opus"
+ check_package_version_ge_ARCH $OPUS_DEV $OPUS_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_ARCH $OPUS_DEV
+ OPUS_USE=true
+ fi
fi
@@ -4633,6 +4665,10 @@ print_info_ffmpeglink() {
_packages="$_packages $VPX_DEV"
fi
+ if [ "$OPUS_USE" = true ]; then
+ _packages="$_packages $OPUS_DEV"
+ fi
+
if [ "$MP3LAME_USE" = true ]; then
_packages="$_packages $MP3LAME_DEV"
fi
diff --git a/build_files/buildbot/buildbot_utils.py b/build_files/buildbot/buildbot_utils.py
index 6891b91aa1e..eded6646671 100644
--- a/build_files/buildbot/buildbot_utils.py
+++ b/build_files/buildbot/buildbot_utils.py
@@ -20,6 +20,7 @@
import argparse
import os
+import re
import subprocess
import sys
@@ -27,6 +28,7 @@ class Builder:
def __init__(self, name, branch):
self.name = name
self.branch = branch
+ self.is_release_branch = re.match("^blender-v(.*)-release$", branch) is not None
# Buildbot runs from build/ directory
self.blender_dir = os.path.abspath(os.path.join('..', 'blender.git'))
diff --git a/build_files/buildbot/config/blender_linux.cmake b/build_files/buildbot/config/blender_linux.cmake
index 6806684e88b..2047c28deb9 100644
--- a/build_files/buildbot/config/blender_linux.cmake
+++ b/build_files/buildbot/config/blender_linux.cmake
@@ -2,33 +2,20 @@
include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/config/blender_release.cmake")
-# For libc-2.24 we are using chroot which runs on a 64bit system.
-# There we can not use CPU bitness check since it is always 64bit. So instead
-# we check for a specific libraries.
-#
-# Other builders we are running in a bare virtual machine, and the libraries
-# are installed to /opt/.
-# We assume that only 64bit builders exists in such configuration.
-if(EXISTS "/lib/x86_64-linux-gnu/libc-2.24.so")
- message(STATUS "Building in GLibc-2.24 environment")
- set(LIBDIR_NAME "linux_x86_64")
-elseif(EXISTS "/lib/i386-linux-gnu//libc-2.24.so")
- message(STATUS "Building in GLibc-2.24 environment")
- set(LIBDIR_NAME "linux_i686")
-else()
- message(STATUS "Building in generic 64bit environment")
- set(LIBDIR_NAME "linux_x86_64")
-endif()
+message(STATUS "Building in CentOS 7 64bit environment")
+set(LIBDIR_NAME "linux_centos7_x86_64")
# Default to only build Blender
set(WITH_BLENDER ON CACHE BOOL "" FORCE)
# ######## Linux-specific build options ########
# Options which are specific to Linux-only platforms
+
set(WITH_DOC_MANPAGE OFF CACHE BOOL "" FORCE)
# ######## Official release-specific build options ########
# Options which are specific to Linux release builds only
+
set(WITH_JACK_DYNLOAD ON CACHE BOOL "" FORCE)
set(WITH_SDL_DYNLOAD ON CACHE BOOL "" FORCE)
set(WITH_SYSTEM_GLEW OFF CACHE BOOL "" FORCE)
@@ -40,7 +27,7 @@ set(WITH_PYTHON_INSTALL_REQUESTS ON CACHE BOOL "" FORCE)
# ######## Release environment specific settings ########
-set(LIBDIR "/opt/blender-deps/${LIBDIR_NAME}" CACHE BOOL "" FORCE)
+set(LIBDIR "${CMAKE_CURRENT_LIST_DIR}/../../../../lib/${LIBDIR_NAME}" CACHE STRING "" FORCE)
# Platform specific configuration, to ensure static linking against everything.
diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py
index a7729843a0e..5bef2b81739 100644
--- a/build_files/buildbot/slave_pack.py
+++ b/build_files/buildbot/slave_pack.py
@@ -32,8 +32,9 @@ def get_package_name(builder, platform=None):
package_name = 'blender-' + info.full_version
if platform:
package_name += '-' + platform
- if builder.branch != 'master' and info.is_development_build:
- package_name = builder.branch + "-" + package_name
+ if not (builder.branch == 'master' or builder.is_release_branch):
+ if info.is_development_build:
+ package_name = builder.branch + "-" + package_name
return package_name
@@ -47,6 +48,7 @@ def create_buildbot_upload_zip(builder, package_files):
try:
z = zipfile.ZipFile(buildbot_upload_zip, "w", compression=zipfile.ZIP_STORED)
for filepath, filename in package_files:
+ print("Packaged", filename)
z.write(filepath, arcname=filename)
z.close()
except Exception as ex:
@@ -147,20 +149,6 @@ def pack_linux(builder):
py_target = os.path.join(builder.install_dir, info.version)
buildbot_utils.call(builder.command_prefix + ['find', py_target, '-iname', '*.so', '-exec', 'strip', '-s', '{}', ';'])
- # Copy all specific files which are too specific to be copied by
- # the CMake rules themselves
- print("Copying extra scripts and libs...")
-
- extra = '/' + os.path.join('home', 'sources', 'release-builder', 'extra')
- mesalibs = os.path.join(extra, 'mesalibs' + str(builder.bits) + '.tar.bz2')
- software_gl = os.path.join(builder.blender_dir, 'release', 'bin', 'blender-softwaregl')
- icons = os.path.join(builder.blender_dir, 'release', 'freedesktop', 'icons')
-
- os.system('tar -xpf %s -C %s' % (mesalibs, builder.install_dir))
- os.system('cp %s %s' % (software_gl, builder.install_dir))
- os.system('cp -r %s %s' % (icons, builder.install_dir))
- os.system('chmod 755 %s' % (os.path.join(builder.install_dir, 'blender-softwaregl')))
-
# Construct package name
platform_name = 'linux-' + blender_glibc + '-' + blender_arch
package_name = get_package_name(builder, platform_name)
diff --git a/build_files/buildbot/slave_update.py b/build_files/buildbot/slave_update.py
index 39f449b87bc..36a7ae31c84 100644
--- a/build_files/buildbot/slave_update.py
+++ b/build_files/buildbot/slave_update.py
@@ -28,4 +28,4 @@ if __name__ == "__main__":
# Run make update which handles all libraries and submodules.
make_update = os.path.join(builder.blender_dir, "build_files", "utils", "make_update.py")
- buildbot_utils.call([sys.executable, make_update, '--no-blender', "--use-tests"])
+ buildbot_utils.call([sys.executable, make_update, '--no-blender', "--use-tests", "--use-centos-libraries"])
diff --git a/build_files/cmake/Modules/GTestTesting.cmake b/build_files/cmake/Modules/GTestTesting.cmake
index 1c98a6456b8..a93e829e6b0 100644
--- a/build_files/cmake/Modules/GTestTesting.cmake
+++ b/build_files/cmake/Modules/GTestTesting.cmake
@@ -48,6 +48,14 @@ macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST)
if(WITH_OPENMP_STATIC)
target_link_libraries(${TARGET_NAME} ${OpenMP_LIBRARIES})
endif()
+
+ get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ if(GENERATOR_IS_MULTI_CONFIG)
+ string(REPLACE "\${BUILD_TYPE}" "$<CONFIG>" TEST_INSTALL_DIR ${CMAKE_INSTALL_PREFIX})
+ else()
+ string(REPLACE "\${BUILD_TYPE}" "" TEST_INSTALL_DIR ${CMAKE_INSTALL_PREFIX})
+ endif()
+
set_target_properties(${TARGET_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${TESTS_OUTPUT_DIR}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${TESTS_OUTPUT_DIR}"
diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake
index 403d38f6a05..4c47c4c4dba 100644
--- a/build_files/cmake/config/blender_full.cmake
+++ b/build_files/cmake/config/blender_full.cmake
@@ -49,6 +49,7 @@ set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION ON CACHE BOOL "" FORCE)
set(WITH_SDL ON CACHE BOOL "" FORCE)
+set(WITH_TBB ON CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)
set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index 37cbfa27972..6d0f160c764 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -54,5 +54,6 @@ set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
set(WITH_QUADRIFLOW OFF CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION OFF CACHE BOOL "" FORCE)
set(WITH_SDL OFF CACHE BOOL "" FORCE)
+set(WITH_TBB OFF CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE)
set(WITH_X11_XF86VMODE OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake
index cb338f40a7b..cf849519c83 100644
--- a/build_files/cmake/config/blender_release.cmake
+++ b/build_files/cmake/config/blender_release.cmake
@@ -50,6 +50,7 @@ set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION ON CACHE BOOL "" FORCE)
set(WITH_SDL ON CACHE BOOL "" FORCE)
+set(WITH_TBB ON CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)
set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index e159dd9e5ee..c3025be34ba 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -460,13 +460,16 @@ function(setup_liblinks
target_link_libraries(${target} ${OSL_LIBRARIES})
endif()
if(WITH_OPENVDB)
- target_link_libraries(${target} ${OPENVDB_LIBRARIES} ${TBB_LIBRARIES} ${BLOSC_LIBRARIES})
+ target_link_libraries(${target} ${OPENVDB_LIBRARIES} ${BLOSC_LIBRARIES})
endif()
if(WITH_OPENIMAGEIO)
target_link_libraries(${target} ${OPENIMAGEIO_LIBRARIES})
endif()
if(WITH_OPENIMAGEDENOISE)
- target_link_libraries(${target} ${OPENIMAGEDENOISE_LIBRARIES} ${TBB_LIBRARIES})
+ target_link_libraries(${target} ${OPENIMAGEDENOISE_LIBRARIES})
+ endif()
+ if(WITH_TBB)
+ target_link_libraries(${target} ${TBB_LIBRARIES})
endif()
if(WITH_OPENCOLORIO)
target_link_libraries(${target} ${OPENCOLORIO_LIBRARIES})
@@ -1209,7 +1212,9 @@ macro(openmp_delayload
)
if(MSVC)
if(WITH_OPENMP)
- if(MSVC_VERSION EQUAL 1800)
+ if(MSVC_CLANG)
+ set(OPENMP_DLL_NAME "libomp")
+ elseif(MSVC_VERSION EQUAL 1800)
set(OPENMP_DLL_NAME "vcomp120")
else()
set(OPENMP_DLL_NAME "vcomp140")
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index 249546dd216..3ae3b2b66b5 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -157,7 +157,7 @@ if(WITH_CODEC_FFMPEG)
avcodec avdevice avformat avutil
mp3lame swscale x264 xvidcore
theora theoradec theoraenc
- vorbis vorbisenc vorbisfile ogg
+ vorbis vorbisenc vorbisfile ogg opus
vpx swresample)
set(FFMPEG_LIBPATH ${FFMPEG}/lib)
endif()
@@ -313,9 +313,7 @@ endif()
if(WITH_OPENVDB)
set(OPENVDB ${LIBDIR}/openvdb)
set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
- set(TBB_INCLUDE_DIRS ${LIBDIR}/tbb/include)
- set(TBB_LIBRARIES ${LIBDIR}/tbb/lib/libtbb.a)
- set(OPENVDB_LIBRARIES openvdb blosc ${TBB_LIBRARIES})
+ set(OPENVDB_LIBRARIES openvdb blosc)
set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib)
set(OPENVDB_DEFINITIONS)
endif()
@@ -386,14 +384,25 @@ endif()
if(WITH_OPENIMAGEDENOISE)
find_package(OpenImageDenoise)
- find_package(TBB)
if(NOT OPENIMAGEDENOISE_FOUND)
set(WITH_OPENIMAGEDENOISE OFF)
message(STATUS "OpenImageDenoise not found")
- elseif(NOT TBB_FOUND)
+ endif()
+endif()
+
+if(WITH_TBB)
+ find_package(TBB)
+endif()
+
+if(NOT WITH_TBB OR NOT TBB_FOUND)
+ if(WITH_OPENIMAGEDENOISE)
+ message(STATUS "TBB not found, disabling OpenImageDenoise")
set(WITH_OPENIMAGEDENOISE OFF)
- message(STATUS "TBB not found")
+ endif()
+ if(WITH_OPENVDB)
+ message(STATUS "TBB not found, disabling OpenVDB")
+ set(WITH_OPENVDB OFF)
endif()
endif()
diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake
index 1b3f9cf3fad..c48780ebd6a 100644
--- a/build_files/cmake/platform/platform_unix.cmake
+++ b/build_files/cmake/platform/platform_unix.cmake
@@ -22,14 +22,30 @@
# Detect precompiled library directory
if(NOT DEFINED LIBDIR)
+ # Path to a locally compiled libraries.
set(LIBDIR_NAME ${CMAKE_SYSTEM_NAME}_${CMAKE_SYSTEM_PROCESSOR})
string(TOLOWER ${LIBDIR_NAME} LIBDIR_NAME)
- set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_NAME})
-else()
- message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
+ set(LIBDIR_NATIVE_ABI ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_NAME})
+
+ # Path to precompiled libraries with known CentOS 7 ABI.
+ set(LIBDIR_CENTOS7_ABI ${CMAKE_SOURCE_DIR}/../lib/linux_centos7_x86_64)
+
+ # Choose the best suitable libraries.
+ if(EXISTS ${LIBDIR_NATIVE_ABI})
+ set(LIBDIR ${LIBDIR_NATIVE_ABI})
+ elseif(EXISTS ${LIBDIR_CENTOS7_ABI})
+ set(LIBDIR ${LIBDIR_CENTOS7_ABI})
+ set(WITH_CXX11_ABI OFF)
+ endif()
+
+ # Avoid namespace pollustion.
+ unset(LIBDIR_NATIVE_ABI)
+ unset(LIBDIR_CENTOS7_ABI)
endif()
if(EXISTS ${LIBDIR})
+ message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
+
file(GLOB LIB_SUBDIRS ${LIBDIR}/*)
# NOTE: Make sure "proper" compiled zlib comes first before the one
# which is a part of OpenCollada. They have different ABI, and we
@@ -244,13 +260,8 @@ endif()
if(WITH_OPENVDB)
find_package_wrapper(OpenVDB)
- find_package_wrapper(TBB)
find_package_wrapper(Blosc)
- if(NOT TBB_FOUND)
- set(WITH_OPENVDB OFF)
- set(WITH_OPENVDB_BLOSC OFF)
- message(STATUS "TBB not found, disabling OpenVDB")
- elseif(NOT OPENVDB_FOUND)
+ if(NOT OPENVDB_FOUND)
set(WITH_OPENVDB OFF)
set(WITH_OPENVDB_BLOSC OFF)
message(STATUS "OpenVDB not found, disabling it")
@@ -416,6 +427,21 @@ if(WITH_OPENSUBDIV)
endif()
endif()
+if(WITH_TBB)
+ find_package_wrapper(TBB)
+endif()
+
+if(NOT WITH_TBB OR NOT TBB_FOUND)
+ if(WITH_OPENIMAGEDENOISE)
+ message(STATUS "TBB not found, disabling OpenImageDenoise")
+ set(WITH_OPENIMAGEDENOISE OFF)
+ endif()
+ if(WITH_OPENVDB)
+ message(STATUS "TBB not found, disabling OpenVDB")
+ set(WITH_OPENVDB OFF)
+ endif()
+endif()
+
# OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed
if(HAIKU)
list(APPEND PLATFORM_LINKLIBS -lnetwork)
diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake
index b2277c440fe..ef7722b0aef 100644
--- a/build_files/cmake/platform/platform_win32.cmake
+++ b/build_files/cmake/platform/platform_win32.cmake
@@ -35,6 +35,22 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
else()
message("Unable to detect the Visual Studio redist directory, copying of the runtime dlls will not work, try running from the visual studio developer prompt.")
endif()
+ # 1) CMake has issues detecting openmp support in clang-cl so we have to provide
+ # the right switches here.
+ # 2) While the /openmp switch *should* work, it currently doesn't as for clang 9.0.0
+ if(WITH_OPENMP)
+ set(OPENMP_CUSTOM ON)
+ set(OPENMP_FOUND ON)
+ set(OpenMP_C_FLAGS "/clang:-fopenmp")
+ set(OpenMP_CXX_FLAGS "/clang:-fopenmp")
+ GET_FILENAME_COMPONENT(LLVMROOT "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\LLVM\\LLVM;]" ABSOLUTE CACHE)
+ set(CLANG_OPENMP_DLL "${LLVMROOT}/bin/libomp.dll")
+ set(CLANG_OPENMP_LIB "${LLVMROOT}/lib/libomp.lib")
+ if(NOT EXISTS "${CLANG_OPENMP_DLL}")
+ message(FATAL_ERROR "Clang OpenMP library (${CLANG_OPENMP_DLL}) not found.")
+ endif()
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} \"${CLANG_OPENMP_LIB}\"")
+ endif()
endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ${WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS})
@@ -96,7 +112,7 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
list(APPEND PLATFORM_LINKLIBS
- ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32
+ ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 Comctl32
advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp
)
@@ -475,25 +491,20 @@ endif()
if(WITH_OPENVDB)
set(BLOSC_LIBRARIES optimized ${LIBDIR}/blosc/lib/libblosc.lib debug ${LIBDIR}/blosc/lib/libblosc_d.lib)
- set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib)
- set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include)
set(OPENVDB ${LIBDIR}/openVDB)
set(OPENVDB_LIBPATH ${OPENVDB}/lib)
- set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include ${TBB_INCLUDE_DIR})
- set(OPENVDB_LIBRARIES optimized ${OPENVDB_LIBPATH}/openvdb.lib debug ${OPENVDB_LIBPATH}/openvdb_d.lib ${TBB_LIBRARIES} ${BLOSC_LIBRARIES})
+ set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
+ set(OPENVDB_LIBRARIES optimized ${OPENVDB_LIBPATH}/openvdb.lib debug ${OPENVDB_LIBPATH}/openvdb_d.lib ${BLOSC_LIBRARIES})
set(OPENVDB_DEFINITIONS -DNOMINMAX)
endif()
if(WITH_OPENIMAGEDENOISE)
- set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib)
- set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include)
set(OPENIMAGEDENOISE ${LIBDIR}/OpenImageDenoise)
set(OPENIMAGEDENOISE_LIBPATH ${LIBDIR}/OpenImageDenoise/lib)
- set(OPENIMAGEDENOISE_INCLUDE_DIRS ${OPENIMAGEDENOISE}/include ${TBB_INCLUDE_DIR})
+ set(OPENIMAGEDENOISE_INCLUDE_DIRS ${OPENIMAGEDENOISE}/include)
set(OPENIMAGEDENOISE_LIBRARIES
optimized ${OPENIMAGEDENOISE_LIBPATH}/OpenImageDenoise.lib ${OPENIMAGEDENOISE_LIBPATH}/common.lib ${OPENIMAGEDENOISE_LIBPATH}/mkldnn.lib
- debug ${OPENIMAGEDENOISE_LIBPATH}/OpenImageDenoise_d.lib ${OPENIMAGEDENOISE_LIBPATH}/common_d.lib ${OPENIMAGEDENOISE_LIBPATH}/mkldnn_d.lib
- ${TBB_LIBRARIES})
+ debug ${OPENIMAGEDENOISE_LIBPATH}/OpenImageDenoise_d.lib ${OPENIMAGEDENOISE_LIBPATH}/common_d.lib ${OPENIMAGEDENOISE_LIBPATH}/mkldnn_d.lib)
set(OPENIMAGEDENOISE_DEFINITIONS)
endif()
@@ -558,6 +569,21 @@ if(WITH_SYSTEM_AUDASPACE)
set(AUDASPACE_PY_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace-py.lib)
endif()
+if(WITH_TBB)
+ set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib)
+ set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include)
+ set(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
+else()
+ if(WITH_OPENIMAGEDENOISE)
+ message(STATUS "TBB disabled, also disabling OpenImageDenoise")
+ set(WITH_OPENIMAGEDENOISE OFF)
+ endif()
+ if(WITH_OPENVDB)
+ message(STATUS "TBB disabled, also disabling OpenVDB")
+ set(WITH_OPENVDB OFF)
+ endif()
+endif()
+
# used in many places so include globally, like OpenGL
blender_include_dirs_sys("${PTHREADS_INCLUDE_DIRS}")
diff --git a/build_files/utils/make_test.py b/build_files/utils/make_test.py
index a8a6afc43cc..309ab36ecdd 100755
--- a/build_files/utils/make_test.py
+++ b/build_files/utils/make_test.py
@@ -39,7 +39,8 @@ if make_utils.command_missing(git_command):
sys.exit(1)
# Test if we are building a specific release version.
-release_version = make_utils.git_branch_release_version(git_command)
+branch = make_utils.git_branch(git_command)
+release_version = make_utils.git_branch_release_version(branch)
lib_tests_dirpath = os.path.join('..', 'lib', "tests")
if not os.path.exists(lib_tests_dirpath):
diff --git a/build_files/utils/make_update.py b/build_files/utils/make_update.py
index 3ecfa218432..ec72514fdfc 100755
--- a/build_files/utils/make_update.py
+++ b/build_files/utils/make_update.py
@@ -28,13 +28,17 @@ def parse_arguments():
parser.add_argument("--use-tests", action="store_true")
parser.add_argument("--svn-command", default="svn")
parser.add_argument("--git-command", default="git")
+ parser.add_argument("--use-centos-libraries", action="store_true")
return parser.parse_args()
+def get_blender_git_root():
+ return check_output([args.git_command, "rev-parse", "--show-toplevel"])
+
# Setup for precompiled libraries and tests from svn.
def svn_update(args, release_version):
svn_non_interactive = [args.svn_command, '--non-interactive']
- lib_dirpath = os.path.join('..', 'lib')
+ lib_dirpath = os.path.join(get_blender_git_root(), '..', 'lib')
svn_url = make_utils.svn_libraries_base_url(release_version)
# Checkout precompiled libraries
@@ -45,6 +49,8 @@ def svn_update(args, release_version):
# this script is bundled as part of the precompiled libraries. However it
# is used by the buildbot.
lib_platform = "win64_vc14"
+ elif args.use_centos_libraries:
+ lib_platform = "linux_centos7_x86_64"
else:
# No precompiled libraries for Linux.
lib_platform = None
@@ -81,10 +87,14 @@ def svn_update(args, release_version):
if os.path.isdir(lib_dirpath):
for dirname in os.listdir(lib_dirpath):
+ dirpath = os.path.join(lib_dirpath, dirname)
+
if dirname == ".svn":
+ # Cleanup must be run from svn root directory if it exists.
+ if not make_utils.command_missing(args.svn_command):
+ call(svn_non_interactive + ["cleanup", lib_dirpath])
continue
- dirpath = os.path.join(lib_dirpath, dirname)
svn_dirpath = os.path.join(dirpath, ".svn")
svn_root_dirpath = os.path.join(lib_dirpath, ".svn")
@@ -94,21 +104,23 @@ def svn_update(args, release_version):
sys.stderr.write("svn not found, can't update libraries\n")
sys.exit(1)
- call(svn_non_interactive + ["cleanup", dirpath])
+ # Cleanup to continue with interrupted downloads.
+ if os.path.exists(svn_dirpath):
+ call(svn_non_interactive + ["cleanup", dirpath])
+ # Switch to appropriate branch and update.
call(svn_non_interactive + ["switch", svn_url + dirname, dirpath])
call(svn_non_interactive + ["update", dirpath])
-
-# Update blender repository.
-def blender_update_skip(args):
+# Test if git repo can be updated.
+def git_update_skip(args, check_remote_exists=True):
if make_utils.command_missing(args.git_command):
sys.stderr.write("git not found, can't update code\n")
sys.exit(1)
# Abort if a rebase is still progress.
- rebase_merge = check_output([args.git_command, 'rev-parse', '--git-path', 'rebase-merge'])
- rebase_apply = check_output([args.git_command, 'rev-parse', '--git-path', 'rebase-apply'])
- merge_head = check_output([args.git_command, 'rev-parse', '--git-path', 'MERGE_HEAD'])
+ rebase_merge = check_output([args.git_command, 'rev-parse', '--git-path', 'rebase-merge'], exit_on_error=False)
+ rebase_apply = check_output([args.git_command, 'rev-parse', '--git-path', 'rebase-apply'], exit_on_error=False)
+ merge_head = check_output([args.git_command, 'rev-parse', '--git-path', 'MERGE_HEAD'], exit_on_error=False)
if os.path.exists(rebase_merge) or \
os.path.exists(rebase_apply) or \
os.path.exists(merge_head):
@@ -120,49 +132,92 @@ def blender_update_skip(args):
return "you have unstaged changes"
# Test if there is an upstream branch configured
- branch = check_output([args.git_command, "rev-parse", "--abbrev-ref", "HEAD"])
- remote = check_output([args.git_command, "config", "branch." + branch + ".remote"], exit_on_error=False)
- if len(remote) == 0:
- return "no remote branch to pull from"
+ if check_remote_exists:
+ branch = check_output([args.git_command, "rev-parse", "--abbrev-ref", "HEAD"])
+ remote = check_output([args.git_command, "config", "branch." + branch + ".remote"], exit_on_error=False)
+ if len(remote) == 0:
+ return "no remote branch to pull from"
- return None
+ return ""
+# Update blender repository.
def blender_update(args):
print_stage("Updating Blender Git Repository")
call([args.git_command, "pull", "--rebase"])
# Update submodules.
-def submodules_update(args, release_version):
+def submodules_update(args, release_version, branch):
print_stage("Updating Submodules")
if make_utils.command_missing(args.git_command):
sys.stderr.write("git not found, can't update code\n")
sys.exit(1)
- call([args.git_command, "submodule", "update", "--init", "--recursive"])
+ # Update submodules to latest master or appropriate release branch.
if not release_version:
- # Update submodules to latest master if not building a specific release.
- # In that case submodules are set to a specific revision, which is checked
- # out by running "git submodule update".
- call([args.git_command, "submodule", "foreach", "git", "checkout", "master"])
- call([args.git_command, "submodule", "foreach", "git", "pull", "--rebase", "origin", "master"])
+ branch = "master"
+
+ submodules = [
+ ("release/scripts/addons", branch),
+ ("release/scripts/addons_contrib", branch),
+ ("release/datafiles/locale", branch),
+ ("source/tools", branch),
+ ]
+
+ # Initialize submodules only if needed.
+ for submodule_path, submodule_branch in submodules:
+ if not os.path.exists(os.path.join(submodule_path, ".git")):
+ call([args.git_command, "submodule", "update", "--init", "--recursive"])
+ break
+
+ # Checkout appropriate branch and pull changes.
+ skip_msg = ""
+ for submodule_path, submodule_branch in submodules:
+ cwd = os.getcwd()
+ try:
+ os.chdir(submodule_path)
+ msg = git_update_skip(args, check_remote_exists=False)
+ if msg:
+ skip_msg += submodule_path + " skipped: " + msg + "\n"
+ else:
+ if make_utils.git_branch(args.git_command) != submodule_branch:
+ call([args.git_command, "fetch", "origin"])
+ call([args.git_command, "checkout", submodule_branch])
+ call([args.git_command, "pull", "--rebase", "origin", submodule_branch])
+ finally:
+ os.chdir(cwd)
+
+ return skip_msg
if __name__ == "__main__":
args = parse_arguments()
- blender_skipped = None
+ blender_skip_msg = ""
+ submodules_skip_msg = ""
# Test if we are building a specific release version.
- release_version = make_utils.git_branch_release_version(args.git_command)
+ branch = make_utils.git_branch(args.git_command)
+ release_version = make_utils.git_branch_release_version(branch)
if not args.no_libraries:
svn_update(args, release_version)
if not args.no_blender:
- blender_skipped = blender_update_skip(args)
- if not blender_skipped:
+ blender_skip_msg = git_update_skip(args)
+ if blender_skip_msg:
+ blender_skip_msg = "Blender repository skipped: " + blender_skip_msg + "\n"
+ else:
blender_update(args)
if not args.no_submodules:
- submodules_update(args, release_version)
-
- if blender_skipped:
- print_stage("Blender repository skipped: " + blender_skipped)
+ submodules_skip_msg = submodules_update(args, release_version, branch)
+
+ # Report any skipped repositories at the end, so it's not as easy to miss.
+ skip_msg = blender_skip_msg + submodules_skip_msg
+ if skip_msg:
+ print_stage(skip_msg.strip())
+
+ # For failed submodule update we throw an error, since not having correct
+ # submodules can make Blender throw errors.
+ # For Blender itself we don't and consider "make update" to be a command
+ # you can use while working on uncommitted code.
+ if submodules_skip_msg:
+ sys.exit(1)
diff --git a/build_files/utils/make_utils.py b/build_files/utils/make_utils.py
index 5fedd792149..7b21bc607a4 100755
--- a/build_files/utils/make_utils.py
+++ b/build_files/utils/make_utils.py
@@ -35,7 +35,7 @@ def check_output(cmd, exit_on_error=True):
return output.strip()
-def git_branch_release_version(git_command):
+def git_branch(git_command):
# Test if we are building a specific release version.
try:
branch = subprocess.check_output([git_command, "rev-parse", "--abbrev-ref", "HEAD"])
@@ -43,7 +43,9 @@ def git_branch_release_version(git_command):
sys.stderr.write("Failed to get Blender git branch\n")
sys.exit(1)
- branch = branch.strip().decode('utf8')
+ return branch.strip().decode('utf8')
+
+def git_branch_release_version(branch):
release_version = re.search("^blender-v(.*)-release$", branch)
if release_version:
release_version = release_version.group(1)
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile
index 366d0b1b507..4380b94890a 100644
--- a/doc/doxygen/Doxyfile
+++ b/doc/doxygen/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = "V2.81"
+PROJECT_NUMBER = "V2.82"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
diff --git a/doc/python_api/sphinx_doc_update.py b/doc/python_api/sphinx_doc_update.py
index 995991c4afd..78bfd3c85b8 100755
--- a/doc/python_api/sphinx_doc_update.py
+++ b/doc/python_api/sphinx_doc_update.py
@@ -94,10 +94,10 @@ def main():
rsync_base = "rsync://%s@%s:%s" % (args.user, args.rsync_server, args.rsync_root)
- blenver = blenver_zip = ""
+ blenver = api_blenver = api_blenver_zip = ""
api_name = ""
branch = ""
- is_release = False
+ is_release = is_beta = False
# I) Update local mirror using rsync.
rsync_mirror_cmd = ("rsync", "--delete-after", "-avzz", rsync_base, args.mirror_dir)
@@ -118,11 +118,14 @@ def main():
"import sys, bpy\n"
"with open(sys.argv[-1], 'w') as f:\n"
" is_release = bpy.app.version_cycle in {'rc', 'release'}\n"
+ " is_beta = bpy.app.version_cycle in {'beta'}\n"
" branch = bpy.app.build_branch.split()[0].decode()\n"
" f.write('%d\\n' % is_release)\n"
+ " f.write('%d\\n' % is_beta)\n"
" f.write('%s\\n' % branch)\n"
+ " f.write('%d.%d%s\\n' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char))\n"
" f.write('%d.%d%s\\n' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n"
- " if is_release else '%s\\n' % branch)\n"
+ " if (is_release or is_beta) else '%s\\n' % branch)\n"
" f.write('%d_%d%s_release' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n"
" if is_release else '%d_%d_%d' % bpy.app.version)\n"
)
@@ -130,8 +133,9 @@ def main():
"--python-expr", getver_script, "--", getver_file)
subprocess.run(get_ver_cmd)
with open(getver_file) as f:
- is_release, branch, blenver, blenver_zip = f.read().split("\n")
+ is_release, is_beta, branch, blenver, api_blenver, api_blenver_zip = f.read().split("\n")
is_release = bool(int(is_release))
+ is_beta = bool(int(is_beta))
os.remove(getver_file)
# IV) Build doc.
@@ -143,14 +147,17 @@ def main():
os.chdir(curr_dir)
# V) Cleanup existing matching dir in server mirror (if any), and copy new doc.
- api_name = blenver
+ api_name = api_blenver
api_dir = os.path.join(args.mirror_dir, api_name)
if os.path.exists(api_dir):
- shutil.rmtree(api_dir)
+ if os.path.islink(api_dir):
+ os.remove(api_dir)
+ else:
+ shutil.rmtree(api_dir)
os.rename(os.path.join(tmp_dir, "sphinx-out"), api_dir)
# VI) Create zip archive.
- zip_name = "blender_python_reference_%s" % blenver_zip # We can't use 'release' postfix here...
+ zip_name = "blender_python_reference_%s" % api_blenver_zip # We can't use 'release' postfix here...
zip_path = os.path.join(args.mirror_dir, zip_name)
with zipfile.ZipFile(zip_path, 'w') as zf:
for dirname, _, filenames in os.walk(api_dir):
@@ -163,12 +170,27 @@ def main():
# VII) Create symlinks and html redirects.
if is_release:
symlink = os.path.join(args.mirror_dir, "current")
- os.remove(symlink)
+ if os.path.exists(symlink):
+ if os.path.islink(symlink):
+ os.remove(symlink)
+ else:
+ shutil.rmtree(symlink)
os.symlink("./%s" % api_name, symlink)
with open(os.path.join(args.mirror_dir, "250PythonDoc/index.html"), 'w') as f:
f.write("<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\""
"content=\"0;url=../%s/\"></head><body>Redirecting...</body></html>" % api_name)
+ elif is_beta:
+ # We do not have any particular symlink for that stage.
+ pass
elif branch == "master":
+ # Also create a symlink from version number to actual master api doc.
+ symlink = os.path.join(args.mirror_dir, blenver)
+ if os.path.exists(symlink):
+ if os.path.islink(symlink):
+ os.remove(symlink)
+ else:
+ shutil.rmtree(symlink)
+ os.symlink("./%s" % api_name, symlink)
with open(os.path.join(args.mirror_dir, "blender_python_api/index.html"), 'w') as f:
f.write("<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\""
"content=\"0;url=../%s/\"></head><body>Redirecting...</body></html>" % api_name)
diff --git a/extern/audaspace/src/devices/SoftwareDevice.cpp b/extern/audaspace/src/devices/SoftwareDevice.cpp
index c944b9ed12d..8c16c75e8e3 100644
--- a/extern/audaspace/src/devices/SoftwareDevice.cpp
+++ b/extern/audaspace/src/devices/SoftwareDevice.cpp
@@ -78,7 +78,7 @@ bool SoftwareDevice::SoftwareHandle::pause(bool keep)
}
SoftwareDevice::SoftwareHandle::SoftwareHandle(SoftwareDevice* device, std::shared_ptr<IReader> reader, std::shared_ptr<PitchReader> pitch, std::shared_ptr<ResampleReader> resampler, std::shared_ptr<ChannelMapperReader> mapper, bool keep) :
- m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(1.0f), m_old_volume(0), m_loopcount(0),
+ m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(0.0f), m_old_volume(0.0f), m_loopcount(0),
m_relative(true), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()),
m_distance_reference(1.0f), m_attenuation(1.0f), m_cone_angle_outer(M_PI), m_cone_angle_inner(M_PI), m_cone_volume_outer(0),
m_flags(RENDER_CONE), m_stop(nullptr), m_stop_data(nullptr), m_status(STATUS_PLAYING), m_device(device)
diff --git a/extern/cuew/src/cuew.c b/extern/cuew/src/cuew.c
index 1f386c4e5d3..a0146741494 100644
--- a/extern/cuew/src/cuew.c
+++ b/extern/cuew/src/cuew.c
@@ -859,6 +859,23 @@ int cuewNvrtcVersion(void) {
return 0;
}
+static size_t safe_strnlen(const char *s, size_t maxlen) {
+ size_t length;
+ for (length = 0; length < maxlen; s++, length++) {
+ if (*s == '\0') {
+ break;
+ }
+ }
+ return length;
+}
+
+static char *safe_strncpy(char *dest, const char *src, size_t n) {
+ const size_t src_len = safe_strnlen(src, n - 1);
+ memcpy(dest, src, src_len);
+ dest[src_len] = '\0';
+ return dest;
+}
+
int cuewCompilerVersion(void) {
const char *path = cuewCompilerPath();
const char *marker = "Cuda compilation tools, release ";
@@ -874,7 +891,7 @@ int cuewCompilerVersion(void) {
}
/* get --version output */
- strncpy(command, path, sizeof(command));
+ safe_strncpy(command, path, sizeof(command));
strncat(command, " --version", sizeof(command) - strlen(path));
pipe = popen(command, "r");
if (!pipe) {
diff --git a/extern/quadriflow/CMakeLists.txt b/extern/quadriflow/CMakeLists.txt
index 3891079073e..2e13bf17b17 100644
--- a/extern/quadriflow/CMakeLists.txt
+++ b/extern/quadriflow/CMakeLists.txt
@@ -23,6 +23,9 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
add_c_flag(
"-Wno-unused-result"
)
+ remove_cc_flag(
+ "-Wmissing-declarations"
+ )
endif()
set(CMAKE_CXX_STANDARD 14)
diff --git a/extern/quadriflow/patches/blender.patch b/extern/quadriflow/patches/blender.patch
index d131abc52e2..55fdd123e3b 100644
--- a/extern/quadriflow/patches/blender.patch
+++ b/extern/quadriflow/patches/blender.patch
@@ -1,3 +1,19 @@
+diff --git a/extern/quadriflow/src/config.hpp b/extern/quadriflow/src/config.hpp
+index 842b885..bf597ad 100644
+--- a/extern/quadriflow/src/config.hpp
++++ b/extern/quadriflow/src/config.hpp
+@@ -1,6 +1,11 @@
+ #ifndef CONFIG_H_
+ #define CONFIG_H_
+
++/* Workaround a bug in boost 1.68, until we upgrade to a newer version. */
++#if defined(__clang__) && defined(WIN32)
++ #include <boost/type_traits/is_assignable.hpp>
++ using namespace boost;
++#endif
+ // Move settings to cmake to make CMake happy :)
+
+ // #define WITH_SCALE
diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.cc
index 35a73d9..0eeba8a 100644
--- a/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.cc
diff --git a/extern/quadriflow/src/config.hpp b/extern/quadriflow/src/config.hpp
index 842b885a209..bf597ad0f39 100644
--- a/extern/quadriflow/src/config.hpp
+++ b/extern/quadriflow/src/config.hpp
@@ -1,6 +1,11 @@
#ifndef CONFIG_H_
#define CONFIG_H_
+/* Workaround a bug in boost 1.68, until we upgrade to a newer version. */
+#if defined(__clang__) && defined(WIN32)
+ #include <boost/type_traits/is_assignable.hpp>
+ using namespace boost;
+#endif
// Move settings to cmake to make CMake happy :)
// #define WITH_SCALE
diff --git a/intern/clog/clog.c b/intern/clog/clog.c
index da94acd97b1..9074e0f85e1 100644
--- a/intern/clog/clog.c
+++ b/intern/clog/clog.c
@@ -174,6 +174,7 @@ static void clg_str_append(CLogStringBuf *cstr, const char *str)
clg_str_append_with_len(cstr, str, strlen(str));
}
+ATTR_PRINTF_FORMAT(2, 0)
static void clg_str_vappendf(CLogStringBuf *cstr, const char *fmt, va_list args)
{
/* Use limit because windows may use '-1' for a formatting error. */
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 59509d20fb2..5520cfd5ecf 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -541,7 +541,6 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
const bool show_lights = BlenderViewportParameters(b_v3d).use_scene_lights;
BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
- const bool has_local_view = b_v3d && b_v3d.local_view();
BL::Depsgraph::object_instances_iterator b_instance_iter;
for (b_depsgraph.object_instances.begin(b_instance_iter);
@@ -555,10 +554,10 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
/* test if object needs to be hidden */
const bool show_self = b_instance.show_self();
- const bool show_local_view = !has_local_view || b_ob.local_view_get(b_v3d);
const bool show_particles = b_instance.show_particles();
+ const bool show_in_viewport = !b_v3d || b_ob.visible_in_viewport_get(b_v3d);
- if (show_local_view && (show_self || show_particles)) {
+ if (show_in_viewport && (show_self || show_particles)) {
/* object itself */
sync_object(b_depsgraph,
b_view_layer,
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 362155f22ac..22dbc3fba79 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -1340,6 +1340,14 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
graph->connect(background->output("Background"), out->input("Surface"));
}
else if (!new_viewport_parameters.use_scene_world) {
+ float3 world_color;
+ if (b_world) {
+ world_color = get_float3(b_world.color());
+ }
+ else {
+ world_color = make_float3(0.0f, 0.0f, 0.0f);
+ }
+
BackgroundNode *background = new BackgroundNode();
graph->add(background);
@@ -1347,7 +1355,7 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
graph->add(light_path);
MixNode *mix_scene_with_background = new MixNode();
- mix_scene_with_background->color2 = get_float3(b_world.color());
+ mix_scene_with_background->color2 = world_color;
graph->add(mix_scene_with_background);
EnvironmentTextureNode *texture_environment = new EnvironmentTextureNode();
@@ -1369,7 +1377,7 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
MixNode *mix_background_with_environment = new MixNode();
mix_background_with_environment->fac = new_viewport_parameters.studiolight_background_alpha;
- mix_background_with_environment->color1 = get_float3(b_world.color());
+ mix_background_with_environment->color1 = world_color;
graph->add(mix_background_with_environment);
ShaderNode *out = graph->output();
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 00dd37f089c..b5e10b0c2cb 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -454,6 +454,12 @@ class CUDADevice : public Device {
VLOG(1) << "Using precompiled kernel.";
return cubin;
}
+ const string ptx = path_get(string_printf("lib/%s_compute_%d%d.ptx", name, major, minor));
+ VLOG(1) << "Testing for pre-compiled kernel " << ptx << ".";
+ if (path_exists(ptx)) {
+ VLOG(1) << "Using precompiled kernel.";
+ return ptx;
+ }
}
const string common_cflags = compile_kernel_get_common_cflags(
diff --git a/intern/cycles/device/device_optix.cpp b/intern/cycles/device/device_optix.cpp
index b745235aed5..6f4734059da 100644
--- a/intern/cycles/device/device_optix.cpp
+++ b/intern/cycles/device/device_optix.cpp
@@ -169,6 +169,7 @@ class OptiXDevice : public Device {
OptixModule optix_module = NULL;
OptixPipeline pipelines[NUM_PIPELINES] = {};
+ bool motion_blur = false;
bool need_texture_info = false;
device_vector<SbtRecord> sbt_data;
device_vector<TextureInfo> texture_info;
@@ -337,7 +338,12 @@ class OptiXDevice : public Device {
# endif
pipeline_options.pipelineLaunchParamsVariableName = "__params"; // See kernel_globals.h
- if (requested_features.use_object_motion) {
+ // Keep track of whether motion blur is enabled, so to enable/disable motion in BVH builds
+ // This is necessary since objects may be reported to have motion if the Vector pass is
+ // active, but may still need to be rendered without motion blur if that isn't active as well
+ motion_blur = requested_features.use_object_motion;
+
+ if (motion_blur) {
pipeline_options.usesMotionBlur = true;
// Motion blur can insert motion transforms into the traversal graph
// It is no longer a two-level graph then, so need to set flags to allow any configuration
@@ -872,7 +878,7 @@ class OptiXDevice : public Device {
size_t num_motion_steps = 1;
Attribute *motion_keys = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (mesh->use_motion_blur && motion_keys) {
+ if (motion_blur && mesh->use_motion_blur && motion_keys) {
num_motion_steps = mesh->motion_steps;
}
@@ -942,7 +948,7 @@ class OptiXDevice : public Device {
size_t num_motion_steps = 1;
Attribute *motion_keys = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (mesh->use_motion_blur && motion_keys) {
+ if (motion_blur && mesh->use_motion_blur && motion_keys) {
num_motion_steps = mesh->motion_steps;
}
@@ -1041,7 +1047,7 @@ class OptiXDevice : public Device {
instance.visibilityMask = (ob->mesh->has_volume ? 3 : 1);
// Insert motion traversable if object has motion
- if (ob->use_motion()) {
+ if (motion_blur && ob->use_motion()) {
blas.emplace_back(this, "motion_transform");
device_only_memory<uint8_t> &motion_transform_gpu = blas.back();
motion_transform_gpu.alloc_to_device(sizeof(OptixSRTMotionTransform) +
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index ea8aa197b6f..78da584e132 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -389,11 +389,20 @@ if(WITH_CYCLES_CUDA_BINARIES)
set(cuda_cubins)
macro(CYCLES_CUDA_KERNEL_ADD arch prev_arch name flags sources experimental)
- set(cuda_cubin ${name}_${arch}.cubin)
+ if(${arch} MATCHES "compute_.*")
+ set(format "ptx")
+ else()
+ set(format "cubin")
+ endif()
+ set(cuda_file ${name}_${arch}.${format})
set(kernel_sources ${sources})
if(NOT ${prev_arch} STREQUAL "none")
- set(kernel_sources ${kernel_sources} ${name}_${prev_arch}.cubin)
+ if(${prev_arch} MATCHES "compute_.*")
+ set(kernel_sources ${kernel_sources} ${name}_${prev_arch}.ptx)
+ else()
+ set(kernel_sources ${kernel_sources} ${name}_${prev_arch}.cubin)
+ endif()
endif()
set(cuda_kernel_src "/kernels/cuda/${name}.cu")
@@ -406,7 +415,7 @@ if(WITH_CYCLES_CUDA_BINARIES)
-I ${CMAKE_CURRENT_SOURCE_DIR}/..
-I ${CMAKE_CURRENT_SOURCE_DIR}/kernels/cuda
--use_fast_math
- -o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin})
+ -o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_file})
if(${experimental})
set(cuda_flags ${cuda_flags} -D __KERNEL_EXPERIMENTAL__)
@@ -440,20 +449,21 @@ if(WITH_CYCLES_CUDA_BINARIES)
-v
-cuda-toolkit-dir "${CUDA_TOOLKIT_ROOT_DIR}"
DEPENDS ${kernel_sources} cycles_cubin_cc)
+ set(cuda_file ${cuda_cubin})
else()
add_custom_command(
- OUTPUT ${cuda_cubin}
+ OUTPUT ${cuda_file}
COMMAND ${CUDA_NVCC_EXECUTABLE}
-arch=${arch}
${CUDA_NVCC_FLAGS}
- --cubin
+ --${format}
${CMAKE_CURRENT_SOURCE_DIR}${cuda_kernel_src}
--ptxas-options="-v"
${cuda_flags}
DEPENDS ${kernel_sources})
endif()
- delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${cuda_cubin}" ${CYCLES_INSTALL_PATH}/lib)
- list(APPEND cuda_cubins ${cuda_cubin})
+ delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${cuda_file}" ${CYCLES_INSTALL_PATH}/lib)
+ list(APPEND cuda_cubins ${cuda_file})
unset(cuda_debug_flags)
endmacro()
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index d45ffe9c7df..55abe39c465 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -459,7 +459,9 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
throughput /= probability;
}
+# ifdef __DENOISING_FEATURES__
kernel_update_denoising_features(kg, sd, state, L);
+# endif
# ifdef __AO__
/* ambient occlusion */
diff --git a/intern/cycles/kernel/shaders/node_mix.osl b/intern/cycles/kernel/shaders/node_mix.osl
index 8caea6803ed..9fbd3391ade 100644
--- a/intern/cycles/kernel/shaders/node_mix.osl
+++ b/intern/cycles/kernel/shaders/node_mix.osl
@@ -91,12 +91,12 @@ color node_mix_diff(float t, color col1, color col2)
color node_mix_dark(float t, color col1, color col2)
{
- return min(col1, col2) * t + col1 * (1.0 - t);
+ return mix(col1, min(col1, col2), t);
}
color node_mix_light(float t, color col1, color col2)
{
- return max(col1, col2 * t);
+ return mix(col1, max(col1, col2), t);
}
color node_mix_dodge(float t, color col1, color col2)
diff --git a/intern/cycles/kernel/svm/svm_color_util.h b/intern/cycles/kernel/svm/svm_color_util.h
index 0f571eb7253..1a0fa03305e 100644
--- a/intern/cycles/kernel/svm/svm_color_util.h
+++ b/intern/cycles/kernel/svm/svm_color_util.h
@@ -92,12 +92,12 @@ ccl_device float3 svm_mix_diff(float t, float3 col1, float3 col2)
ccl_device float3 svm_mix_dark(float t, float3 col1, float3 col2)
{
- return min(col1, col2) * t + col1 * (1.0f - t);
+ return interp(col1, min(col1, col2), t);
}
ccl_device float3 svm_mix_light(float t, float3 col1, float3 col2)
{
- return max(col1, col2 * t);
+ return interp(col1, max(col1, col2), t);
}
ccl_device float3 svm_mix_dodge(float t, float3 col1, float3 col2)
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 71f1863ea49..b58e10a7b52 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -5567,11 +5567,21 @@ void MapRangeNode::expand(ShaderGraph *graph)
ShaderOutput *result_out = output("Result");
if (!result_out->links.empty()) {
ClampNode *clamp_node = new ClampNode();
- clamp_node->min = to_min;
- clamp_node->max = to_max;
graph->add(clamp_node);
graph->relink(result_out, clamp_node->output("Result"));
graph->connect(result_out, clamp_node->input("Value"));
+ if (input("To Min")->link) {
+ graph->connect(input("To Min")->link, clamp_node->input("Min"));
+ }
+ else {
+ clamp_node->min = to_min;
+ }
+ if (input("To Max")->link) {
+ graph->connect(input("To Max")->link, clamp_node->input("Max"));
+ }
+ else {
+ clamp_node->max = to_max;
+ }
}
}
}
diff --git a/intern/cycles/util/util_defines.h b/intern/cycles/util/util_defines.h
index 2778cffba3a..b29d4163133 100644
--- a/intern/cycles/util/util_defines.h
+++ b/intern/cycles/util/util_defines.h
@@ -16,127 +16,127 @@
*/
#ifndef __UTIL_DEFINES_H__
-# define __UTIL_DEFINES_H__
+#define __UTIL_DEFINES_H__
/* Bitness */
-# if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || \
- defined(_M_X64)
-# define __KERNEL_64_BIT__
-# endif
+#if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || \
+ defined(_M_X64)
+# define __KERNEL_64_BIT__
+#endif
/* Qualifiers for kernel code shared by CPU and GPU */
-# ifndef __KERNEL_GPU__
-# define ccl_device static inline
-# define ccl_device_noinline static
-# define ccl_device_noinline_cpu ccl_device_noinline
-# define ccl_global
-# define ccl_static_constant static const
-# define ccl_constant const
-# define ccl_local
-# define ccl_local_param
-# define ccl_private
-# define ccl_restrict __restrict
-# define ccl_ref &
-# define ccl_optional_struct_init
-# define __KERNEL_WITH_SSE_ALIGN__
-
-# if defined(_WIN32) && !defined(FREE_WINDOWS)
-# define ccl_device_inline static __forceinline
-# define ccl_device_forceinline static __forceinline
-# define ccl_align(...) __declspec(align(__VA_ARGS__))
-# ifdef __KERNEL_64_BIT__
-# define ccl_try_align(...) __declspec(align(__VA_ARGS__))
-# else /* __KERNEL_64_BIT__ */
-# undef __KERNEL_WITH_SSE_ALIGN__
+#ifndef __KERNEL_GPU__
+# define ccl_device static inline
+# define ccl_device_noinline static
+# define ccl_device_noinline_cpu ccl_device_noinline
+# define ccl_global
+# define ccl_static_constant static const
+# define ccl_constant const
+# define ccl_local
+# define ccl_local_param
+# define ccl_private
+# define ccl_restrict __restrict
+# define ccl_ref &
+# define ccl_optional_struct_init
+# define __KERNEL_WITH_SSE_ALIGN__
+
+# if defined(_WIN32) && !defined(FREE_WINDOWS)
+# define ccl_device_inline static __forceinline
+# define ccl_device_forceinline static __forceinline
+# define ccl_align(...) __declspec(align(__VA_ARGS__))
+# ifdef __KERNEL_64_BIT__
+# define ccl_try_align(...) __declspec(align(__VA_ARGS__))
+# else /* __KERNEL_64_BIT__ */
+# undef __KERNEL_WITH_SSE_ALIGN__
/* No support for function arguments (error C2719). */
-# define ccl_try_align(...)
-# endif /* __KERNEL_64_BIT__ */
-# define ccl_may_alias
-# define ccl_always_inline __forceinline
-# define ccl_never_inline __declspec(noinline)
-# define ccl_maybe_unused
-# else /* _WIN32 && !FREE_WINDOWS */
-# define ccl_device_inline static inline __attribute__((always_inline))
-# define ccl_device_forceinline static inline __attribute__((always_inline))
-# define ccl_align(...) __attribute__((aligned(__VA_ARGS__)))
-# ifndef FREE_WINDOWS64
-# define __forceinline inline __attribute__((always_inline))
-# endif
-# define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__)))
-# define ccl_may_alias __attribute__((__may_alias__))
-# define ccl_always_inline __attribute__((always_inline))
-# define ccl_never_inline __attribute__((noinline))
-# define ccl_maybe_unused __attribute__((used))
-# endif /* _WIN32 && !FREE_WINDOWS */
+# define ccl_try_align(...)
+# endif /* __KERNEL_64_BIT__ */
+# define ccl_may_alias
+# define ccl_always_inline __forceinline
+# define ccl_never_inline __declspec(noinline)
+# define ccl_maybe_unused
+# else /* _WIN32 && !FREE_WINDOWS */
+# define ccl_device_inline static inline __attribute__((always_inline))
+# define ccl_device_forceinline static inline __attribute__((always_inline))
+# define ccl_align(...) __attribute__((aligned(__VA_ARGS__)))
+# ifndef FREE_WINDOWS64
+# define __forceinline inline __attribute__((always_inline))
+# endif
+# define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__)))
+# define ccl_may_alias __attribute__((__may_alias__))
+# define ccl_always_inline __attribute__((always_inline))
+# define ccl_never_inline __attribute__((noinline))
+# define ccl_maybe_unused __attribute__((used))
+# endif /* _WIN32 && !FREE_WINDOWS */
/* Use to suppress '-Wimplicit-fallthrough' (in place of 'break'). */
-# ifndef ATTR_FALLTHROUGH
-# if defined(__GNUC__) && (__GNUC__ >= 7) /* gcc7.0+ only */
-# define ATTR_FALLTHROUGH __attribute__((fallthrough))
-# else
-# define ATTR_FALLTHROUGH ((void)0)
-# endif
+# ifndef ATTR_FALLTHROUGH
+# if defined(__GNUC__) && (__GNUC__ >= 7) /* gcc7.0+ only */
+# define ATTR_FALLTHROUGH __attribute__((fallthrough))
+# else
+# define ATTR_FALLTHROUGH ((void)0)
# endif
-# endif /* __KERNEL_GPU__ */
+# endif
+#endif /* __KERNEL_GPU__ */
/* macros */
/* hints for branch prediction, only use in code that runs a _lot_ */
-# if defined(__GNUC__) && defined(__KERNEL_CPU__)
-# define LIKELY(x) __builtin_expect(!!(x), 1)
-# define UNLIKELY(x) __builtin_expect(!!(x), 0)
-# else
-# define LIKELY(x) (x)
-# define UNLIKELY(x) (x)
-# endif
-
-# if defined(__GNUC__) || defined(__clang__)
-# if defined(__cplusplus)
+#if defined(__GNUC__) && defined(__KERNEL_CPU__)
+# define LIKELY(x) __builtin_expect(!!(x), 1)
+# define UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+# define LIKELY(x) (x)
+# define UNLIKELY(x) (x)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+# if defined(__cplusplus)
/* Some magic to be sure we don't have reference in the type. */
template<typename T> static inline T decltype_helper(T x)
{
return x;
}
-# define TYPEOF(x) decltype(decltype_helper(x))
-# else
-# define TYPEOF(x) typeof(x)
-# endif
+# define TYPEOF(x) decltype(decltype_helper(x))
+# else
+# define TYPEOF(x) typeof(x)
# endif
+#endif
/* Causes warning:
* incompatible types when assigning to type 'Foo' from type 'Bar'
* ... the compiler optimizes away the temp var */
-# ifdef __GNUC__
-# define CHECK_TYPE(var, type) \
- { \
- TYPEOF(var) * __tmp; \
- __tmp = (type *)NULL; \
- (void)__tmp; \
- } \
- (void)0
-
-# define CHECK_TYPE_PAIR(var_a, var_b) \
- { \
- TYPEOF(var_a) * __tmp; \
- __tmp = (typeof(var_b) *)NULL; \
- (void)__tmp; \
- } \
- (void)0
-# else
-# define CHECK_TYPE(var, type)
-# define CHECK_TYPE_PAIR(var_a, var_b)
-# endif
+#ifdef __GNUC__
+# define CHECK_TYPE(var, type) \
+ { \
+ TYPEOF(var) * __tmp; \
+ __tmp = (type *)NULL; \
+ (void)__tmp; \
+ } \
+ (void)0
+
+# define CHECK_TYPE_PAIR(var_a, var_b) \
+ { \
+ TYPEOF(var_a) * __tmp; \
+ __tmp = (typeof(var_b) *)NULL; \
+ (void)__tmp; \
+ } \
+ (void)0
+#else
+# define CHECK_TYPE(var, type)
+# define CHECK_TYPE_PAIR(var_a, var_b)
+#endif
/* can be used in simple macros */
-# define CHECK_TYPE_INLINE(val, type) ((void)(((type)0) != (val)))
-
-# ifndef __KERNEL_GPU__
-# include <cassert>
-# define util_assert(statement) assert(statement)
-# else
-# define util_assert(statement)
-# endif
+#define CHECK_TYPE_INLINE(val, type) ((void)(((type)0) != (val)))
+
+#ifndef __KERNEL_GPU__
+# include <cassert>
+# define util_assert(statement) assert(statement)
+#else
+# define util_assert(statement)
+#endif
#endif /* __UTIL_DEFINES_H__ */
diff --git a/intern/cycles/util/util_static_assert.h b/intern/cycles/util/util_static_assert.h
index b4b972a4036..ceb52830319 100644
--- a/intern/cycles/util/util_static_assert.h
+++ b/intern/cycles/util/util_static_assert.h
@@ -15,18 +15,18 @@
*/
#ifndef __UTIL_STATIC_ASSERT_H__
-# define __UTIL_STATIC_ASSERT_H__
+#define __UTIL_STATIC_ASSERT_H__
CCL_NAMESPACE_BEGIN
/* TODO(sergey): In theory CUDA might work with own static assert
* implementation since it's just pure C++.
*/
-# ifdef __KERNEL_GPU__
-# ifndef static_assert
-# define static_assert(statement, message)
-# endif
-# endif /* __KERNEL_GPU__ */
+#ifdef __KERNEL_GPU__
+# ifndef static_assert
+# define static_assert(statement, message)
+# endif
+#endif /* __KERNEL_GPU__ */
/* TODO(sergey): For until C++11 is a bare minimum for us,
* we do a bit of a trickery to show meaningful message so
@@ -42,8 +42,8 @@ CCL_NAMESPACE_BEGIN
* After C++11 bump it should be possible to glue structure
* name to the error message,
*/
-# define static_assert_align(st, align) \
- static_assert((sizeof(st) % (align) == 0), "Structure must be strictly aligned") // NOLINT
+#define static_assert_align(st, align) \
+ static_assert((sizeof(st) % (align) == 0), "Structure must be strictly aligned") // NOLINT
CCL_NAMESPACE_END
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 20bb144a924..720929ce945 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -66,6 +66,25 @@ extern GHOST_SystemHandle GHOST_CreateSystem(void);
extern GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle);
/**
+ * Show a system message box to the user
+ * \param systemhandle The handle to the system
+ * \param title Title of the message box
+ * \param message Message of the message box
+ * \param help_label Text to show on the help button that opens a link
+ * \param continue_label Text to show on the ok button that continues
+ * \param link Optional (hyper)link to a webpage to show when pressing help
+ * \param dialog_options Options to configure the message box.
+ * \return void.
+ */
+extern void GHOST_ShowMessageBox(GHOST_SystemHandle systemhandle,
+ const char *title,
+ const char *message,
+ const char *help_label,
+ const char *continue_label,
+ const char *link,
+ GHOST_DialogOptions dialog_options);
+
+/**
* Creates an event consumer object
* \param eventCallback The event callback routine.
* \param userdata Pointer to user data returned to the callback routine.
@@ -176,10 +195,22 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings);
+extern GHOST_WindowHandle GHOST_CreateDialogWindow(GHOST_SystemHandle systemhandle,
+ GHOST_WindowHandle parent_windowhandle,
+ const char *title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ GHOST_GLSettings glSettings);
+
/**
* Create a new offscreen context.
* Never explicitly delete the context, use disposeContext() instead.
* \param systemhandle The handle to the system
+ * \param platform_support_callback An optional callback to check platform support
* \return A handle to the new context ( == NULL if creation failed).
*/
extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle);
@@ -207,6 +238,8 @@ extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandl
*/
extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata);
+extern int GHOST_IsDialogWindow(GHOST_WindowHandle windowhandle);
+
/**
* Dispose a window.
* \param systemhandle The handle to the system
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 27be80a2f20..b781de266bc 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -235,7 +235,8 @@ class GHOST_ISystem {
* \param state: The state of the window when opened.
* \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
- * \param exclusive: Use to show the window on top and ignore others (used fullscreen).
+ * \param exclusive: Use to show the window on top and ignore others (used full-screen).
+ * \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
* \param parentWindow: Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
@@ -248,7 +249,8 @@ class GHOST_ISystem {
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
- const GHOST_TEmbedderWindowID parentWindow = 0) = 0;
+ const bool is_dialog = false,
+ const GHOST_IWindow *parentWindow = NULL) = 0;
/**
* Dispose a window.
@@ -435,6 +437,27 @@ class GHOST_ISystem {
*/
virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0;
+ /***************************************************************************************
+ * System Message Box.
+ ***************************************************************************************/
+
+ /**
+ * Show a system message box
+ *
+ * \param title The title of the message box
+ * \param message The message to display
+ * \param help_label Help button label
+ * \param continue_label Continue button label
+ * \param link An optional hyperlink
+ * \param dialog_options Options how to display the message
+ */
+ virtual GHOST_TSuccess showMessageBox(const char * /*title*/,
+ const char * /*message*/,
+ const char * /*help_label*/,
+ const char * /*continue_label*/,
+ const char * /*link*/,
+ GHOST_DialogOptions /*dialog_options*/) const = 0;
+
protected:
/**
* Initialize the system.
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 03a0db9abbe..c19d4bdf6bd 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -241,6 +241,8 @@ class GHOST_IWindow {
*/
virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
+ virtual bool isDialog() const = 0;
+
/**
* Returns the tablet data (pressure etc).
* \return The tablet data (pressure etc).
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 891f9d982b9..32472373b17 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -58,6 +58,11 @@ typedef enum {
GHOST_glAlphaBackground = (1 << 2),
} GHOST_GLFlags;
+typedef enum GHOST_DialogOptions {
+ GHOST_DialogWarning = (1 << 0),
+ GHOST_DialogError = (1 << 1),
+} GHOST_DialogOptions;
+
#ifdef _MSC_VER
typedef __int64 GHOST_TInt64;
typedef unsigned __int64 GHOST_TUns64;
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index a1a209af77a..eeb23ea7471 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -47,6 +47,18 @@ GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle)
return system->disposeSystem();
}
+void GHOST_ShowMessageBox(GHOST_SystemHandle systemhandle,
+ const char *title,
+ const char *message,
+ const char *help_label,
+ const char *continue_label,
+ const char *link,
+ GHOST_DialogOptions dialog_options)
+{
+ GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
+ system->showMessageBox(title, message, help_label, continue_label, link, dialog_options);
+}
+
GHOST_EventConsumerHandle GHOST_CreateEventConsumer(GHOST_EventCallbackProcPtr eventCallback,
GHOST_TUserDataPtr userdata)
{
@@ -140,7 +152,33 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
return (GHOST_WindowHandle)system->createWindow(
- title, left, top, width, height, state, type, glSettings, false);
+ title, left, top, width, height, state, type, glSettings, false, false);
+}
+
+GHOST_WindowHandle GHOST_CreateDialogWindow(GHOST_SystemHandle systemhandle,
+ GHOST_WindowHandle parent_windowhandle,
+ const char *title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ GHOST_GLSettings glSettings)
+{
+ GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
+
+ return (GHOST_WindowHandle)system->createWindow(title,
+ left,
+ top,
+ width,
+ height,
+ state,
+ type,
+ glSettings,
+ false,
+ true,
+ (GHOST_IWindow *)parent_windowhandle);
}
GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle)
@@ -156,6 +194,13 @@ void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr
window->setUserData(userdata);
}
+int GHOST_IsDialogWindow(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
+
+ return (int)window->isDialog();
+}
+
GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle,
GHOST_WindowHandle windowhandle)
{
@@ -618,8 +663,13 @@ GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandl
GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
-
- return context->activateDrawingContext();
+ if (context) {
+ return context->activateDrawingContext();
+ }
+ else {
+ GHOST_PRINT("GHOST_ActivateOpenGLContext: Context not valid");
+ return GHOST_kFailure;
+ }
}
GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle)
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index fbf8af01e59..893592e3cf5 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -105,14 +105,6 @@ class GHOST_System : public GHOST_ISystem {
***************************************************************************************/
/**
- * Inherited from GHOST_ISystem but left pure virtual
- *
- * virtual GHOST_TUns8 getNumDisplays() const = 0;
- * virtual void getMainDisplayDimensions(...) const = 0;
- * virtual GHOST_IWindow* createWindow(..)
- */
-
- /**
* Dispose a window.
* \param window Pointer to the window to be disposed.
* \return Indication of success.
@@ -317,6 +309,25 @@ class GHOST_System : public GHOST_ISystem {
*/
virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0;
+ /**
+ * Show a system message box
+ * \param title The title of the message box
+ * \param message The message to display
+ * \param help_label Help button label
+ * \param continue_label Continue button label
+ * \param link An optional hyperlink
+ * \param dialog_options Options how to display the message
+ */
+ virtual GHOST_TSuccess showMessageBox(const char * /*title*/,
+ const char * /*message*/,
+ const char * /*help_label */,
+ const char * /*continue_label */,
+ const char * /*link*/,
+ GHOST_DialogOptions /*dialog_options*/) const
+ {
+ return GHOST_kFailure;
+ };
+
protected:
/**
* Initialize the system.
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 109dd6c180d..1e44c3e31d4 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -109,7 +109,8 @@ class GHOST_SystemCocoa : public GHOST_System {
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
- const GHOST_TEmbedderWindowID parentWindow = 0);
+ const bool is_dialog = false,
+ const GHOST_IWindow *parentWindow = NULL);
/**
* Create a new offscreen context.
@@ -232,6 +233,11 @@ class GHOST_SystemCocoa : public GHOST_System {
GHOST_TSuccess handleApplicationBecomeActiveEvent();
/**
+ * \return True if any dialog window is open.
+ */
+ bool hasDialogWindow();
+
+ /**
* External objects should call this when they send an event outside processEvents.
*/
void notifyExternalEventProcessed();
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 2026c1b7b4f..68bac7d153b 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -707,7 +707,8 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const STR_String &title,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
- const GHOST_TEmbedderWindowID parentWindow)
+ const bool is_dialog,
+ const GHOST_IWindow *parentWindow)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
GHOST_IWindow *window = NULL;
@@ -735,7 +736,9 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const STR_String &title,
state,
type,
glSettings.flags & GHOST_glStereoVisual,
- glSettings.flags & GHOST_glDebugContext);
+ glSettings.flags & GHOST_glDebugContext,
+ is_dialog,
+ (GHOST_WindowCocoa *)parentWindow);
if (window->getValid()) {
// Store the pointer to the window
@@ -972,6 +975,13 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
// Note: called from NSApplication delegate
GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
{
+ for (GHOST_IWindow *iwindow : m_windowManager->getWindows()) {
+ GHOST_WindowCocoa *window = (GHOST_WindowCocoa *)iwindow;
+ if (window->isDialog()) {
+ [window->getCocoaWindow() makeKeyAndOrderFront:nil];
+ }
+ }
+
// Update the modifiers key mask, as its status may have changed when the application
// was not active (that is when update events are sent to another application).
unsigned int modifiers;
@@ -1021,6 +1031,17 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
return GHOST_kSuccess;
}
+bool GHOST_SystemCocoa::hasDialogWindow()
+{
+ for (GHOST_IWindow *iwindow : m_windowManager->getWindows()) {
+ GHOST_WindowCocoa *window = (GHOST_WindowCocoa *)iwindow;
+ if (window->isDialog()) {
+ return true;
+ }
+ }
+ return false;
+}
+
void GHOST_SystemCocoa::notifyExternalEventProcessed()
{
m_outsideLoopEventProcessed = true;
diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h
index 93aea87e9a6..10138bfc6eb 100644
--- a/intern/ghost/intern/GHOST_SystemNULL.h
+++ b/intern/ghost/intern/GHOST_SystemNULL.h
@@ -114,8 +114,9 @@ class GHOST_SystemNULL : public GHOST_System {
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
- bool exclusive,
- const GHOST_TEmbedderWindowID parentWindow)
+ const bool exclusive,
+ const bool is_dialog,
+ const GHOST_IWindow *parentWindow)
{
return new GHOST_WindowNULL(this,
title,
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index 520c62719f8..e3f6f4b6bb1 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -58,6 +58,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const STR_String &title,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
+ const bool /* is_dialog */,
const GHOST_TEmbedderWindowID parentWindow)
{
GHOST_WindowSDL *window = NULL;
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index 7dbdc3ccec8..942b6297c22 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -89,6 +89,7 @@ class GHOST_SystemSDL : public GHOST_System {
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
+ const bool is_dialog = false,
const GHOST_TEmbedderWindowID parentWindow = 0);
/* SDL specific */
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 9073ed9944b..c86accf4ede 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -28,12 +28,21 @@
# define _WIN32_IE 0x0501 /* shipped before XP, so doesn't impose additional requirements */
#endif
+/* clang-format off */
+#pragma comment(linker,"\"/manifestdependency:type='win32' \
+name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
+processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+/* clang-format on */
+
+#include <commctrl.h>
#include <shlobj.h>
#include <tlhelp32.h>
#include <psapi.h>
+#include <shellapi.h>
#include <windowsx.h>
#include "utfconv.h"
+#include "utf_winfunc.h"
#include "GHOST_DisplayManagerWin32.h"
#include "GHOST_EventButton.h"
@@ -266,7 +275,8 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const STR_String &title,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
- const GHOST_TEmbedderWindowID parentWindow)
+ const bool is_dialog,
+ const GHOST_IWindow *parentWindow)
{
GHOST_WindowWin32 *window = new GHOST_WindowWin32(
this,
@@ -279,8 +289,9 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const STR_String &title,
type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
((glSettings.flags & GHOST_glAlphaBackground) != 0),
- parentWindow,
- ((glSettings.flags & GHOST_glDebugContext) != 0));
+ (GHOST_WindowWin32 *)parentWindow,
+ ((glSettings.flags & GHOST_glDebugContext) != 0),
+ is_dialog);
if (window->getValid()) {
// Store the pointer to the window
@@ -356,14 +367,8 @@ GHOST_IContext *GHOST_SystemWin32::createOffscreenContext()
goto finished;
}
else {
- MessageBox(NULL,
- "A graphics card and driver with support for OpenGL 3.3 or higher is required.\n"
- "Installing the latest driver for your graphics card may resolve the issue.\n\n"
- "The program will now close.",
- "Blender - Unsupported Graphics Card or Driver",
- MB_OK | MB_ICONERROR);
delete context;
- exit();
+ return NULL;
}
#elif defined(WITH_GL_PROFILE_COMPAT)
@@ -514,6 +519,7 @@ GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons &buttons) const
GHOST_TSuccess GHOST_SystemWin32::init()
{
GHOST_TSuccess success = GHOST_System::init();
+ InitCommonControls();
/* Disable scaling on high DPI displays on Vista */
HMODULE
@@ -1774,6 +1780,57 @@ void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const
}
}
+/** \name Message Box
+ * \{ */
+GHOST_TSuccess GHOST_SystemWin32::showMessageBox(const char *title,
+ const char *message,
+ const char *help_label,
+ const char *continue_label,
+ const char *link,
+ GHOST_DialogOptions dialog_options) const
+{
+ const wchar_t *title_16 = alloc_utf16_from_8(title, 0);
+ const wchar_t *message_16 = alloc_utf16_from_8(message, 0);
+ const wchar_t *help_label_16 = alloc_utf16_from_8(help_label, 0);
+ const wchar_t *continue_label_16 = alloc_utf16_from_8(continue_label, 0);
+
+ int nButtonPressed = 0;
+ TASKDIALOGCONFIG config = {0};
+ const TASKDIALOG_BUTTON buttons[] = {{IDOK, help_label_16}, {IDCONTINUE, continue_label_16}};
+
+ config.cbSize = sizeof(config);
+ config.hInstance = 0;
+ config.dwCommonButtons = 0;
+ config.pszMainIcon = (dialog_options & GHOST_DialogError ?
+ TD_ERROR_ICON :
+ dialog_options & GHOST_DialogWarning ? TD_WARNING_ICON :
+ TD_INFORMATION_ICON);
+ config.pszWindowTitle = L"Blender";
+ config.pszMainInstruction = title_16;
+ config.pszContent = message_16;
+ config.pButtons = (link) ? buttons : buttons + 1;
+ config.cButtons = (link) ? 2 : 1;
+
+ TaskDialogIndirect(&config, &nButtonPressed, NULL, NULL);
+ switch (nButtonPressed) {
+ case IDOK:
+ ShellExecute(NULL, "open", link, NULL, NULL, SW_SHOWNORMAL);
+ break;
+ case IDCONTINUE:
+ break;
+ default:
+ break; // should never happen
+ }
+
+ free((void *)title_16);
+ free((void *)message_16);
+ free((void *)help_label_16);
+ free((void *)continue_label_16);
+
+ return GHOST_kSuccess;
+}
+/* \} */
+
static DWORD GetParentProcessID(void)
{
HANDLE snapshot;
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 7ac6a3e3e20..b069e6cf3b6 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -29,10 +29,6 @@
# error WIN32 only!
#endif // WIN32
-/* require Windows XP or newer */
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x501
-
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ole2.h> // for drag-n-drop
@@ -112,7 +108,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param type The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
- * \param parentWindow Parent (embedder) window
+ * \param parentWindow Parent window
* \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *createWindow(const STR_String &title,
@@ -124,7 +120,8 @@ class GHOST_SystemWin32 : public GHOST_System {
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
- const GHOST_TEmbedderWindowID parentWindow = 0);
+ const bool is_dialog = false,
+ const GHOST_IWindow *parentWindow = 0);
/**
* Create a new offscreen context.
@@ -204,6 +201,22 @@ class GHOST_SystemWin32 : public GHOST_System {
void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
/**
+ * Show a system message box
+ * \param title The title of the message box
+ * \param message The message to display
+ * \param help_label Help button label
+ * \param continue_label Continue button label
+ * \param link An optional hyperlink
+ * \param dialog_options Options how to display the message
+ */
+ GHOST_TSuccess showMessageBox(const char *title,
+ const char *message,
+ const char *help_label,
+ const char *continue_label,
+ const char *link,
+ GHOST_DialogOptions dialog_options) const;
+
+ /**
* Creates a drag'n'drop event and pushes it immediately onto the event queue.
* Called by GHOST_DropTargetWin32 class.
* \param eventType: The type of drag'n'drop event
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index e46edeeac9a..1ca412fbccc 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -324,7 +324,7 @@ void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32
* \param type The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
- * \param parentWindow Parent (embedder) window
+ * \param parentWindow Parent window
* \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *GHOST_SystemX11::createWindow(const STR_String &title,
@@ -336,7 +336,8 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const STR_String &title,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
- const GHOST_TEmbedderWindowID parentWindow)
+ const bool is_dialog,
+ const GHOST_IWindow *parentWindow)
{
GHOST_WindowX11 *window = NULL;
@@ -351,8 +352,9 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const STR_String &title,
width,
height,
state,
- parentWindow,
+ (GHOST_WindowX11 *)parentWindow,
type,
+ is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
exclusive,
((glSettings.flags & GHOST_glAlphaBackground) != 0),
@@ -2143,6 +2145,222 @@ void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const
}
}
+/** \name Message Box
+ * \{ */
+class DialogData {
+ public:
+ /* Width of the dialog */
+ uint width;
+ /* Heigth of the dialog */
+ uint height;
+ /* Default padding (x direction) between controls and edge of dialog */
+ uint padding_x;
+ /* Default padding (y direction) between controls and edge of dialog */
+ uint padding_y;
+ /* Width of a single button */
+ uint button_width;
+ /* Height of a single button */
+ uint button_height;
+ /* Inset of a button to its text */
+ uint button_inset_x;
+ /* Size of the border of the button */
+ uint button_border_size;
+ /* Height of a line of text */
+ uint line_height;
+ /* offset of the text inside the button */
+ uint button_text_offset_y;
+
+ /* Construct a new DialogData with the default settings */
+ DialogData()
+ : width(640),
+ height(175),
+ padding_x(10),
+ padding_y(5),
+ button_width(130),
+ button_height(24),
+ button_inset_x(10),
+ button_border_size(1),
+ line_height(16)
+ {
+ button_text_offset_y = button_height - line_height;
+ }
+
+ void drawButton(Display *display,
+ Window &window,
+ GC &borderGC,
+ GC &buttonGC,
+ uint button_num,
+ const char *label)
+ {
+ XFillRectangle(display,
+ window,
+ borderGC,
+ width - (padding_x + button_width) * button_num,
+ height - padding_y - button_height,
+ button_width,
+ button_height);
+
+ XFillRectangle(display,
+ window,
+ buttonGC,
+ width - (padding_x + button_width) * button_num + button_border_size,
+ height - padding_y - button_height + button_border_size,
+ button_width - button_border_size * 2,
+ button_height - button_border_size * 2);
+
+ XDrawString(display,
+ window,
+ borderGC,
+ width - (padding_x + button_width) * button_num + button_inset_x,
+ height - padding_y - button_text_offset_y,
+ label,
+ strlen(label));
+ }
+
+ /* Is the mouse inside the given button */
+ bool isInsideButton(XEvent &e, uint button_num)
+ {
+ return ((e.xmotion.y > height - padding_y - button_height) &&
+ (e.xmotion.y < height - padding_y) &&
+ (e.xmotion.x > width - (padding_x + button_width) * button_num) &&
+ (e.xmotion.x < width - padding_x - (padding_x + button_width) * (button_num - 1)));
+ }
+};
+
+static void split(const char *text, const char *seps, char ***str, int *count)
+{
+ char *tok, *data;
+ int i;
+ *count = 0;
+
+ data = strdup(text);
+ for (tok = strtok(data, seps); tok != NULL; tok = strtok(NULL, seps))
+ (*count)++;
+ free(data);
+
+ data = strdup(text);
+ *str = (char **)malloc((size_t)(*count) * sizeof(char *));
+ for (i = 0, tok = strtok(data, seps); tok != NULL; tok = strtok(NULL, seps), i++)
+ (*str)[i] = strdup(tok);
+ free(data);
+}
+
+GHOST_TSuccess GHOST_SystemX11::showMessageBox(const char *title,
+ const char *message,
+ const char *help_label,
+ const char *continue_label,
+ const char *link,
+ GHOST_DialogOptions) const
+{
+ char **text_splitted = NULL;
+ int textLines = 0;
+ split(message, "\n", &text_splitted, &textLines);
+
+ DialogData dialog_data;
+ XSizeHints hints;
+
+ Window window;
+ XEvent e;
+ int screen = DefaultScreen(m_display);
+ window = XCreateSimpleWindow(m_display,
+ RootWindow(m_display, screen),
+ 0,
+ 0,
+ dialog_data.width,
+ dialog_data.height,
+ 1,
+ BlackPixel(m_display, screen),
+ WhitePixel(m_display, screen));
+
+ /* Window Should not be resizable */
+ {
+ hints.flags = PSize | PMinSize | PMaxSize;
+ hints.min_width = hints.max_width = hints.base_width = dialog_data.width;
+ hints.min_height = hints.max_height = hints.base_height = dialog_data.height;
+ XSetWMNormalHints(m_display, window, &hints);
+ }
+
+ /* Set title */
+ {
+ Atom wm_Name = XInternAtom(m_display, "_NET_WM_NAME", False);
+ Atom utf8Str = XInternAtom(m_display, "UTF8_STRING", False);
+
+ Atom winType = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE", False);
+ Atom typeDialog = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
+
+ XChangeProperty(m_display,
+ window,
+ wm_Name,
+ utf8Str,
+ 8,
+ PropModeReplace,
+ (const unsigned char *)title,
+ (int)strlen(title));
+
+ XChangeProperty(
+ m_display, window, winType, XA_ATOM, 32, PropModeReplace, (unsigned char *)&typeDialog, 1);
+ }
+
+ /* Create buttons GC */
+ XGCValues buttonBorderGCValues;
+ buttonBorderGCValues.foreground = BlackPixel(m_display, screen);
+ buttonBorderGCValues.background = WhitePixel(m_display, screen);
+ XGCValues buttonGCValues;
+ buttonGCValues.foreground = WhitePixel(m_display, screen);
+ buttonGCValues.background = BlackPixel(m_display, screen);
+
+ GC buttonBorderGC = XCreateGC(m_display, window, GCForeground, &buttonBorderGCValues);
+ GC buttonGC = XCreateGC(m_display, window, GCForeground, &buttonGCValues);
+
+ XSelectInput(m_display, window, ExposureMask | ButtonPressMask | ButtonReleaseMask);
+ XMapWindow(m_display, window);
+
+ while (1) {
+ XNextEvent(m_display, &e);
+ if (e.type == Expose) {
+ for (int i = 0; i < textLines; i++) {
+ XDrawString(m_display,
+ window,
+ DefaultGC(m_display, screen),
+ dialog_data.padding_x,
+ dialog_data.padding_x + (i + 1) * dialog_data.line_height,
+ text_splitted[i],
+ (int)strlen(text_splitted[i]));
+ }
+ dialog_data.drawButton(m_display, window, buttonBorderGC, buttonGC, 1, continue_label);
+ if (strlen(link)) {
+ dialog_data.drawButton(m_display, window, buttonBorderGC, buttonGC, 2, help_label);
+ }
+ }
+ else if (e.type == ButtonRelease) {
+ if (dialog_data.isInsideButton(e, 1)) {
+ break;
+ }
+ else if (dialog_data.isInsideButton(e, 2)) {
+ if (strlen(link)) {
+ string cmd = "xdg-open \"" + string(link) + "\"";
+ if (system(cmd.c_str()) != 0) {
+ GHOST_PRINTF("GHOST_SystemX11::showMessageBox: Unable to run system command [%s]",
+ cmd);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ for (int i = 0; i < textLines; i++) {
+ free(text_splitted[i]);
+ }
+ free(text_splitted);
+
+ XDestroyWindow(m_display, window);
+ XFreeGC(m_display, buttonBorderGC);
+ XFreeGC(m_display, buttonGC);
+ return GHOST_kSuccess;
+}
+/* \} */
+
#ifdef WITH_XDND
GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType,
GHOST_TDragnDropTypes draggedObjectType,
@@ -2303,26 +2521,30 @@ void GHOST_SystemX11::refreshXInputDevices()
/* Find how many pressure levels tablet has */
XAnyClassPtr ici = device_info[i].inputclassinfo;
- for (int j = 0; j < xtablet.Device->num_classes; ++j) {
- if (ici->c_class == ValuatorClass) {
- XValuatorInfo *xvi = (XValuatorInfo *)ici;
- xtablet.PressureLevels = xvi->axes[2].max_value;
-
- if (xvi->num_axes > 3) {
- /* this is assuming that the tablet has the same tilt resolution in both
- * positive and negative directions. It would be rather weird if it didn't.. */
- xtablet.XtiltLevels = xvi->axes[3].max_value;
- xtablet.YtiltLevels = xvi->axes[4].max_value;
- }
- else {
- xtablet.XtiltLevels = 0;
- xtablet.YtiltLevels = 0;
+ if (ici != NULL) {
+ for (int j = 0; j < xtablet.Device->num_classes; ++j) {
+ if (ici->c_class == ValuatorClass) {
+ XValuatorInfo *xvi = (XValuatorInfo *)ici;
+ if (xvi->axes != NULL) {
+ xtablet.PressureLevels = xvi->axes[2].max_value;
+
+ if (xvi->num_axes > 3) {
+ /* this is assuming that the tablet has the same tilt resolution in both
+ * positive and negative directions. It would be rather weird if it didn't.. */
+ xtablet.XtiltLevels = xvi->axes[3].max_value;
+ xtablet.YtiltLevels = xvi->axes[4].max_value;
+ }
+ else {
+ xtablet.XtiltLevels = 0;
+ xtablet.YtiltLevels = 0;
+ }
+
+ break;
+ }
}
- break;
+ ici = (XAnyClassPtr)(((char *)ici) + ici->length);
}
-
- ici = (XAnyClassPtr)(((char *)ici) + ici->length);
}
m_xtablets.push_back(xtablet);
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 1fe94b40f17..67dd0789ac3 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -146,7 +146,8 @@ class GHOST_SystemX11 : public GHOST_System {
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
- const GHOST_TEmbedderWindowID parentWindow = 0);
+ const bool is_dialog = false,
+ const GHOST_IWindow *parentWindow = 0);
/**
* Create a new offscreen context.
@@ -232,6 +233,21 @@ class GHOST_SystemX11 : public GHOST_System {
*/
void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
+ /**
+ * Show a system message box
+ * \param title The title of the message box
+ * \param message The message to display
+ * \param help_label Help button label
+ * \param continue_label Continue button label
+ * \param link An optional hyperlink
+ * \param dialog_options Options how to display the message
+ */
+ GHOST_TSuccess showMessageBox(const char *title,
+ const char *message,
+ const char *help_label,
+ const char *continue_label,
+ const char *link,
+ GHOST_DialogOptions dialog_options) const;
#ifdef WITH_XDND
/**
* Creates a drag'n'drop event and pushes it immediately onto the event queue.
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 5f9e8ffdd5e..553a7d89df4 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -109,6 +109,11 @@ class GHOST_Window : public GHOST_IWindow {
*/
inline GHOST_TStandardCursor getCursorShape() const;
+ inline bool isDialog() const
+ {
+ return false;
+ }
+
/**
* Set the shape of the cursor.
* \param cursorShape: The new cursor shape type id.
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index 66de8bcf7cc..d260d0eacbc 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -66,7 +66,9 @@ class GHOST_WindowCocoa : public GHOST_Window {
GHOST_TWindowState state,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
const bool stereoVisual = false,
- bool is_debug = false);
+ bool is_debug = false,
+ bool dialog = false,
+ GHOST_WindowCocoa *parentWindow = 0);
/**
* Destructor.
@@ -218,6 +220,8 @@ class GHOST_WindowCocoa : public GHOST_Window {
NSCursor *getStandardCursor(GHOST_TStandardCursor cursor) const;
void loadCursor(bool visible, GHOST_TStandardCursor cursor) const;
+ bool isDialog() const;
+
const GHOST_TabletData *GetTabletData()
{
return &m_tablet;
@@ -328,6 +332,7 @@ class GHOST_WindowCocoa : public GHOST_Window {
bool m_immediateDraw;
bool m_debug_context; // for debug messages during context setup
+ bool m_is_dialog;
};
#endif // __GHOST_WINDOWCOCOA_H__
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 6087df978fa..1d89da90a32 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -166,7 +166,8 @@
- (BOOL)canBecomeKeyWindow
{
- return YES;
+ /* Don't make other windows active when a dialog window is open. */
+ return (associatedWindow->isDialog() || !systemCocoa->hasDialogWindow());
}
//The drag'n'drop dragging destination methods
@@ -290,7 +291,9 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
const bool stereoVisual,
- bool is_debug)
+ bool is_debug,
+ bool is_dialog,
+ GHOST_WindowCocoa *parentWindow)
: GHOST_Window(width, height, state, stereoVisual, false),
m_openGLView(nil),
m_metalView(nil),
@@ -298,7 +301,8 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
m_systemCocoa(systemCocoa),
m_customCursor(0),
m_immediateDraw(false),
- m_debug_context(is_debug)
+ m_debug_context(is_debug),
+ m_is_dialog(is_dialog)
{
m_fullScreen = false;
@@ -313,12 +317,16 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
rect.size.width = width;
rect.size.height = height;
- m_window = [[CocoaWindow alloc]
- initWithContentRect:rect
- styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
- NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable
- backing:NSBackingStoreBuffered
- defer:NO];
+ NSWindowStyleMask styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
+ NSWindowStyleMaskResizable;
+ if (!is_dialog) {
+ styleMask |= NSWindowStyleMaskMiniaturizable;
+ }
+
+ m_window = [[CocoaWindow alloc] initWithContentRect:rect
+ styleMask:styleMask
+ backing:NSBackingStoreBuffered
+ defer:NO];
if (m_window == nil) {
[pool drain];
@@ -402,6 +410,10 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
if (state == GHOST_kWindowStateFullScreen)
setState(GHOST_kWindowStateFullScreen);
+ if (is_dialog && parentWindow) {
+ [parentWindow->getCocoaWindow() addChildWindow:m_window ordered:NSWindowAbove];
+ }
+
setNativePixelSize();
[pool drain];
@@ -548,10 +560,8 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect &bounds) const
NSRect screenSize = [[m_window screen] visibleFrame];
// Max window contents as screen size (excluding title bar...)
- NSRect contentRect = [CocoaWindow
- contentRectForFrameRect:screenSize
- styleMask:(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
- NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable)];
+ NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize
+ styleMask:[m_window styleMask]];
rect = [m_window contentRectForFrameRect:[m_window frame]];
@@ -1045,6 +1055,11 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor shape) co
[cursor set];
}
+bool GHOST_WindowCocoa::isDialog() const
+{
+ return m_is_dialog;
+}
+
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h
index 1d332a7dc3e..29f3eee7cce 100644
--- a/intern/ghost/intern/GHOST_WindowNULL.h
+++ b/intern/ghost/intern/GHOST_WindowNULL.h
@@ -36,6 +36,11 @@ class GHOST_WindowNULL : public GHOST_Window {
return NULL;
}
+ GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor)
+ {
+ return GHOST_kSuccess;
+ }
+
GHOST_WindowNULL(GHOST_SystemNULL *system,
const STR_String &title,
GHOST_TInt32 left,
@@ -43,7 +48,7 @@ class GHOST_WindowNULL : public GHOST_Window {
GHOST_TUns32 width,
GHOST_TUns32 height,
GHOST_TWindowState state,
- const GHOST_TEmbedderWindowID parentWindow,
+ const GHOST_IWindow *parentWindow,
GHOST_TDrawingContextType type,
const bool stereoVisual)
: GHOST_Window(width, height, state, stereoVisual, false), m_system(system)
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index d283e9e3aff..e1c6aa1109c 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -23,6 +23,7 @@
#define _USE_MATH_DEFINES
+#include "GHOST_WindowManager.h"
#include "GHOST_WindowWin32.h"
#include "GHOST_SystemWin32.h"
#include "GHOST_DropTargetWin32.h"
@@ -66,8 +67,9 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
GHOST_TDrawingContextType type,
bool wantStereoVisual,
bool alphaBackground,
- GHOST_TEmbedderWindowID parentwindowhwnd,
- bool is_debug)
+ GHOST_WindowWin32 *parentwindow,
+ bool is_debug,
+ bool dialog)
: GHOST_Window(width, height, state, wantStereoVisual, false),
m_inLiveResize(false),
m_system(system),
@@ -82,7 +84,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_fpGetPointerInfo(NULL),
m_fpGetPointerPenInfo(NULL),
m_fpGetPointerTouchInfo(NULL),
- m_parentWindowHwnd(parentwindowhwnd),
+ m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : NULL),
m_debug_context(is_debug)
{
// Initialize tablet variables
@@ -146,9 +148,9 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
top = monitor.rcWork.top;
int wintype = WS_OVERLAPPEDWINDOW;
- if (m_parentWindowHwnd != 0) {
+ if ((m_parentWindowHwnd != 0) && !dialog) {
wintype = WS_CHILD;
- GetWindowRect((HWND)m_parentWindowHwnd, &rect);
+ GetWindowRect(m_parentWindowHwnd, &rect);
left = 0;
top = 0;
width = rect.right - rect.left;
@@ -156,14 +158,14 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
}
wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
- m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name
- title_16, // pointer to window name
- wintype, // window style
- left, // horizontal position of window
- top, // vertical position of window
- width, // window width
- height, // window height
- (HWND)m_parentWindowHwnd, // handle to parent or owner window
+ m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name
+ title_16, // pointer to window name
+ wintype, // window style
+ left, // horizontal position of window
+ top, // vertical position of window
+ width, // window width
+ height, // window height
+ dialog ? 0 : m_parentWindowHwnd, // handle to parent or owner window
0, // handle to menu or child-window identifier
::GetModuleHandle(0), // handle to application instance
0); // pointer to window-creation data
@@ -267,7 +269,16 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
}
}
- if (parentwindowhwnd != 0) {
+ if (dialog && parentwindow) {
+ ::SetWindowLongPtr(m_hWnd,
+ GWL_STYLE,
+ WS_VISIBLE | WS_CHILD | WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX |
+ WS_SIZEBOX);
+ ::SetWindowLongPtr(m_hWnd, GWLP_HWNDPARENT, (LONG_PTR)m_parentWindowHwnd);
+ ::SetWindowPos(
+ m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+ }
+ else if (parentwindow) {
RAWINPUTDEVICE device = {0};
device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/
device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
@@ -386,6 +397,16 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
}
if (m_hWnd) {
+ /* If this window is referenced by others as parent, clear that relation or windows will free
+ * the handle while we still reference it. */
+ for (GHOST_IWindow *iter_win : m_system->getWindowManager()->getWindows()) {
+ GHOST_WindowWin32 *iter_winwin = (GHOST_WindowWin32 *)iter_win;
+ if (iter_winwin->m_parentWindowHwnd == m_hWnd) {
+ ::SetWindowLongPtr(iter_winwin->m_hWnd, GWLP_HWNDPARENT, NULL);
+ iter_winwin->m_parentWindowHwnd = 0;
+ }
+ }
+
if (m_dropTarget) {
// Disable DragDrop
RevokeDragDrop(m_hWnd);
@@ -528,7 +549,7 @@ GHOST_TWindowState GHOST_WindowWin32::getState() const
// we need to find a way to combine parented windows + resizing if we simply set the
// state as GHOST_kWindowStateEmbedded we will need to check for them somewhere else.
// It's also strange that in Windows is the only platform we need to make this separation.
- if (m_parentWindowHwnd != 0) {
+ if ((m_parentWindowHwnd != 0) && !isDialog()) {
state = GHOST_kWindowStateEmbedded;
return state;
}
@@ -574,6 +595,7 @@ void GHOST_WindowWin32::clientToScreen(GHOST_TInt32 inX,
GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
{
GHOST_TWindowState curstate = getState();
+ LONG_PTR newstyle = -1;
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
::GetWindowPlacement(m_hWnd, &wp);
@@ -587,7 +609,7 @@ GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
break;
case GHOST_kWindowStateMaximized:
wp.showCmd = SW_SHOWMAXIMIZED;
- ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
+ newstyle = WS_OVERLAPPEDWINDOW;
break;
case GHOST_kWindowStateFullScreen:
if (curstate != state && curstate != GHOST_kWindowStateMinimized)
@@ -595,17 +617,21 @@ GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
wp.showCmd = SW_SHOWMAXIMIZED;
wp.ptMaxPosition.x = 0;
wp.ptMaxPosition.y = 0;
- ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_MAXIMIZE);
+ newstyle = WS_MAXIMIZE;
break;
case GHOST_kWindowStateEmbedded:
- ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_CHILD);
+ newstyle = WS_CHILD;
break;
case GHOST_kWindowStateNormal:
default:
wp.showCmd = SW_SHOWNORMAL;
- ::SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
+ newstyle = WS_OVERLAPPEDWINDOW;
break;
}
+ if ((newstyle >= 0) && !isDialog()) {
+ ::SetWindowLongPtr(m_hWnd, GWL_STYLE, newstyle);
+ }
+
/* Clears window cache for SetWindowLongPtr */
::SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
@@ -737,6 +763,14 @@ void GHOST_WindowWin32::lostMouseCapture()
}
}
+bool GHOST_WindowWin32::isDialog() const
+{
+ HWND parent = (HWND)::GetWindowLongPtr(m_hWnd, GWLP_HWNDPARENT);
+ long int style = (long int)::GetWindowLongPtr(m_hWnd, GWL_STYLE);
+
+ return (parent != 0) && (style & WS_POPUPWINDOW);
+}
+
void GHOST_WindowWin32::registerMouseClickEvent(int press)
{
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index 8dac142d6f4..f72f03855fd 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -235,8 +235,9 @@ class GHOST_WindowWin32 : public GHOST_Window {
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
bool wantStereoVisual = false,
bool alphaBackground = false,
- GHOST_TEmbedderWindowID parentWindowHwnd = 0,
- bool is_debug = false);
+ GHOST_WindowWin32 *parentWindow = 0,
+ bool is_debug = false,
+ bool dialog = false);
/**
* Destructor.
@@ -381,6 +382,8 @@ class GHOST_WindowWin32 : public GHOST_Window {
*/
void lostMouseCapture();
+ bool isDialog() const;
+
/**
* Loads the windows equivalent of a standard GHOST cursor.
* \param visible Flag for cursor visibility.
@@ -528,8 +531,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
GHOST_WIN32_GetPointerPenInfo m_fpGetPointerPenInfo;
GHOST_WIN32_GetPointerTouchInfo m_fpGetPointerTouchInfo;
- /** Hwnd to parent window */
- GHOST_TEmbedderWindowID m_parentWindowHwnd;
+ HWND m_parentWindowHwnd;
#ifdef WITH_INPUT_IME
/** Handle input method editors event */
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 8aa4a4e284a..ae8d705fe4a 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -72,7 +72,18 @@ typedef struct {
long input_mode;
} MotifWmHints;
-#define MWM_HINTS_DECORATIONS (1L << 1)
+enum {
+ MWM_HINTS_FUNCTIONS = (1L << 0),
+ MWM_HINTS_DECORATIONS = (1L << 1),
+};
+enum {
+ MWM_FUNCTION_ALL = (1L << 0),
+ MWM_FUNCTION_RESIZE = (1L << 1),
+ MWM_FUNCTION_MOVE = (1L << 2),
+ MWM_FUNCTION_MINIMIZE = (1L << 3),
+ MWM_FUNCTION_MAXIMIZE = (1L << 4),
+ MWM_FUNCTION_CLOSE = (1L << 5),
+};
#ifndef HOST_NAME_MAX
# define HOST_NAME_MAX 64
@@ -191,8 +202,9 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
GHOST_TUns32 width,
GHOST_TUns32 height,
GHOST_TWindowState state,
- const GHOST_TEmbedderWindowID parentWindow,
+ GHOST_WindowX11 *parentWindow,
GHOST_TDrawingContextType type,
+ const bool is_dialog,
const bool stereoVisual,
const bool exclusive,
const bool alphaBackground,
@@ -259,7 +271,7 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
m_display, RootWindow(m_display, m_visualInfo->screen), m_visualInfo->visual, AllocNone);
/* create the window! */
- if (parentWindow == 0) {
+ if ((parentWindow == 0) || is_dialog) {
m_window = XCreateWindow(m_display,
RootWindow(m_display, m_visualInfo->screen),
left,
@@ -279,7 +291,7 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
unsigned int w_return, h_return, border_w_return, depth_return;
XGetGeometry(m_display,
- parentWindow,
+ parentWindow->m_window,
&root_return,
&x_return,
&y_return,
@@ -294,7 +306,7 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
height = h_return;
m_window = XCreateWindow(m_display,
- parentWindow, /* reparent against embedder */
+ parentWindow->m_window, /* reparent against embedder */
left,
top,
width,
@@ -306,7 +318,7 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
xattributes_valuemask,
&xattributes);
- XSelectInput(m_display, parentWindow, SubstructureNotifyMask);
+ XSelectInput(m_display, parentWindow->m_window, SubstructureNotifyMask);
}
#ifdef WITH_XDND
@@ -356,6 +368,10 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
m_post_state = GHOST_kWindowStateNormal;
}
+ if (is_dialog && parentWindow) {
+ setDialogHints(parentWindow);
+ }
+
/* Create some hints for the window manager on how
* we want this window treated. */
{
@@ -701,6 +717,42 @@ void GHOST_WindowX11::clientToScreen(GHOST_TInt32 inX,
outY = ay;
}
+GHOST_TSuccess GHOST_WindowX11::setDialogHints(GHOST_WindowX11 *parentWindow)
+{
+
+ Atom atom_window_type = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE", False);
+ Atom atom_dialog = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
+ MotifWmHints hints = {0};
+
+ XChangeProperty(m_display,
+ m_window,
+ atom_window_type,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ (unsigned char *)&atom_dialog,
+ 1);
+ XSetTransientForHint(m_display, m_window, parentWindow->m_window);
+
+ /* Disable minimizing of the window for now.
+ * Actually, most window managers disable minimizing and maximizing for dialogs, ignoring this.
+ * Leaving it here anyway in the hope it brings back maximizing on some window managers at least,
+ * we'd preferably have it even for dialog windows (e.g. file browser). */
+ hints.flags = MWM_HINTS_FUNCTIONS;
+ hints.functions = MWM_FUNCTION_RESIZE | MWM_FUNCTION_MOVE | MWM_FUNCTION_MAXIMIZE |
+ MWM_FUNCTION_CLOSE;
+ XChangeProperty(m_display,
+ m_window,
+ m_system->m_atom._MOTIF_WM_HINTS,
+ m_system->m_atom._MOTIF_WM_HINTS,
+ 32,
+ PropModeReplace,
+ (unsigned char *)&hints,
+ 4);
+
+ return GHOST_kSuccess;
+}
+
void GHOST_WindowX11::icccmSetState(int state)
{
XEvent xev;
@@ -1112,6 +1164,44 @@ GHOST_TSuccess GHOST_WindowX11::setOrder(GHOST_TWindowOrder order)
return GHOST_kSuccess;
}
+bool GHOST_WindowX11::isDialog() const
+{
+ Atom atom_window_type = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE", False);
+ Atom atom_dialog = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
+
+ Atom *prop_ret;
+ unsigned long bytes_after, num_ret;
+ Atom type_ret;
+ bool st;
+ int format_ret, ret;
+
+ prop_ret = NULL;
+ st = False;
+ ret = XGetWindowProperty(m_display,
+ m_window,
+ atom_window_type,
+ 0,
+ INT_MAX,
+ False,
+ XA_ATOM,
+ &type_ret,
+ &format_ret,
+ &num_ret,
+ &bytes_after,
+ (unsigned char **)&prop_ret);
+ if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
+ if (prop_ret[0] == atom_dialog) {
+ st = True;
+ }
+ }
+
+ if (prop_ret) {
+ XFree(prop_ret);
+ }
+
+ return st;
+}
+
GHOST_TSuccess GHOST_WindowX11::invalidate()
{
/* So the idea of this function is to generate an expose event
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index 0b8fe3a3a41..faf3acba234 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -75,8 +75,9 @@ class GHOST_WindowX11 : public GHOST_Window {
GHOST_TUns32 width,
GHOST_TUns32 height,
GHOST_TWindowState state,
- const GHOST_TEmbedderWindowID parentWindow,
+ GHOST_WindowX11 *parentWindow,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
+ const bool is_dialog = false,
const bool stereoVisual = false,
const bool exclusive = false,
const bool alphaBackground = false,
@@ -92,6 +93,8 @@ class GHOST_WindowX11 : public GHOST_Window {
void getClientBounds(GHOST_Rect &bounds) const;
+ bool isDialog() const;
+
GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
@@ -185,6 +188,8 @@ class GHOST_WindowX11 : public GHOST_Window {
GHOST_TSuccess endFullScreen() const;
+ GHOST_TSuccess setDialogHints(GHOST_WindowX11 *parentWindow);
+
GHOST_TUns16 getDPIHint();
protected:
diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c
index ab58c8f48e4..4f120b7d83c 100644
--- a/intern/mikktspace/mikktspace.c
+++ b/intern/mikktspace/mikktspace.c
@@ -460,11 +460,6 @@ tbool genTangSpace(const SMikkTSpaceContext *pContext, const float fAngularThres
///////////////////////////////////////////////////////////////////////////////////////////////////
-typedef struct {
- float vert[3];
- int index;
-} STmpVert;
-
static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[],
const SMikkTSpaceContext *pContext,
const int iNrTrianglesIn);
diff --git a/intern/numaapi/README.blender b/intern/numaapi/README.blender
index 6f71d5f8807..0151be80e10 100644
--- a/intern/numaapi/README.blender
+++ b/intern/numaapi/README.blender
@@ -1,5 +1,5 @@
Project: LibNumaAPI
URL: https://github.com/Nazg-Gul/libNumaAPI
License: MIT
-Upstream version: 4e7206befce
+Upstream version: 1afdd28a08d
Local modifications: None
diff --git a/intern/numaapi/source/build_config.h b/intern/numaapi/source/build_config.h
index 444adcc0c71..b8af51a5dd7 100644
--- a/intern/numaapi/source/build_config.h
+++ b/intern/numaapi/source/build_config.h
@@ -307,6 +307,27 @@
# define ARCH_CPU_32_BITS 1
# define ARCH_CPU_BIG_ENDIAN 1
# endif
+#elif defined(__powerpc64__)
+# define ARCH_CPU_PPC_FAMILY 1
+# define ARCH_CPU_PPC 1
+# define ARCH_CPU_64_BITS 1
+# if defined(__BIG_ENDIAN__)
+# define ARCH_CPU_BIG_ENDIAN 1
+# elif defined(__LITTLE_ENDIAN)
+# define ARCH_CPU_LITTLE_ENDIAN 1
+# else
+# error Please define your endianness
+# endif
+#elif defined(__s390x__)
+# define ARCH_CPU_S390_FAMILY 1
+# define ARCH_CPU_S390X 1
+# define ARCH_CPU_64_BITS 1
+# define ARCH_CPU_BIG_ENDIAN 1
+#elif defined(__s390__)
+# define ARCH_CPU_S390_FAMILY 1
+# define ARCH_CPU_S390 1
+# define ARCH_CPU_31_BITS 1
+# define ARCH_CPU_BIG_ENDIAN 1
#else
# error Please add support for your architecture in build_config.h
#endif
@@ -337,6 +358,12 @@
#if !defined(ARCH_CPU_MIPS64_FAMILY)
# define ARCH_CPU_MIPS64_FAMILY 0
#endif
+#if !defined(ARCH_CPU_PPC_FAMILY)
+# define ARCH_CPU_PPC_FAMILY 0
+#endif
+#if !defined(ARCH_CPU_S390_FAMILY)
+# define ARCH_CPU_S390_FAMILY 0
+#endif
////////////////////////////////////////////////////////////////////////////////
// Sizes of platform-dependent types.
diff --git a/intern/opensubdiv/internal/opensubdiv_topology_refiner.cc b/intern/opensubdiv/internal/opensubdiv_topology_refiner.cc
index f4a1a82ca52..ac27cbdefdc 100644
--- a/intern/opensubdiv/internal/opensubdiv_topology_refiner.cc
+++ b/intern/opensubdiv/internal/opensubdiv_topology_refiner.cc
@@ -123,6 +123,21 @@ void getEdgeVertices(const OpenSubdiv_TopologyRefiner *topology_refiner,
edge_vertices_indices[1] = array[1];
}
+int getNumVertexEdges(const OpenSubdiv_TopologyRefiner *topology_refiner, const int vertex_index)
+{
+ const OpenSubdiv::Far::TopologyLevel *base_level = getOSDTopologyBaseLevel(topology_refiner);
+ return base_level->GetVertexEdges(vertex_index).size();
+}
+
+void getVertexEdges(const OpenSubdiv_TopologyRefiner *topology_refiner,
+ const int vertex_index,
+ int *vertex_edges_indices)
+{
+ const OpenSubdiv::Far::TopologyLevel *base_level = getOSDTopologyBaseLevel(topology_refiner);
+ OpenSubdiv::Far::ConstIndexArray array = base_level->GetVertexEdges(vertex_index);
+ convertArrayToRaw(array, vertex_edges_indices);
+}
+
int getNumFacePtexFaces(const OpenSubdiv_TopologyRefiner *topology_refiner, const int face_index)
{
const int num_face_vertices = topology_refiner->getNumFaceVertices(topology_refiner, face_index);
@@ -201,6 +216,8 @@ void assignFunctionPointers(OpenSubdiv_TopologyRefiner *topology_refiner)
topology_refiner->getNumFaceEdges = getNumFaceEdges;
topology_refiner->getFaceEdges = getFaceEdges;
topology_refiner->getEdgeVertices = getEdgeVertices;
+ topology_refiner->getNumVertexEdges = getNumVertexEdges;
+ topology_refiner->getVertexEdges = getVertexEdges;
// PTex face geometry.
topology_refiner->getNumFacePtexFaces = getNumFacePtexFaces;
topology_refiner->getNumPtexFaces = getNumPtexFaces;
@@ -389,7 +406,7 @@ bool compareCyclicBackward(const CyclicArray &array_a,
// vertices.
bool checkVerticesOfFacesMatch(const CyclicArray &indices_a, const CyclicArray &indices_b)
{
- if (indices_a.size() != indices_a.size()) {
+ if (indices_a.size() != indices_b.size()) {
return false;
}
// "Align" the arrays so we know first matched element.
diff --git a/intern/opensubdiv/opensubdiv_topology_refiner_capi.h b/intern/opensubdiv/opensubdiv_topology_refiner_capi.h
index cf7f59adf2f..38d722ab572 100644
--- a/intern/opensubdiv/opensubdiv_topology_refiner_capi.h
+++ b/intern/opensubdiv/opensubdiv_topology_refiner_capi.h
@@ -58,11 +58,13 @@ typedef struct OpenSubdiv_TopologyRefiner {
int (*getNumVertices)(const struct OpenSubdiv_TopologyRefiner *topology_refiner);
int (*getNumEdges)(const struct OpenSubdiv_TopologyRefiner *topology_refiner);
int (*getNumFaces)(const struct OpenSubdiv_TopologyRefiner *topology_refiner);
+
int (*getNumFaceVertices)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index);
void (*getFaceVertices)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index,
int *face_vertices_indices);
+
int (*getNumFaceEdges)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index);
void (*getFaceEdges)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
@@ -72,6 +74,12 @@ typedef struct OpenSubdiv_TopologyRefiner {
const int edge_index,
int edge_vertices_indices[2]);
+ int (*getNumVertexEdges)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
+ const int vertex_index);
+ void (*getVertexEdges)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
+ const int vertex_index,
+ int *vertex_edges_indices);
+
//////////////////////////////////////////////////////////////////////////////
// PTex face geometry queries.
diff --git a/release/datafiles/locale b/release/datafiles/locale
-Subproject 1f6ec7f7a145c36808231090c8666febb49db22
+Subproject 88497d7507e76281fbdd0cc1f8451f81ae7e378
diff --git a/release/datafiles/userdef/userdef_default.c b/release/datafiles/userdef/userdef_default.c
index 7785c9d2962..dc35187ab7e 100644
--- a/release/datafiles/userdef/userdef_default.c
+++ b/release/datafiles/userdef/userdef_default.c
@@ -22,6 +22,7 @@
#include "DNA_userdef_types.h"
#include "DNA_curve_types.h"
#include "DNA_space_types.h"
+#include "DNA_anim_types.h"
#include "BLI_math_rotation.h"
@@ -138,6 +139,7 @@ const UserDef U_default = {
.glreslimit = 0,
.curssize = 0,
.color_picker_type = USER_CP_CIRCLE_HSV,
+ .auto_smoothing_new = FCURVE_SMOOTH_CONT_ACCEL,
.ipo_new = BEZT_IPO_BEZ,
.keyhandles_new = HD_AUTO_ANIM,
.view_frame_type = ZOOM_FRAME_MODE_KEEP_RANGE,
diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c
index 80bed03debf..0b9e8beccc1 100644
--- a/release/datafiles/userdef/userdef_default_theme.c
+++ b/release/datafiles/userdef/userdef_default_theme.c
@@ -585,6 +585,7 @@ const bTheme U_theme_default = {
.anim_preview_range = RGBA(0xa14d0066),
.nla_tweaking = RGBA(0x4df31a4d),
.nla_tweakdupli = RGBA(0xd90000ff),
+ .nla_track = RGBA(0x424242ff),
.nla_transition = RGBA(0x1c2630ff),
.nla_transition_sel = RGBA(0x2e75dbff),
.nla_meta = RGBA(0x332642ff),
@@ -746,12 +747,12 @@ const bTheme U_theme_default = {
.back = RGBA(0x333333b3),
.sub_back = RGBA(0x0000003e),
},
+ .active = RGBA(0x3b5689ff),
.vertex_size = 3,
.outline_width = 1,
.facedot_size = 4,
.match = RGBA(0x337f334c),
.selected_highlight = RGBA(0x223a5bff),
- .active = RGBA(0x3b5689ff),
.selected_object = RGBA(0xe96a00ff),
.active_object = RGBA(0xffaf29ff),
.edited_object = RGBA(0x00806266),
diff --git a/release/freedesktop/org.blender.Blender.appdata.xml b/release/freedesktop/org.blender.Blender.appdata.xml
index 1287c9eea5d..984b5b3b15e 100644
--- a/release/freedesktop/org.blender.Blender.appdata.xml
+++ b/release/freedesktop/org.blender.Blender.appdata.xml
@@ -40,6 +40,27 @@
</screenshot>
</screenshots>
<releases>
+ <release version="2.81" date="2019-11-14">
+ <description>
+ <p>New features:</p>
+ <ul>
+ <li>Many sculpt tools and poly build tool for retopology</li>
+ <li>Voxel remesh and quad remesh</li>
+ <li>Transform origins, new snapping, mirroring and auto merge options</li>
+ <li>Revamped shaders for texturing</li>
+ <li>Cycles denoising with OpenImageDenoise and NVIDIA RTX support</li>
+ <li>Library overrides to make local overrides to linked characters and other data</li>
+ <li>
+ </ul>
+ <ul>
+ <p>Enhancements:</p>
+ <li>Eevee shadows, transparency and bump mapping redesigned</li>
+ <li>Viewport options for look development with Cycles and Eevee</li>
+ <li>Finer control over rotations and scale in bones, constraints and drivers</li>
+ <li>Outliner improvements, new file browser and batch rename</li>
+ </ul>
+ </description>
+ </release>
<release version="2.80" date="2019-07-30">
<description>
<p>New features:</p>
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject eb9bab0e7153fda8de113af9e3c54eca74c986e
+Subproject 0ec4a4fd2ac1a9a0aaf550ced7e4b445a340ca4
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
-Subproject d9ed9d4d064c74c86e2767cd4be32d602a0ee31
+Subproject 69bcc72f1ec4df73265ce35851658ef184b9d0f
diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py
index a6c7940f5c8..c81558db587 100644
--- a/release/scripts/modules/bl_i18n_utils/settings.py
+++ b/release/scripts/modules/bl_i18n_utils/settings.py
@@ -94,6 +94,7 @@ LANGUAGES = (
(44, "Kazakh (қазақша)", "kk_KZ"),
(45, "Abkhaz (Аԥсуа бызшәа)", "ab"),
(46, "Thai (ภาษาไทย)", "th_TH"),
+ (47, "Slovak (Slovenčina)", "sk_SK"),
)
# Default context, in py!
diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py
index 1576947b8b4..f70f1eacead 100644
--- a/release/scripts/modules/bpy_extras/mesh_utils.py
+++ b/release/scripts/modules/bpy_extras/mesh_utils.py
@@ -265,7 +265,7 @@ def ngon_tessellate(from_data, indices, fix_loops=True, debug_print=True):
return []
def mlen(co):
- # manhatten length of a vector, faster then length
+ # Manhatten length of a vector, faster then length.
return abs(co[0]) + abs(co[1]) + abs(co[2])
def vert_treplet(v, i):
@@ -278,9 +278,8 @@ def ngon_tessellate(from_data, indices, fix_loops=True, debug_print=True):
return v1[1], v2[1]
if not fix_loops:
- """
- Normal single concave loop filling
- """
+ # Normal single concave loop filling.
+
if type(from_data) in {tuple, list}:
verts = [Vector(from_data[i]) for ii, i in enumerate(indices)]
else:
@@ -294,17 +293,19 @@ def ngon_tessellate(from_data, indices, fix_loops=True, debug_print=True):
fill = tessellate_polygon([verts])
else:
- """
- Separate this loop into multiple loops be finding edges that are
- used twice. This is used by lightwave LWO files a lot
- """
+ # Separate this loop into multiple loops be finding edges that are
+ # used twice. This is used by Light-Wave LWO files a lot.
if type(from_data) in {tuple, list}:
- verts = [vert_treplet(Vector(from_data[i]), ii)
- for ii, i in enumerate(indices)]
+ verts = [
+ vert_treplet(Vector(from_data[i]), ii)
+ for ii, i in enumerate(indices)
+ ]
else:
- verts = [vert_treplet(from_data.vertices[i].co, ii)
- for ii, i in enumerate(indices)]
+ verts = [
+ vert_treplet(from_data.vertices[i].co, ii)
+ for ii, i in enumerate(indices)
+ ]
edges = [(i, i - 1) for i in range(len(verts))]
if edges:
@@ -354,7 +355,7 @@ def ngon_tessellate(from_data, indices, fix_loops=True, debug_print=True):
else:
return False
- # If were stuill here s1 and s2 are 2 segments in the same polyline
+ # If were still here s1 and s2 are 2 segments in the same poly-line.
s1.pop() # remove the last vert from s1
s1.extend(s2) # add segment 2 to segment 1
@@ -402,14 +403,14 @@ def ngon_tessellate(from_data, indices, fix_loops=True, debug_print=True):
# draw_loops(loop_list)
#raise Exception("done loop")
# map to original indices
- fill = [[vert_map[i] for i in reversed(f)] for f in fill]
+ fill = [[vert_map[i] for i in f] for f in fill]
if not fill:
if debug_print:
print('Warning Cannot scanfill, fallback on a triangle fan.')
fill = [[0, i - 1, i] for i in range(2, len(indices))]
else:
- # Use real scanfill.
+ # Use real scan-fill.
# See if its flipped the wrong way.
flip = None
for fi in fill:
diff --git a/release/scripts/modules/bpy_extras/node_shader_utils.py b/release/scripts/modules/bpy_extras/node_shader_utils.py
index 4ca3e675c37..720d1d8af5a 100644
--- a/release/scripts/modules/bpy_extras/node_shader_utils.py
+++ b/release/scripts/modules/bpy_extras/node_shader_utils.py
@@ -487,6 +487,35 @@ class PrincipledBSDFWrapper(ShaderWrapper):
alpha_texture = property(alpha_texture_get)
+ # --------------------------------------------------------------------
+ # Emission color.
+
+ def emission_color_get(self):
+ if not self.use_nodes or self.node_principled_bsdf is None:
+ return Color((0.0, 0.0, 0.0))
+ return rgba_to_rgb(self.node_principled_bsdf.inputs["Emission"].default_value)
+
+ @_set_check
+ def emission_color_set(self, color):
+ if self.use_nodes and self.node_principled_bsdf is not None:
+ color = values_clamp(color, 0.0, 1.0)
+ color = rgb_to_rgba(color)
+ self.node_principled_bsdf.inputs["Emission"].default_value = color
+
+ emission_color = property(emission_color_get, emission_color_set)
+
+
+ def emission_color_texture_get(self):
+ if not self.use_nodes or self.node_principled_bsdf is None:
+ return None
+ return ShaderImageTextureWrapper(
+ self, self.node_principled_bsdf,
+ self.node_principled_bsdf.inputs["Emission"],
+ grid_row_diff=1,
+ )
+
+ emission_color_texture = property(emission_color_texture_get)
+
# --------------------------------------------------------------------
# Normal map.
@@ -771,7 +800,7 @@ class ShaderImageTextureWrapper():
def scale_get(self):
if self.node_mapping is None:
- return Vector((0.0, 0.0, 0.0))
+ return Vector((1.0, 1.0, 1.0))
return self.node_mapping.inputs['Scale'].default_value
@_set_check
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 29470895079..43ee785438b 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -184,6 +184,27 @@ class WindowManager(bpy_types.ID):
self.piemenu_end__internal(pie)
+class WorkSpace(bpy_types.ID):
+ __slots__ = ()
+
+ def status_text_set(self, text):
+ """
+ Set the status text or None to clear,
+ When text is a function, this will be called with the (header, context) arguments.
+ """
+ from bl_ui.space_statusbar import STATUSBAR_HT_header
+ draw_fn = getattr(STATUSBAR_HT_header, "_draw_orig", None)
+ if draw_fn is None:
+ draw_fn = STATUSBAR_HT_header._draw_orig = STATUSBAR_HT_header.draw
+
+ if not (text is None or isinstance(text, str)):
+ draw_fn = text
+ text = None
+
+ self.status_text_set_internal(text)
+ STATUSBAR_HT_header.draw = draw_fn
+
+
class _GenericBone:
"""
functions for bones, common between Armature/Pose/Edit bones.
@@ -418,6 +439,8 @@ class Mesh(bpy_types.ID):
int pairs, each pair contains two indices to the
*vertices* argument. eg: [(1, 2), ...]
+ When an empty iterable is passed in, the edges are inferred from the polygons.
+
:type edges: iterable object
:arg faces:
@@ -453,11 +476,15 @@ class Mesh(bpy_types.ID):
self.polygons.foreach_set("loop_start", loop_starts)
self.polygons.foreach_set("vertices", vertex_indices)
- # if no edges - calculate them
- if faces and (not edges):
- self.update(calc_edges=True)
- elif edges:
- self.update(calc_edges_loose=True)
+ if edges or faces:
+ self.update(
+ # Needed to either:
+ # - Calculate edges that don't exist for polygons.
+ # - Assign edges to polygon loops.
+ calc_edges=bool(faces),
+ # Flag loose edges.
+ calc_edges_loose=bool(edges),
+ )
@property
def edge_keys(self):
@@ -612,17 +639,27 @@ class Gizmo(StructRNA):
if select_id is not None:
gpu.select.load_id(select_id)
+ use_blend = False
else:
if self.is_highlight:
color = (*self.color_highlight, self.alpha_highlight)
else:
color = (*self.color, self.alpha)
shader.uniform_float("color", color)
+ use_blend = color[3] < 1.0
+
+ if use_blend:
+ # TODO: wrap GPU_blend from GPU state.
+ from bgl import glEnable, glDisable, GL_BLEND
+ glEnable(GL_BLEND)
with gpu.matrix.push_pop():
gpu.matrix.multiply_matrix(matrix)
batch.draw()
+ if use_blend:
+ glDisable(GL_BLEND)
+
@staticmethod
def new_custom_shape(type, verts):
"""
diff --git a/release/scripts/presets/keyconfig/blender.py b/release/scripts/presets/keyconfig/blender.py
index 8a7689d6d60..596b17d734f 100644
--- a/release/scripts/presets/keyconfig/blender.py
+++ b/release/scripts/presets/keyconfig/blender.py
@@ -169,7 +169,10 @@ def load():
keyconfig_data = blender_default.generate_keymaps(
blender_default.Params(
select_mouse=kc_prefs.select_mouse,
- use_mouse_emulate_3_button=prefs.inputs.use_mouse_emulate_3_button,
+ use_mouse_emulate_3_button=(
+ prefs.inputs.use_mouse_emulate_3_button and
+ prefs.inputs.mouse_emulate_3_button_modifier == 'ALT'
+ ),
spacebar_action=kc_prefs.spacebar_action,
v3d_tilde_action=kc_prefs.v3d_tilde_action,
use_select_all_toggle=kc_prefs.use_select_all_toggle,
diff --git a/release/scripts/presets/keyconfig/blender_27x.py b/release/scripts/presets/keyconfig/blender_27x.py
index 4ce77f46213..8d50d449494 100644
--- a/release/scripts/presets/keyconfig/blender_27x.py
+++ b/release/scripts/presets/keyconfig/blender_27x.py
@@ -53,7 +53,10 @@ def load():
keyconfig_data = blender_default.generate_keymaps(
blender_default.Params(
select_mouse=kc_prefs.select_mouse,
- use_mouse_emulate_3_button=prefs.inputs.use_mouse_emulate_3_button,
+ use_mouse_emulate_3_button=(
+ prefs.inputs.use_mouse_emulate_3_button and
+ prefs.inputs.mouse_emulate_3_button_modifier == 'ALT'
+ ),
spacebar_action='SEARCH',
use_select_all_toggle=True,
use_gizmo_drag=False,
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index ddf7accc2b2..b7fd266596b 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -1448,7 +1448,6 @@ def km_graph_editor(params):
("graph.bake", {"type": 'C', "value": 'PRESS', "alt": True}, None),
op_menu("GRAPH_MT_delete", {"type": 'X', "value": 'PRESS'}),
op_menu("GRAPH_MT_delete", {"type": 'DEL', "value": 'PRESS'}),
- op_menu("GRAPH_MT_context_menu", params.context_menu_event),
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
("graph.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "ctrl": True},
@@ -1479,6 +1478,7 @@ def km_graph_editor(params):
op_menu_pie("GRAPH_MT_pivot_pie", {"type": 'PERIOD', "value": 'PRESS'}),
("marker.add", {"type": 'M', "value": 'PRESS'}, None),
("marker.rename", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
+ op_menu("GRAPH_MT_context_menu", params.context_menu_event),
])
if params.select_mouse == 'LEFTMOUSE' and not params.legacy:
@@ -1582,9 +1582,9 @@ def km_image(params):
)
),
op_menu_pie("IMAGE_MT_pivot_pie", {"type": 'PERIOD', "value": 'PRESS'}),
- op_menu("IMAGE_MT_mask_context_menu", params.context_menu_event),
("image.render_border", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
("image.clear_render_border", {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ op_menu("IMAGE_MT_mask_context_menu", params.context_menu_event),
])
if params.legacy:
@@ -1671,7 +1671,6 @@ def km_node_editor(params):
{"properties": [("factor", 1.2)]}),
("node.backimage_fit", {"type": 'HOME', "value": 'PRESS', "alt": True}, None),
("node.backimage_sample", {"type": params.action_mouse, "value": 'PRESS', "alt": True}, None),
- op_menu("NODE_MT_context_menu", params.context_menu_event),
("node.link_make", {"type": 'F', "value": 'PRESS'},
{"properties": [("replace", False)]}),
("node.link_make", {"type": 'F', "value": 'PRESS', "shift": True},
@@ -1737,6 +1736,7 @@ def km_node_editor(params):
{"properties": [("data_path", 'tool_settings.use_snap')]}),
("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("data_path", 'tool_settings.snap_node_element')]}),
+ op_menu("NODE_MT_context_menu", params.context_menu_event),
])
return keymap
@@ -1793,6 +1793,9 @@ def km_file_browser(params):
{"properties": [("data_path", 'space_data.params.show_hidden')]}),
("file.directory_new", {"type": 'I', "value": 'PRESS'},
{"properties": [("confirm", False)]}),
+ ("file.rename", {"type": 'F2', "value": 'PRESS'}, None),
+ ("file.delete", {"type": 'X', "value": 'PRESS'}, None),
+ ("file.delete", {"type": 'DEL', "value": 'PRESS'}, None),
("file.smoothscroll", {"type": 'TIMER1', "value": 'ANY', "any": True}, None),
("file.bookmark_add", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
("file.filenum", {"type": 'NUMPAD_PLUS', "value": 'PRESS'},
@@ -1831,7 +1834,7 @@ def km_file_browser_main(params):
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True},
{"properties": [("extend", True)]}),
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True},
- {"properties": [("extend", True), ("fill", True)]}),
+ {"properties": [("extend", True), ("fill", True), ("open", False)]}),
("file.select_walk", {"type": 'UP_ARROW', "value": 'PRESS'},
{"properties": [("direction", 'UP')]}),
("file.select_walk", {"type": 'UP_ARROW', "value": 'PRESS', "shift": True},
@@ -1983,7 +1986,6 @@ def km_dopesheet(params):
("action.interpolation_type", {"type": 'T', "value": 'PRESS'}, None),
("action.extrapolation_type", {"type": 'E', "value": 'PRESS', "shift": True}, None),
("action.keyframe_type", {"type": 'R', "value": 'PRESS'}, None),
- op_menu("DOPESHEET_MT_context_menu", params.context_menu_event),
("action.sample", {"type": 'O', "value": 'PRESS', "shift": True, "alt": True}, None),
op_menu("DOPESHEET_MT_delete", {"type": 'X', "value": 'PRESS'}),
op_menu("DOPESHEET_MT_delete", {"type": 'DEL', "value": 'PRESS'}),
@@ -2015,6 +2017,7 @@ def km_dopesheet(params):
op_menu_pie("VIEW3D_MT_proportional_editing_falloff_pie", {"type": 'O', "value": 'PRESS', "shift": True}),
("marker.add", {"type": 'M', "value": 'PRESS'}, None),
("marker.rename", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
+ op_menu("DOPESHEET_MT_context_menu", params.context_menu_event),
])
return keymap
@@ -2128,7 +2131,6 @@ def km_nla_editor(params):
("nla.apply_scale", {"type": 'A', "value": 'PRESS', "ctrl": True}, None),
("nla.clear_scale", {"type": 'S', "value": 'PRESS', "alt": True}, None),
op_menu_pie("NLA_MT_snap_pie", {"type": 'S', "value": 'PRESS', "shift": True}),
- op_menu("NLA_MT_context_menu", params.context_menu_event),
("nla.fmodifier_add", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None),
("transform.transform", {"type": 'G', "value": 'PRESS'},
{"properties": [("mode", 'TRANSLATION')]}),
@@ -2140,6 +2142,7 @@ def km_nla_editor(params):
{"properties": [("mode", 'TIME_SCALE')]}),
("marker.add", {"type": 'M', "value": 'PRESS'}, None),
("marker.rename", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
+ op_menu("NLA_MT_context_menu", params.context_menu_event),
])
return keymap
@@ -2299,9 +2302,9 @@ def km_text(params):
{"properties": [("lines", 1)]}),
("text.line_break", {"type": 'RET', "value": 'PRESS'}, None),
("text.line_break", {"type": 'NUMPAD_ENTER', "value": 'PRESS'}, None),
- op_menu("TEXT_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
("text.autocomplete", {"type": 'SPACE', "value": 'PRESS', "ctrl": True}, None),
("text.line_number", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
+ op_menu("TEXT_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
("text.insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
])
@@ -2429,7 +2432,6 @@ def km_sequencer(params):
("sequencer.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True}, None),
op_menu("SEQUENCER_MT_add", {"type": 'A', "value": 'PRESS', "shift": True}),
op_menu("SEQUENCER_MT_change", {"type": 'C', "value": 'PRESS'}),
- op_menu("SEQUENCER_MT_context_menu", params.context_menu_event),
("sequencer.slip", {"type": 'S', "value": 'PRESS'}, None),
("wm.context_set_int", {"type": 'O', "value": 'PRESS'},
{"properties": [("data_path", 'scene.sequence_editor.overlay_frame'), ("value", 0)]}),
@@ -2443,6 +2445,7 @@ def km_sequencer(params):
{"properties": [("left_right", 'LEFT'), ("linked_time", True)]}),
("sequencer.select", {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
{"properties": [("left_right", 'RIGHT'), ("linked_time", True)]}),
+ op_menu("SEQUENCER_MT_context_menu", params.context_menu_event),
])
return keymap
@@ -2539,8 +2542,8 @@ def km_console(params):
{"properties": [("text", '\t')]}),
("console.indent", {"type": 'TAB', "value": 'PRESS'}, None),
("console.unindent", {"type": 'TAB', "value": 'PRESS', "shift": True}, None),
+ op_menu("CONSOLE_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
("console.insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
- op_menu("CONSOLE_MT_context_menu", params.context_menu_event),
])
return keymap
@@ -2667,7 +2670,6 @@ def km_clip_editor(params):
("clip.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
("clip.keyframe_delete", {"type": 'I', "value": 'PRESS', "alt": True}, None),
("clip.join_tracks", {"type": 'J', "value": 'PRESS', "ctrl": True}, None),
- op_menu("CLIP_MT_tracking_context_menu", params.context_menu_event),
("clip.lock_selection_toggle", {"type": 'L', "value": 'PRESS'}, None),
("wm.context_toggle", {"type": 'D', "value": 'PRESS', "alt": True},
{"properties": [("data_path", 'space_data.show_disabled')]}),
@@ -2689,6 +2691,7 @@ def km_clip_editor(params):
op_menu_pie("CLIP_MT_pivot_pie", {"type": 'PERIOD', "value": 'PRESS'}),
("clip.copy_tracks", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
("clip.paste_tracks", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ op_menu("CLIP_MT_tracking_context_menu", params.context_menu_event),
])
if params.legacy:
@@ -3049,8 +3052,6 @@ def km_grease_pencil_stroke_edit_mode(params):
("gpencil.blank_frame_add", {"type": 'I', "value": 'PRESS', "shift": True}, None),
("gpencil.active_frames_delete_all", {"type": 'X', "value": 'PRESS', "shift": True}, None),
("gpencil.active_frames_delete_all", {"type": 'DEL', "value": 'PRESS', "shift": True}, None),
- # Context menu
- op_menu("VIEW3D_MT_gpencil_edit_context_menu", params.context_menu_event),
# Separate
("gpencil.stroke_separate", {"type": 'P', "value": 'PRESS'}, None),
# Split and joint strokes
@@ -3105,6 +3106,8 @@ def km_grease_pencil_stroke_edit_mode(params):
{"properties": [("mode", 1)]}),
("gpencil.selectmode_toggle", {"type": 'THREE', "value": 'PRESS'},
{"properties": [("mode", 2)]}),
+ # Context menu
+ op_menu("VIEW3D_MT_gpencil_edit_context_menu", params.context_menu_event),
])
if params.legacy:
@@ -3131,8 +3134,6 @@ def km_grease_pencil_stroke_paint_mode(params):
# Brush size
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
{"properties": [("data_path_primary", 'tool_settings.gpencil_paint.brush.size')]}),
- # Draw context menu
- op_panel("VIEW3D_PT_gpencil_draw_context_menu", params.context_menu_event),
# Draw delete menu
op_menu("GPENCIL_MT_gpencil_draw_delete", {"type": 'X', "value": 'PRESS'}),
# Animation menu
@@ -3148,6 +3149,8 @@ def km_grease_pencil_stroke_paint_mode(params):
{"properties": [("unselected", False)]}),
("gpencil.hide", {"type": 'H', "value": 'PRESS', "shift": True},
{"properties": [("unselected", True)]}),
+ # Draw context menu
+ op_panel("VIEW3D_PT_gpencil_draw_context_menu", params.context_menu_event),
])
return keymap
@@ -3170,9 +3173,6 @@ def km_grease_pencil_stroke_paint_draw_brush(params):
# Draw - straight lines
("gpencil.draw", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True},
{"properties": [("mode", 'DRAW_STRAIGHT'), ("wait_for_input", False)]}),
- # Draw - poly lines
- ("gpencil.draw", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
- {"properties": [("mode", 'DRAW_POLY'), ("wait_for_input", False)]}),
# Erase
("gpencil.draw", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
{"properties": [("mode", 'ERASER'), ("wait_for_input", False)]}),
@@ -3278,12 +3278,12 @@ def km_grease_pencil_stroke_sculpt_mode(params):
# Brush size
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt.brush.size')]}),
- # Context menu
- op_panel("VIEW3D_PT_gpencil_sculpt_context_menu", params.context_menu_event),
# Copy
("gpencil.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
# Display
*_grease_pencil_display(),
+ # Context menu
+ op_panel("VIEW3D_PT_gpencil_sculpt_context_menu", params.context_menu_event),
])
return keymap
@@ -3425,7 +3425,6 @@ def km_pose(params):
("pose.push", {"type": 'E', "value": 'PRESS', "ctrl": True}, None),
("pose.relax", {"type": 'E', "value": 'PRESS', "alt": True}, None),
("pose.breakdown", {"type": 'E', "value": 'PRESS', "shift": True}, None),
- op_menu("VIEW3D_MT_pose_context_menu", params.context_menu_event),
op_menu("VIEW3D_MT_pose_propagate", {"type": 'P', "value": 'PRESS', "alt": True}),
*(
(("object.hide_collection",
@@ -3434,6 +3433,7 @@ def km_pose(params):
for i in range(10)
)
),
+ op_menu("VIEW3D_MT_pose_context_menu", params.context_menu_event),
])
return keymap
@@ -3496,7 +3496,6 @@ def km_object_mode(params):
("collection.objects_remove_all", {"type": 'G', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
("collection.objects_add_active", {"type": 'G', "value": 'PRESS', "shift": True, "ctrl": True}, None),
("collection.objects_remove_active", {"type": 'G', "value": 'PRESS', "shift": True, "alt": True}, None),
- op_menu("VIEW3D_MT_object_context_menu", params.context_menu_event),
*_template_items_object_subdivision_set(),
("object.move_to_collection", {"type": 'M', "value": 'PRESS'}, None),
("object.link_to_collection", {"type": 'M', "value": 'PRESS', "shift": True}, None),
@@ -3513,6 +3512,7 @@ def km_object_mode(params):
for i in range(10)
)
),
+ op_menu("VIEW3D_MT_object_context_menu", params.context_menu_event),
])
if params.legacy:
@@ -3613,9 +3613,9 @@ def km_curve(params):
{"properties": [("unselected", True)]}),
("curve.normals_make_consistent", {"type": 'N', "value": 'PRESS', "ctrl" if params.legacy else "shift": True}, None),
("object.vertex_parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
- op_menu("VIEW3D_MT_edit_curve_context_menu", params.context_menu_event),
op_menu("VIEW3D_MT_hook", {"type": 'H', "value": 'PRESS', "ctrl": True}),
*_template_items_proportional_editing(connected=True),
+ op_menu("VIEW3D_MT_edit_curve_context_menu", params.context_menu_event),
])
return keymap
@@ -3917,8 +3917,8 @@ def km_sculpt(params):
("wm.context_toggle", {"type": 'S', "value": 'PRESS', "shift": True},
{"properties": [("data_path", 'tool_settings.sculpt.brush.use_smooth_stroke')]}),
op_menu("VIEW3D_MT_angle_control", {"type": 'R', "value": 'PRESS'}),
+ op_menu_pie("VIEW3D_MT_sculpt_mask_edit_pie", {"type" : 'A', "value": 'PRESS'}),
op_panel("VIEW3D_PT_sculpt_context_menu", params.context_menu_event),
- op_menu_pie("VIEW3D_MT_sculpt_mask_edit_pie", {"type" : 'A', "value": 'PRESS'})
])
if params.legacy:
@@ -4022,7 +4022,6 @@ def km_mesh(params):
{"properties": [("use_occlude_geometry", True), ("only_selected", False)]}),
("object.vertex_parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
# Menus.
- op_menu("VIEW3D_MT_edit_mesh_context_menu", params.context_menu_event),
op_menu("VIEW3D_MT_edit_mesh_faces", {"type": 'F', "value": 'PRESS', "ctrl": True}),
op_menu("VIEW3D_MT_edit_mesh_edges", {"type": 'E', "value": 'PRESS', "ctrl": True}),
op_menu("VIEW3D_MT_edit_mesh_vertices", {"type": 'V', "value": 'PRESS', "ctrl": True}),
@@ -4032,6 +4031,7 @@ def km_mesh(params):
op_menu("VIEW3D_MT_edit_mesh_normals", {"type": 'N', "value": 'PRESS', "alt" : True}),
("object.vertex_group_remove_from", {"type": 'G', "value": 'PRESS', "ctrl": True, "alt": True}, None),
*_template_items_proportional_editing(connected=True),
+ op_menu("VIEW3D_MT_edit_mesh_context_menu", params.context_menu_event),
])
if params.use_mouse_emulate_3_button and params.select_mouse == 'LEFTMOUSE':
@@ -4188,8 +4188,8 @@ def km_lattice(params):
("object.vertex_parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
("lattice.flip", {"type": 'F', "value": 'PRESS', "alt": True}, None),
op_menu("VIEW3D_MT_hook", {"type": 'H', "value": 'PRESS', "ctrl": True}),
- op_menu("VIEW3D_MT_edit_lattice_context_menu", params.context_menu_event),
*_template_items_proportional_editing(connected=False),
+ op_menu("VIEW3D_MT_edit_lattice_context_menu", params.context_menu_event),
])
return keymap
@@ -4225,7 +4225,6 @@ def km_particle(params):
{"properties": [("data_path_primary", 'tool_settings.particle_edit.brush.size')]}),
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
{"properties": [("data_path_primary", 'tool_settings.particle_edit.brush.strength')]}),
- op_menu("VIEW3D_MT_particle_context_menu", params.context_menu_event),
("particle.weight_set", {"type": 'K', "value": 'PRESS', "shift": True}, None),
*(
(("wm.context_set_enum",
@@ -4235,6 +4234,7 @@ def km_particle(params):
)
),
*_template_items_proportional_editing(connected=False),
+ op_menu("VIEW3D_MT_particle_context_menu", params.context_menu_event),
])
return keymap
@@ -5870,6 +5870,18 @@ def km_3d_view_tool_paint_gpencil_cutter(params):
)
+def km_3d_view_tool_paint_gpencil_eyedropper(params):
+ return (
+ "3D View Tool: Paint Gpencil, Eyedropper",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {"items": [
+ ("ui.eyedropper_gpencil_color", {"type": params.tool_mouse, "value": 'PRESS'}, None),
+ ("ui.eyedropper_gpencil_color", {"type": params.tool_mouse, "value": 'PRESS', "shift": True}, None),
+ ("ui.eyedropper_gpencil_color", {"type": params.tool_mouse, "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ]},
+ )
+
+
def km_3d_view_tool_edit_gpencil_select(params):
return (
"3D View Tool: Edit Gpencil, Tweak",
@@ -6207,6 +6219,7 @@ def generate_keymaps(params=None):
km_3d_view_tool_paint_gpencil_arc(params),
km_3d_view_tool_paint_gpencil_curve(params),
km_3d_view_tool_paint_gpencil_cutter(params),
+ km_3d_view_tool_paint_gpencil_eyedropper(params),
km_3d_view_tool_edit_gpencil_select(params),
km_3d_view_tool_edit_gpencil_select_box(params),
km_3d_view_tool_edit_gpencil_select_circle(params),
diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
index 5ce79936836..49a394b478d 100644
--- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
+++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
@@ -1177,10 +1177,14 @@ def km_file_browser(params):
("file.next", {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True}, None),
("file.next", {"type": 'RIGHT_ARROW', "value": 'PRESS', "ctrl": True}, None),
("file.refresh", {"type": 'R', "value": 'PRESS', "ctrl": True}, None),
+ ("file.previous", {"type": 'BACK_SPACE', "value": 'PRESS'}, None),
+ ("file.next", {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True}, None),
("wm.context_toggle", {"type": 'H', "value": 'PRESS'},
{"properties": [("data_path", 'space_data.params.show_hidden')]}),
("file.directory_new", {"type": 'I', "value": 'PRESS'},
{"properties": [("confirm", False)]}),
+ ("file.rename", {"type": 'F2', "value": 'PRESS'}, None),
+ ("file.delete", {"type": 'DEL', "value": 'PRESS'}, None),
("file.smoothscroll", {"type": 'TIMER1', "value": 'ANY', "any": True}, None),
("wm.context_toggle", {"type": 'T', "value": 'PRESS'},
{"properties": [("data_path", 'space_data.show_region_toolbar')]}),
@@ -1221,7 +1225,7 @@ def km_file_browser_main(params):
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True},
{"properties": [("extend", True)]}),
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True,},
- {"properties": [("extend", True), ("fill", True)]}),
+ {"properties": [("extend", True), ("fill", True), ("open", False)]}),
("file.select", {"type": 'RIGHTMOUSE', "value": 'CLICK', "shift": True},
{"properties": [("extend", True), ("open", False)]}),
("file.select", {"type": 'RIGHTMOUSE', "value": 'CLICK', "alt": True},
diff --git a/release/scripts/startup/bl_operators/userpref.py b/release/scripts/startup/bl_operators/userpref.py
index b052f333d2a..0cd90610cdc 100644
--- a/release/scripts/startup/bl_operators/userpref.py
+++ b/release/scripts/startup/bl_operators/userpref.py
@@ -114,7 +114,8 @@ class PREFERENCES_OT_copy_prev(Operator):
shutil.copytree(self._old_path(), self._new_path(), symlinks=True)
- # reload recent-files.txt
+ # reload preferences and recent-files.txt
+ bpy.ops.wm.read_userpref()
bpy.ops.wm.read_history()
# don't loose users work if they open the splash later.
diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
index 2b20754a995..2befb7c73e2 100644
--- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py
+++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
@@ -565,7 +565,12 @@ def unwrap(operator, context, **kwargs):
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
# define list of meshes
- meshes = list({me for obj in context.selected_objects if obj.type == 'MESH' for me in (obj.data,) if me.polygons and me.library is None})
+ meshes = list({
+ me for obj in context.selected_objects
+ if obj.type == 'MESH'
+ for me in (obj.data,)
+ if me.polygons and me.library is None
+ })
if not meshes:
operator.report({'ERROR'}, "No mesh object")
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index cb9af88f45f..5a6db45c329 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -1107,7 +1107,7 @@ class WM_OT_doc_view(Operator):
bl_label = "View Documentation"
doc_id: doc_id
- if bpy.app.version_cycle in {"release", "rc"}:
+ if bpy.app.version_cycle in {"release", "rc", "beta"}:
_prefix = ("https://docs.blender.org/api/%d.%d%s" %
(bpy.app.version[0], bpy.app.version[1], bpy.app.version_char))
else:
@@ -1999,7 +1999,6 @@ class WM_OT_batch_rename(Operator):
descr,
)
-
return data
@staticmethod
@@ -2042,7 +2041,7 @@ class WM_OT_batch_rename(Operator):
if action.use_replace_regex_dst:
replace_dst = action.replace_dst
else:
- replace_dst = re.escape(action.replace_dst)
+ replace_dst = action.replace_dst.replace("\\", "\\\\")
else:
replace_src = re.escape(action.replace_src)
replace_dst = re.escape(action.replace_dst)
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index b589f780c24..d1975919d7e 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -332,7 +332,8 @@ class DATA_PT_font(CurveButtonsPanelText, Panel):
layout = self.layout
text = context.curve
- char = context.curve.edit_format
+ char = text.edit_format
+ mode = context.mode
row = layout.split(factor=0.25)
row.label(text="Regular")
@@ -347,13 +348,14 @@ class DATA_PT_font(CurveButtonsPanelText, Panel):
row.label(text="Bold & Italic")
row.template_ID(text, "font_bold_italic", open="font.open", unlink="font.unlink")
- layout.separator()
+ if mode == 'EDIT_TEXT':
+ layout.separator()
- row = layout.row(align=True)
- row.prop(char, "use_bold", toggle=True)
- row.prop(char, "use_italic", toggle=True)
- row.prop(char, "use_underline", toggle=True)
- row.prop(char, "use_small_caps", toggle=True)
+ row = layout.row(align=True)
+ row.prop(char, "use_bold", toggle=True)
+ row.prop(char, "use_italic", toggle=True)
+ row.prop(char, "use_underline", toggle=True)
+ row.prop(char, "use_small_caps", toggle=True)
class DATA_PT_font_transform(CurveButtonsPanelText, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 51f24007271..72e9f710e9d 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -485,6 +485,7 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel):
else:
col.operator("object.quadriflow_remesh", text="QuadriFlow Remesh")
+
class DATA_PT_customdata(MeshButtonsPanel, Panel):
bl_label = "Geometry Data"
bl_options = {'DEFAULT_CLOSED'}
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index ca9c518f443..e545ee971d8 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -950,6 +950,7 @@ class GPENCIL_UL_layer(UIList):
icon_value=icon,
)
+
class GreasePencilSimplifyPanel:
def draw_header(self, context):
@@ -977,6 +978,7 @@ class GreasePencilSimplifyPanel:
sub.active = rd.simplify_gpencil_view_fill
sub.prop(rd, "simplify_gpencil_remove_lines", text="Lines")
+
classes = (
GPENCIL_MT_pie_tool_palette,
GPENCIL_MT_pie_settings_palette,
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 23b2556eddb..83f7cb710ff 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -367,7 +367,7 @@ def brush_basic_sculpt_settings(layout, context, brush, *, compact=False):
layout.row().prop(brush, "direction", expand=True, **({"text": ""} if compact else {}))
-def brush_basic_gpencil_paint_settings(layout, _context, brush, *, compact=True):
+def brush_basic_gpencil_paint_settings(layout, _context, brush, tool, *, compact=True, is_toolbar=False):
gp_settings = brush.gpencil_settings
# Brush details
@@ -395,6 +395,23 @@ def brush_basic_gpencil_paint_settings(layout, _context, brush, *, compact=True)
row = layout.row(align=True)
row.prop(gp_settings, "fill_draw_mode", text="Boundary")
row.prop(gp_settings, "show_fill_boundary", text="", icon='GRID')
+ # Fill options
+ if is_toolbar:
+ settings = _context.tool_settings.gpencil_sculpt
+ row = layout.row(align=True)
+ sub = row.row(align=True)
+ sub.popover(
+ panel="TOPBAR_PT_gpencil_fill",
+ text="Fill Options",
+ )
+ else:
+ row = layout.row(align=True)
+ row.prop(gp_settings, "fill_factor", text="Resolution")
+ if gp_settings.fill_draw_mode != 'STROKE':
+ row = layout.row(align=True)
+ row.prop(gp_settings, "show_fill", text="Ignore Transparent Strokes")
+ row = layout.row(align=True)
+ row.prop(gp_settings, "fill_threshold", text="Threshold")
else: # brush.gpencil_tool == 'DRAW':
row = layout.row(align=True)
row.prop(brush, "size", text="Radius")
@@ -403,6 +420,25 @@ def brush_basic_gpencil_paint_settings(layout, _context, brush, *, compact=True)
row.prop(gp_settings, "pen_strength", slider=True)
row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
+ if tool.idname in {"builtin.arc", "builtin.curve", "builtin.line", "builtin.box", "builtin.circle"}:
+ settings = _context.tool_settings.gpencil_sculpt
+ if is_toolbar:
+ row = layout.row(align=True)
+ row.prop(settings, "use_thickness_curve", text="", icon='CURVE_DATA')
+ sub = row.row(align=True)
+ sub.active = settings.use_thickness_curve
+ sub.popover(
+ panel="TOPBAR_PT_gpencil_primitive",
+ text="Thickness Profile",
+ )
+ else:
+ row = layout.row(align=True)
+ row.prop(settings, "use_thickness_curve", text="Use Thickness Profile")
+ sub = row.row(align=True)
+ if settings.use_thickness_curve:
+ # Curve
+ layout.template_curve_mapping(settings, "thickness_primitive_curve", brush=True)
+
def brush_basic_gpencil_sculpt_settings(layout, context, brush, *, compact=False):
tool_settings = context.tool_settings
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index a322b96f9dd..181032e4d96 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -158,7 +158,8 @@ class FILEBROWSER_PT_filter(Panel):
def panel_poll_is_upper_region(region):
- # The upper region is left-aligned, the lower is split into it then. Note that after "Flip Regions" it's right-aligned.
+ # The upper region is left-aligned, the lower is split into it then.
+ # Note that after "Flip Regions" it's right-aligned.
return region.alignment in {'LEFT', 'RIGHT'}
@@ -469,7 +470,12 @@ class FILEBROWSER_MT_context_menu(Menu):
layout.separator()
layout.operator("file.rename", text="Rename")
- # layout.operator("file.delete")
+ sub = layout.row()
+ sub.operator_context = 'EXEC_DEFAULT'
+ sub.operator("file.delete", text="Delete")
+
+ layout.separator()
+
sub = layout.row()
sub.operator_context = 'EXEC_DEFAULT'
sub.operator("file.directory_new", text="New Folder")
@@ -503,5 +509,6 @@ classes = (
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
+
for cls in classes:
register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 0f926e596de..2ce81ba8359 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -373,6 +373,12 @@ class NODE_PT_material_slots(Panel):
col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+ if ob.mode == 'EDIT':
+ row = layout.row(align=True)
+ row.operator("object.material_slot_assign", text="Assign")
+ row.operator("object.material_slot_select", text="Select")
+ row.operator("object.material_slot_deselect", text="Deselect")
+
class NODE_PT_node_color_presets(PresetPanel, Panel):
"""Predefined node color"""
@@ -412,6 +418,9 @@ class NODE_MT_context_menu(Menu):
# If something is selected
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("node.duplicate_move")
+ props = layout.operator("wm.call_panel", text="Rename...")
+ props.name = "TOPBAR_PT_name"
+ props.keep_open = False
layout.operator("node.delete")
layout.operator("node.clipboard_copy", text="Copy")
layout.operator("node.clipboard_paste", text="Paste")
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index a942b8769cf..cdac91b8014 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -741,6 +741,9 @@ class SEQUENCER_MT_context_menu(Menu):
layout.operator("sequencer.copy", text="Copy", icon='COPYDOWN')
layout.operator("sequencer.paste", text="Paste", icon='PASTEDOWN')
layout.operator("sequencer.duplicate_move")
+ props = layout.operator("wm.call_panel", text="Rename...")
+ props.name = "TOPBAR_PT_name"
+ props.keep_open = False
layout.operator("sequencer.delete", text="Delete...")
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index aa5be13c01b..890250d3daf 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -1320,7 +1320,7 @@ class _defs_gpencil_paint:
icon_prefix="brush.gpencil_draw.",
type=bpy.types.Brush,
attr="gpencil_tool",
- cursor='PAINT_CROSS',
+ cursor='DOT',
tooldef_keywords=dict(
operator="gpencil.draw",
),
@@ -1392,6 +1392,17 @@ class _defs_gpencil_paint:
keymap=(),
)
+ @ToolDef.from_fn
+ def eyedropper():
+ return dict(
+ idname="builtin.eyedropper",
+ label="Eyedropper",
+ icon="ops.paint.weight_sample",
+ cursor='EYEDROPPER',
+ widget=None,
+ keymap=(),
+ )
+
class _defs_gpencil_edit:
@ToolDef.from_fn
@@ -2044,6 +2055,8 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
_defs_gpencil_paint.generate_from_brushes,
_defs_gpencil_paint.cutter,
None,
+ _defs_gpencil_paint.eyedropper,
+ None,
_defs_gpencil_paint.line,
_defs_gpencil_paint.arc,
_defs_gpencil_paint.curve,
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index be41fb52118..4c90f987c50 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -569,6 +569,7 @@ class USERPREF_PT_animation_fcurves(PreferencePanel, Panel):
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow.prop(edit, "fcurve_unselected_alpha", text="F-Curve Visibility")
+ flow.prop(edit, "fcurve_new_auto_smoothing", text="Default Smoothing Mode")
flow.prop(edit, "keyframe_new_interpolation_type", text="Default Interpolation")
flow.prop(edit, "keyframe_new_handle_type", text="Default Handles")
flow.prop(edit, "use_insertkey_xyz_to_rgb", text="XYZ to RGB")
@@ -1479,12 +1480,17 @@ class USERPREF_PT_input_mouse(PreferencePanel, Panel):
return (prefs.active_section == 'INPUT')
def draw_props(self, context, layout):
+ import sys
prefs = context.preferences
inputs = prefs.inputs
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow.prop(inputs, "use_mouse_emulate_3_button")
+ if sys.platform[:3] != "win":
+ rowsub = flow.row()
+ rowsub.active = inputs.use_mouse_emulate_3_button
+ rowsub.prop(inputs, "mouse_emulate_3_button_modifier")
flow.prop(inputs, "use_mouse_continuous")
flow.prop(inputs, "use_drag_immediately")
flow.prop(inputs, "mouse_double_click_time", text="Double Click Speed")
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index aca8ea701ce..93d480ba306 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -351,28 +351,7 @@ class _draw_tool_settings_context_mode:
from bl_ui.properties_paint_common import (
brush_basic_gpencil_paint_settings,
)
- brush_basic_gpencil_paint_settings(layout, context, brush, compact=True)
-
- # FIXME: tools must use their own UI drawing!
- if tool.idname in {"builtin.arc", "builtin.curve", "builtin.line", "builtin.box", "builtin.circle"}:
- settings = context.tool_settings.gpencil_sculpt
- row = layout.row(align=True)
- row.prop(settings, "use_thickness_curve", text="", icon='CURVE_DATA')
- sub = row.row(align=True)
- sub.active = settings.use_thickness_curve
- sub.popover(
- panel="TOPBAR_PT_gpencil_primitive",
- text="Thickness Profile",
- )
-
- if brush.gpencil_tool == 'FILL':
- settings = context.tool_settings.gpencil_sculpt
- row = layout.row(align=True)
- sub = row.row(align=True)
- sub.popover(
- panel="TOPBAR_PT_gpencil_fill",
- text="Fill Options",
- )
+ brush_basic_gpencil_paint_settings(layout, context, brush, tool, compact=True, is_toolbar=True)
@staticmethod
def SCULPT_GPENCIL(context, layout, tool):
@@ -707,10 +686,18 @@ class VIEW3D_HT_header(Header):
row = layout.row()
row.active = (object_mode == 'EDIT') or (shading.type in {'WIREFRAME', 'SOLID'})
- if shading.type == 'WIREFRAME':
- row.prop(shading, "show_xray_wireframe", text="", icon='XRAY')
- else:
- row.prop(shading, "show_xray", text="", icon='XRAY')
+ # While exposing 'shading.show_xray(_wireframe)' is correct.
+ # this hides the key shortcut from users: T70433.
+ row.operator(
+ "view3d.toggle_xray",
+ text="",
+ icon='XRAY',
+ depress=getattr(
+ shading,
+ "show_xray_wireframe" if shading.type == 'WIREFRAME' else
+ "show_xray"
+ ),
+ )
row = layout.row(align=True)
row.prop(shading, "type", text="", expand=True)
@@ -794,6 +781,8 @@ class VIEW3D_MT_editor_menus(Menu):
elif obj:
if mode_string != 'PAINT_TEXTURE':
layout.menu("VIEW3D_MT_%s" % mode_string.lower())
+ if mode_string == 'SCULPT':
+ layout.menu("VIEW3D_MT_mask")
else:
layout.menu("VIEW3D_MT_object")
@@ -2822,20 +2811,29 @@ class VIEW3D_MT_sculpt(Menu):
props.action = 'SHOW'
props.area = 'ALL'
- props = layout.operator("paint.hide_show", text="Hide Bounding Box")
- props.action = 'HIDE'
- props.area = 'INSIDE'
-
props = layout.operator("paint.hide_show", text="Show Bounding Box")
props.action = 'SHOW'
props.area = 'INSIDE'
+ props = layout.operator("paint.hide_show", text="Hide Bounding Box")
+ props.action = 'HIDE'
+ props.area = 'INSIDE'
+
props = layout.operator("paint.hide_show", text="Hide Masked")
props.action = 'HIDE'
props.area = 'MASKED'
layout.separator()
+ layout.menu("VIEW3D_MT_sculpt_set_pivot", text="Set Pivot")
+
+
+class VIEW3D_MT_mask(Menu):
+ bl_label = "Mask"
+
+ def draw(self, _context):
+ layout = self.layout
+
props = layout.operator("paint.mask_flood_fill", text="Invert Mask")
props.mode = 'INVERT'
@@ -2898,9 +2896,6 @@ class VIEW3D_MT_sculpt(Menu):
props = layout.operator("sculpt.dirty_mask", text='Dirty Mask')
- layout.separator()
- layout.menu("VIEW3D_MT_sculpt_set_pivot", text="Set Pivot")
-
class VIEW3D_MT_sculpt_set_pivot(Menu):
bl_label = "Sculpt Set Pivot"
@@ -5070,11 +5065,8 @@ class VIEW3D_PT_collections(Panel):
if not use_local_collections:
subrow.active = collection.is_visible # Parent collection runtime visibility
subrow.prop(child, "hide_viewport", text="", emboss=False)
- elif not child.is_visible:
- subrow.active = False
- subrow.label(text="", icon='REMOVE')
else:
- subrow.active = collection.visible_get() # Parent collection runtime visibility
+ subrow.active = collection.visible_get() # Parent collection runtime visibility
icon = 'HIDE_OFF' if child.visible_get() else 'HIDE_ON'
props = subrow.operator("object.hide_collection", text="", icon=icon, emboss=False)
props.collection_index = index
@@ -6808,6 +6800,7 @@ classes = (
VIEW3D_MT_paint_weight,
VIEW3D_MT_sculpt,
VIEW3D_MT_sculpt_set_pivot,
+ VIEW3D_MT_mask,
VIEW3D_MT_particle,
VIEW3D_MT_particle_context_menu,
VIEW3D_MT_particle_showhide,
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 3aee14e0239..8da5ba67187 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1873,7 +1873,8 @@ class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel):
from bl_ui.properties_paint_common import (
brush_basic_gpencil_paint_settings,
)
- brush_basic_gpencil_paint_settings(layout, context, brush, compact=True)
+ tool = context.workspace.tools.from_space_view3d_mode(context.mode, create=False)
+ brush_basic_gpencil_paint_settings(layout, context, brush, tool, compact=True, is_toolbar=False)
# Grease Pencil drawing brushes options
diff --git a/release/scripts/templates_py/operator_mesh_add.py b/release/scripts/templates_py/operator_mesh_add.py
index d3df64a5501..01a9ad6160e 100644
--- a/release/scripts/templates_py/operator_mesh_add.py
+++ b/release/scripts/templates_py/operator_mesh_add.py
@@ -2,6 +2,7 @@ import bpy
import bmesh
from bpy_extras.object_utils import AddObjectHelper
+
def add_box(width, height, depth):
"""
This function takes inputs and returns vertex and face arrays.
@@ -77,16 +78,16 @@ class AddBox(bpy.types.Operator):
# generic transform props
align_items = (
- ('WORLD', "World", "Align the new object to the world"),
- ('VIEW', "View", "Align the new object to the view"),
- ('CURSOR', "3D Cursor", "Use the 3D cursor orientation for the new object")
+ ('WORLD', "World", "Align the new object to the world"),
+ ('VIEW', "View", "Align the new object to the view"),
+ ('CURSOR', "3D Cursor", "Use the 3D cursor orientation for the new object")
)
align: EnumProperty(
- name="Align",
- items=align_items,
- default='WORLD',
- update=AddObjectHelper.align_update_callback,
- )
+ name="Align",
+ items=align_items,
+ default='WORLD',
+ update=AddObjectHelper.align_update_callback,
+ )
location: FloatVectorProperty(
name="Location",
subtype='TRANSLATION',
diff --git a/release/scripts/templates_py/operator_modal_draw.py b/release/scripts/templates_py/operator_modal_draw.py
index 5dc72c36a8f..1e185ecfe2b 100644
--- a/release/scripts/templates_py/operator_modal_draw.py
+++ b/release/scripts/templates_py/operator_modal_draw.py
@@ -4,6 +4,7 @@ import blf
import gpu
from gpu_extras.batch import batch_for_shader
+
def draw_callback_px(self, context):
print("mouse points", len(self.mouse_path))
diff --git a/release/scripts/templates_py/ui_tool_simple.py b/release/scripts/templates_py/ui_tool_simple.py
index afda5088e69..fc239093b9c 100644
--- a/release/scripts/templates_py/ui_tool_simple.py
+++ b/release/scripts/templates_py/ui_tool_simple.py
@@ -3,9 +3,10 @@
import bpy
from bpy.types import WorkSpaceTool
+
class MyTool(WorkSpaceTool):
- bl_space_type='VIEW_3D'
- bl_context_mode='OBJECT'
+ bl_space_type = 'VIEW_3D'
+ bl_context_mode = 'OBJECT'
# The prefix of the idname should be your add-on name.
bl_idname = "my_template.my_circle_select"
@@ -30,8 +31,8 @@ class MyTool(WorkSpaceTool):
class MyOtherTool(WorkSpaceTool):
- bl_space_type='VIEW_3D'
- bl_context_mode='OBJECT'
+ bl_space_type = 'VIEW_3D'
+ bl_context_mode = 'OBJECT'
bl_idname = "my_template.my_other_select"
bl_label = "My Lasso Tool Select"
@@ -56,9 +57,11 @@ def register():
bpy.utils.register_tool(MyTool, after={"builtin.scale_cage"}, separator=True, group=True)
bpy.utils.register_tool(MyOtherTool, after={MyTool.bl_idname})
+
def unregister():
bpy.utils.unregister_tool(MyTool)
bpy.utils.unregister_tool(MyOtherTool)
+
if __name__ == "__main__":
register()
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index 69a376d00b0..a69178281ff 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -53,6 +53,7 @@ extern "C" {
#include "BKE_anim.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 868c5a69593..b7139d5bbf6 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -212,8 +212,8 @@ void what_does_obaction(struct Object *ob,
float cframe);
/* for proxy */
-void BKE_pose_copyesult_pchan_result(struct bPoseChannel *pchanto,
- const struct bPoseChannel *pchanfrom);
+void BKE_pose_copy_pchan_result(struct bPoseChannel *pchanto,
+ const struct bPoseChannel *pchanfrom);
bool BKE_pose_copy_result(struct bPose *to, struct bPose *from);
/* clear all transforms */
void BKE_pose_rest(struct bPose *pose);
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h
index e55cb69a5c6..b35abb1ecef 100644
--- a/source/blender/blenkernel/BKE_appdir.h
+++ b/source/blender/blenkernel/BKE_appdir.h
@@ -91,5 +91,6 @@ enum {
#define BLENDER_QUIT_FILE "quit.blend"
#define BLENDER_BOOKMARK_FILE "bookmarks.txt"
#define BLENDER_HISTORY_FILE "recent-files.txt"
+#define BLENDER_PLATFORM_SUPPORT_FILE "platform_support.txt"
#endif /* __BKE_APPDIR_H__ */
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 21ef70b7bcd..9bd90f76b79 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -26,8 +26,8 @@
*
* \note Use #STRINGIFY() rather than defining with quotes.
*/
-#define BLENDER_VERSION 281
-#define BLENDER_SUBVERSION 12
+#define BLENDER_VERSION 282
+#define BLENDER_SUBVERSION 0
/** Several breakages with 280, e.g. collections vs layers. */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index 891247f8127..70741831727 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -31,7 +31,6 @@ struct Main;
struct Scene;
struct ToolSettings;
struct UnifiedPaintSettings;
-struct bContext;
// enum eCurveMappingPreset;
diff --git a/source/blender/blenkernel/BKE_editmesh_bvh.h b/source/blender/blenkernel/BKE_editmesh_bvh.h
index e86408076cd..7c8a9452023 100644
--- a/source/blender/blenkernel/BKE_editmesh_bvh.h
+++ b/source/blender/blenkernel/BKE_editmesh_bvh.h
@@ -72,8 +72,8 @@ struct BMFace *BKE_bmbvh_ray_cast_filter(BMBVHTree *tree,
float *r_dist,
float r_hitout[3],
float r_cagehit[3],
- BMBVHTree_FaceFilter filter,
- void *filter_cb);
+ BMBVHTree_FaceFilter filter_cb,
+ void *filter_userdata);
/* find a vert closest to co in a sphere of radius dist_max */
struct BMVert *BKE_bmbvh_find_vert_closest(BMBVHTree *tree,
diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h
index 918f85d146c..9cbc7d05ac2 100644
--- a/source/blender/blenkernel/BKE_gpencil_modifier.h
+++ b/source/blender/blenkernel/BKE_gpencil_modifier.h
@@ -261,12 +261,6 @@ typedef struct GpencilModifierTypeInfo {
struct Object *ob,
GreasePencilTexWalkFunc walk,
void *userData);
-
- /**
- * Get the number of times the strokes are duplicated in this modifier.
- * This is used to calculate the size of the GPU VBOs
- */
- int (*getDuplicationFactor)(struct GpencilModifierData *md);
} GpencilModifierTypeInfo;
/* Initialize modifier's global data (type info and some common global storages). */
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 234b74eece3..82c831ae8e0 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -309,11 +309,11 @@ void BKE_image_get_aspect(struct Image *image, float *aspx, float *aspy);
/* image_gen.c */
void BKE_image_buf_fill_color(
unsigned char *rect, float *rect_float, int width, int height, const float color[4]);
-void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int height, int width);
+void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int width, int height);
void BKE_image_buf_fill_checker_color(unsigned char *rect,
float *rect_float,
- int height,
- int width);
+ int width,
+ int height);
/* Cycles hookup */
unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame);
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 535980840c1..19eb40debe6 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -114,11 +114,13 @@ void BKE_base_set_visible(struct Scene *scene,
struct ViewLayer *view_layer,
struct Base *base,
bool extend);
-void BKE_layer_collection_isolate(struct Scene *scene,
- struct ViewLayer *view_layer,
- struct LayerCollection *lc,
- bool extend);
-void BKE_layer_collection_local_isolate(struct ViewLayer *view_layer,
+bool BKE_base_is_visible(const struct View3D *v3d, const struct Base *base);
+bool BKE_object_is_visible_in_viewport(const struct View3D *v3d, const struct Object *ob);
+void BKE_layer_collection_isolate_global(struct Scene *scene,
+ struct ViewLayer *view_layer,
+ struct LayerCollection *lc,
+ bool extend);
+void BKE_layer_collection_isolate_local(struct ViewLayer *view_layer,
struct View3D *v3d,
struct LayerCollection *lc,
bool extend);
diff --git a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
index cc4a3a01892..86c094b8a6d 100644
--- a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
+++ b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
@@ -43,7 +43,8 @@ struct Mesh *BKE_mesh_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLeve
struct Mesh *BKE_mesh_remesh_voxel_fix_poles(struct Mesh *mesh);
struct Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(struct Mesh *mesh,
float voxel_size,
- float adaptivity);
+ float adaptivity,
+ float isovalue);
struct Mesh *BKE_mesh_remesh_quadriflow_to_mesh_nomain(struct Mesh *mesh,
int target_faces,
int seed,
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index b2bc30c107c..0977a406aa0 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -48,7 +48,9 @@ typedef enum {
*/
eModifierTypeType_OnlyDeform,
+ /* Modifier adds geometry. */
eModifierTypeType_Constructive,
+ /* Modifier can add and remove geometry. */
eModifierTypeType_Nonconstructive,
/* both deformVerts & applyModifier are valid calls
@@ -380,6 +382,7 @@ struct Object *modifiers_isDeformedByArmature(struct Object *ob);
struct Object *modifiers_isDeformedByMeshDeform(struct Object *ob);
struct Object *modifiers_isDeformedByLattice(struct Object *ob);
struct Object *modifiers_isDeformedByCurve(struct Object *ob);
+bool modifiers_usesMultires(struct Object *ob);
bool modifiers_usesArmature(struct Object *ob, struct bArmature *arm);
bool modifiers_usesSubsurfFacedots(struct Scene *scene, struct Object *ob);
bool modifiers_isCorrectableDeformed(struct Scene *scene, struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 06fd7915476..a5b9b1e5148 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -594,7 +594,8 @@ void nodeChainIter(const bNodeTree *ntree,
void nodeChainIterBackwards(const bNodeTree *ntree,
const bNode *node_start,
bool (*callback)(bNode *, bNode *, void *),
- void *userdata);
+ void *userdata,
+ int recursion_lvl);
void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userdata);
struct bNodeLink *nodeFindLink(struct bNodeTree *ntree,
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 8580aefcfbc..4413ad2a70f 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -220,7 +220,7 @@ typedef struct SculptSession {
struct MPoly *mpoly;
struct MLoop *mloop;
int totvert, totpoly;
- struct KeyBlock *kb;
+ struct KeyBlock *shapekey_active;
float *vmask;
/* Mesh connectivity */
@@ -243,10 +243,10 @@ typedef struct SculptSession {
bool show_mask;
/* Painting on deformed mesh */
- bool modifiers_active; /* object is deformed with some modifiers */
- float (*orig_cos)[3]; /* coords of undeformed mesh */
- float (*deform_cos)[3]; /* coords of deformed mesh but without stroke displacement */
- float (*deform_imats)[3][3]; /* crazyspace deformation matrices */
+ bool deform_modifiers_active; /* object is deformed with some modifiers */
+ float (*orig_cos)[3]; /* coords of undeformed mesh */
+ float (*deform_cos)[3]; /* coords of deformed mesh but without stroke displacement */
+ float (*deform_imats)[3][3]; /* crazyspace deformation matrices */
/* Used to cache the render of the active texture */
unsigned int texcache_side, *texcache, texcache_actual;
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index dedf76ee839..13adb868c01 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -28,6 +28,10 @@
/* For embedding CCGKey in iterator. */
#include "BKE_ccg.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct BMLog;
struct BMesh;
struct CCGElem;
@@ -36,6 +40,7 @@ struct CustomData;
struct DMFlagMat;
struct GPU_PBVH_Buffers;
struct IsectRayPrecalc;
+struct Mesh;
struct MLoop;
struct MLoopTri;
struct MPoly;
@@ -44,6 +49,7 @@ struct PBVH;
struct PBVHNode;
struct SubdivCCG;
struct TaskParallelSettings;
+struct TaskParallelTLS;
typedef struct PBVH PBVH;
typedef struct PBVHNode PBVHNode;
@@ -89,6 +95,7 @@ typedef void (*BKE_pbvh_SearchNearestCallback)(PBVHNode *node, void *data, float
PBVH *BKE_pbvh_new(void);
void BKE_pbvh_build_mesh(PBVH *bvh,
+ const struct Mesh *mesh,
const struct MPoly *mpoly,
const struct MLoop *mloop,
struct MVert *verts,
@@ -430,14 +437,39 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node);
-void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings,
- bool use_threading,
- int totnode);
-
// void BKE_pbvh_node_BB_reset(PBVHNode *node);
// void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
bool pbvh_has_mask(PBVH *bvh);
void pbvh_show_mask_set(PBVH *bvh, bool show_mask);
+/* Parallelization */
+typedef void (*PBVHParallelRangeFunc)(void *__restrict userdata,
+ const int iter,
+ const struct TaskParallelTLS *__restrict tls);
+typedef void (*PBVHParallelReduceFunc)(const void *__restrict userdata,
+ void *__restrict chunk_join,
+ void *__restrict chunk);
+
+typedef struct PBVHParallelSettings {
+ bool use_threading;
+ void *userdata_chunk;
+ size_t userdata_chunk_size;
+ PBVHParallelReduceFunc func_reduce;
+} PBVHParallelSettings;
+
+void BKE_pbvh_parallel_range_settings(struct PBVHParallelSettings *settings,
+ bool use_threading,
+ int totnode);
+
+void BKE_pbvh_parallel_range(const int start,
+ const int stop,
+ void *userdata,
+ PBVHParallelRangeFunc func,
+ const struct PBVHParallelSettings *settings);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BKE_PBVH_H__ */
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index 4c023f54e04..b4c440d54a6 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -103,8 +103,14 @@ bool BKE_rigidbody_add_object(struct Main *bmain,
int type,
struct ReportList *reports);
void BKE_rigidbody_ensure_local_object(struct Main *bmain, struct Object *ob);
-void BKE_rigidbody_remove_object(struct Main *bmain, struct Scene *scene, struct Object *ob);
-void BKE_rigidbody_remove_constraint(struct Scene *scene, struct Object *ob);
+void BKE_rigidbody_remove_object(struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob,
+ const bool free_us);
+void BKE_rigidbody_remove_constraint(struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob,
+ const bool free_us);
/* -------------- */
/* Utility Macros */
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 846b8d21f28..51abc7390b8 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -75,7 +75,10 @@ void BKE_scene_free(struct Scene *sce);
void BKE_scene_init(struct Scene *sce);
struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
-void BKE_scene_remove_rigidbody_object(struct Main *bmain, struct Scene *scene, struct Object *ob);
+void BKE_scene_remove_rigidbody_object(struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob,
+ const bool free_us);
bool BKE_scene_object_find(struct Scene *scene, struct Object *ob);
struct Object *BKE_scene_object_find_by_name(struct Scene *scene, const char *name);
@@ -122,7 +125,7 @@ struct Scene *BKE_scene_find_from_collection(const struct Main *bmain,
#ifdef DURIAN_CAMERA_SWITCH
struct Object *BKE_scene_camera_switch_find(struct Scene *scene); // DURIAN_CAMERA_SWITCH
#endif
-int BKE_scene_camera_switch_update(struct Scene *scene);
+bool BKE_scene_camera_switch_update(struct Scene *scene);
char *BKE_scene_find_marker_name(struct Scene *scene, int frame);
char *BKE_scene_find_last_marker_name(struct Scene *scene, int frame);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 16f766ae8bb..a5b223a73f2 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -351,6 +351,7 @@ void BKE_sequencer_prefetch_start(const SeqRenderData *context, float cfra, floa
void BKE_sequencer_prefetch_stop(struct Scene *scene);
void BKE_sequencer_prefetch_free(struct Scene *scene);
bool BKE_sequencer_prefetch_need_redraw(struct Main *bmain, struct Scene *scene);
+bool BKE_sequencer_prefetch_job_is_running(struct Scene *scene);
void BKE_sequencer_prefetch_get_time_range(struct Scene *scene, int *start, int *end);
SeqRenderData *BKE_sequencer_prefetch_get_original_context(const SeqRenderData *context);
struct Sequence *BKE_sequencer_prefetch_get_original_sequence(struct Sequence *seq,
diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h
index e235193a486..409a0d1232b 100644
--- a/source/blender/blenkernel/BKE_subdiv_ccg.h
+++ b/source/blender/blenkernel/BKE_subdiv_ccg.h
@@ -92,6 +92,14 @@ typedef struct SubdivToCCGSettings {
bool need_mask;
} SubdivToCCGSettings;
+typedef struct SubdivCCGCoord {
+ /* Index of the grid within SubdivCCG::grids array. */
+ int grid_index;
+
+ /* Coordinate within the grid. */
+ short x, y;
+} SubdivCCGCoord;
+
/* This is actually a coarse face, which consists of multiple CCG grids. */
typedef struct SubdivCCGFace {
/* Total number of grids in this face.
@@ -106,20 +114,16 @@ typedef struct SubdivCCGFace {
/* Definition of an edge which is adjacent to at least one of the faces. */
typedef struct SubdivCCGAdjacentEdge {
int num_adjacent_faces;
- /* Indexed by adjacent face index. */
- SubdivCCGFace **faces;
/* Indexed by adjacent face index, then by point index on the edge.
- * points to a grid element. */
- struct CCGElem ***boundary_elements;
+ * points to a coordinate into the grids. */
+ struct SubdivCCGCoord **boundary_coords;
} SubdivCCGAdjacentEdge;
/* Definition of a vertex which is adjacent to at least one of the faces. */
typedef struct SubdivCCGAdjacentVertex {
int num_adjacent_faces;
- /* Indexed by adjacent face index. */
- SubdivCCGFace **faces;
- /* Indexed by adjacent face index, points to a grid element. */
- struct CCGElem **corner_elements;
+ /* Indexed by adjacent face index, points to a coordinate in the grids. */
+ struct SubdivCCGCoord *corner_coords;
} SubdivCCGAdjacentVertex;
/* Representation of subdivision surface which uses CCG grids. */
@@ -135,6 +139,9 @@ typedef struct SubdivCCG {
/* Resolution of grid. All grids have matching resolution, and resolution
* is same as ptex created for non-quad polygons. */
int grid_size;
+ /* Size of a single element of a grid (including coordinate and all the other layers).
+ * Measured in bytes. */
+ int grid_element_size;
/* Grids represent limit surface, with displacement applied. Grids are
* corresponding to face-corners of coarse mesh, each grid has
* grid_size^2 elements.
@@ -255,4 +262,40 @@ void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg,
int *r_num_faces,
int *r_num_loops);
+typedef struct SubdivCCGNeighbors {
+ SubdivCCGCoord *coords;
+ int size;
+ int num_duplicates;
+
+ SubdivCCGCoord coords_fixed[256];
+} SubdivCCGNeighbors;
+
+void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord *coord);
+bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord);
+
+/* CCG element neighbors.
+ *
+ * Neighbors are considered:
+ *
+ * - For an inner elements of a grid other elements which are sharing same row or column (4
+ * neighbor elements in total).
+ *
+ * - For the corner element a single neighboring element on every adjacent edge, single from
+ * every gird.
+ *
+ * - For the boundary element two neighbor elements on the boundary (from same grid) and one
+ * element inside of every neighboring grid. */
+
+/* Get actual neighbors of the given coordinate.
+ *
+ * SubdivCCGNeighbors.neighbors must be freed if it is not equal to
+ * SubdivCCGNeighbors.fixed_neighbors.
+ *
+ * If include_duplicates is true, vertices in other grids that match
+ * the current vertex are added at the end of the coords array. */
+void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ const bool include_duplicates,
+ SubdivCCGNeighbors *r_neighbors);
+
#endif /* __BKE_SUBDIV_CCG_H__ */
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index 65aa43ced7c..98a94c5f689 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -78,6 +78,7 @@ void txt_delete_selected(struct Text *text);
void txt_sel_all(struct Text *text);
void txt_sel_clear(struct Text *text);
void txt_sel_line(struct Text *text);
+void txt_sel_set(struct Text *text, int startl, int startc, int endl, int endc);
char *txt_sel_to_buf(struct Text *text, int *r_buf_strlen);
void txt_insert_buf(struct Text *text, const char *in_buffer);
void txt_split_curline(struct Text *text);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 47b44c3828a..ec4246f5dba 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -183,6 +183,7 @@ set(SRC
intern/particle_system.c
intern/pbvh.c
intern/pbvh_bmesh.c
+ intern/pbvh_parallel.cc
intern/pointcache.c
intern/report.c
intern/rigidbody.c
@@ -637,6 +638,14 @@ if(WITH_QUADRIFLOW)
add_definitions(-DWITH_QUADRIFLOW)
endif()
+if(WITH_TBB)
+ add_definitions(-DWITH_TBB)
+
+ list(APPEND INC_SYS
+ ${TBB_INCLUDE_DIRS}
+ )
+endif()
+
## Warnings as errors, this is too strict!
#if(MSVC)
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 4849d631493..2f61cfcbc15 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -1952,7 +1952,7 @@ Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph,
const CustomData_MeshMasks *dataMask)
{
/* This function isn't thread-safe and can't be used during evaluation. */
- BLI_assert(DEG_debug_is_evaluating(depsgraph) == false);
+ BLI_assert(DEG_is_evaluating(depsgraph) == false);
/* Evaluated meshes aren't supposed to be created on original instances. If you do,
* they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */
@@ -1985,7 +1985,7 @@ Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph,
const CustomData_MeshMasks *dataMask)
{
/* This function isn't thread-safe and can't be used during evaluation. */
- BLI_assert(DEG_debug_is_evaluating(depsgraph) == false);
+ BLI_assert(DEG_is_evaluating(depsgraph) == false);
/* Evaluated meshes aren't supposed to be created on original instances. If you do,
* they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index d072a0aa599..de1cbd236fb 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -1472,7 +1472,7 @@ void BKE_pose_rest(bPose *pose)
}
}
-void BKE_pose_copyesult_pchan_result(bPoseChannel *pchanto, const bPoseChannel *pchanfrom)
+void BKE_pose_copy_pchan_result(bPoseChannel *pchanto, const bPoseChannel *pchanfrom)
{
copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat);
copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat);
@@ -1523,7 +1523,7 @@ bool BKE_pose_copy_result(bPose *to, bPose *from)
for (pchanfrom = from->chanbase.first; pchanfrom; pchanfrom = pchanfrom->next) {
pchanto = BKE_pose_channel_find_name(to, pchanfrom->name);
if (pchanto != NULL) {
- BKE_pose_copyesult_pchan_result(pchanto, pchanfrom);
+ BKE_pose_copy_pchan_result(pchanto, pchanfrom);
}
}
return true;
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 00975976130..b6a2efb37b8 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -643,6 +643,10 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph, Scene *UNUSED(scene), Objec
}
BLI_assert(pose->chan_array != NULL || BLI_listbase_is_empty(&pose->chanbase));
+
+ if (object->proxy != NULL) {
+ object->proxy->proxy_from = object;
+ }
}
void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph, Scene *scene, Object *object)
@@ -905,7 +909,7 @@ void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph, Object *object,
pchan->name);
return;
}
- BKE_pose_copyesult_pchan_result(pchan, pchan_from);
+ BKE_pose_copy_pchan_result(pchan, pchan_from);
copy_dq_dq(&pchan->runtime.deform_dual_quat, &pchan_from->runtime.deform_dual_quat);
BKE_pchan_bbone_segments_cache_copy(pchan, pchan_from);
}
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 4187dfa68ad..fe740f4898e 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -590,7 +590,10 @@ void BKE_brush_gpencil_presets(Main *bmain, ToolSettings *ts)
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
/* Fill brush. */
- brush = BKE_brush_add_gpencil(bmain, ts, "Fill Area");
+ brush = BLI_findstring(&bmain->brushes, "Fill Area", offsetof(ID, name) + 2);
+ if (brush == NULL) {
+ brush = BKE_brush_add_gpencil(bmain, ts, "Fill Area");
+ }
brush->size = 20.0f;
brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
@@ -618,7 +621,10 @@ void BKE_brush_gpencil_presets(Main *bmain, ToolSettings *ts)
brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
/* Soft Eraser brush. */
- brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Soft");
+ brush = BLI_findstring(&bmain->brushes, "Eraser Soft", offsetof(ID, name) + 2);
+ if (brush == NULL) {
+ brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Soft");
+ }
brush->size = 30.0f;
brush->gpencil_settings->draw_strength = 0.5f;
brush->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER);
@@ -631,7 +637,10 @@ void BKE_brush_gpencil_presets(Main *bmain, ToolSettings *ts)
brush->gpencil_settings->era_thickness_f = 10.0f;
/* Hard Eraser brush. */
- brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Hard");
+ brush = BLI_findstring(&bmain->brushes, "Eraser Hard", offsetof(ID, name) + 2);
+ if (brush == NULL) {
+ brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Hard");
+ }
brush->size = 30.0f;
brush->gpencil_settings->draw_strength = 1.0f;
brush->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER);
@@ -643,7 +652,10 @@ void BKE_brush_gpencil_presets(Main *bmain, ToolSettings *ts)
brush->gpencil_tool = GPAINT_TOOL_ERASE;
/* Point Eraser brush. */
- brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Point");
+ brush = BLI_findstring(&bmain->brushes, "Eraser Point", offsetof(ID, name) + 2);
+ if (brush == NULL) {
+ brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Point");
+ }
brush->size = 30.0f;
brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_HARD;
@@ -652,7 +664,10 @@ void BKE_brush_gpencil_presets(Main *bmain, ToolSettings *ts)
brush->gpencil_tool = GPAINT_TOOL_ERASE;
/* Stroke Eraser brush. */
- brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Stroke");
+ brush = BLI_findstring(&bmain->brushes, "Eraser Stroke", offsetof(ID, name) + 2);
+ if (brush == NULL) {
+ brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Stroke");
+ }
brush->size = 30.0f;
brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_STROKE;
@@ -909,6 +924,13 @@ void BKE_brush_sculpt_reset(Brush *br)
case SCULPT_TOOL_CLAY:
br->flag |= BRUSH_FRONTFACE;
break;
+ case SCULPT_TOOL_CLAY_STRIPS:
+ br->flag |= BRUSH_ACCUMULATE;
+ br->alpha = 0.7f;
+ br->normal_radius_factor = 1.7f;
+ br->curve_preset = BRUSH_CURVE_SPHERE;
+ br->spacing = 6;
+ break;
case SCULPT_TOOL_CREASE:
br->flag |= BRUSH_DIR_IN;
br->alpha = 0.25;
@@ -928,6 +950,7 @@ void BKE_brush_sculpt_reset(Brush *br)
break;
case SCULPT_TOOL_SNAKE_HOOK:
br->alpha = 1.0f;
+ br->rake_factor = 1.0f;
break;
case SCULPT_TOOL_THUMB:
br->size = 75;
@@ -968,12 +991,12 @@ void BKE_brush_sculpt_reset(Brush *br)
case SCULPT_TOOL_INFLATE:
case SCULPT_TOOL_BLOB:
case SCULPT_TOOL_CREASE:
- br->add_col[0] = 0.65f;
- br->add_col[1] = 0.85f;
- br->add_col[2] = 0.9f;
- br->sub_col[0] = 0.65f;
- br->sub_col[1] = 0.85f;
- br->sub_col[2] = 0.9f;
+ br->add_col[0] = 0.5f;
+ br->add_col[1] = 0.7f;
+ br->add_col[2] = 0.875f;
+ br->sub_col[0] = 0.5f;
+ br->sub_col[1] = 0.7f;
+ br->sub_col[2] = 0.875f;
break;
case SCULPT_TOOL_SMOOTH:
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 63d58f7e32e..463cbd4f378 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -772,7 +772,7 @@ static int cloth_from_object(
clmd->clothObject->old_solver_type = 255;
clmd->clothObject->edgeset = NULL;
}
- else if (!clmd->clothObject) {
+ else {
modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject");
return 0;
}
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index f2098cc2430..68a38c94ff7 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -773,7 +773,7 @@ static bool scene_collections_object_remove(
bool removed = false;
if (collection_skip == NULL) {
- BKE_scene_remove_rigidbody_object(bmain, scene, ob);
+ BKE_scene_remove_rigidbody_object(bmain, scene, ob, free_us);
}
FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
@@ -1305,6 +1305,9 @@ bool BKE_collection_move(Main *bmain,
BLI_ghash_free(view_layer_hash, NULL, NULL);
+ /* We need to sync it again to pass the correct flags to the collections objects. */
+ BKE_main_collection_sync(bmain);
+
return true;
}
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 6740fc985e9..fe834658689 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -355,7 +355,7 @@ static void crazyspace_init_verts_and_matrices(const Mesh *mesh,
BLI_assert(num_verts == mesh->totvert);
}
-static bool crazyspace_modifier_supports_deform(ModifierData *md)
+static bool crazyspace_modifier_supports_deform_matrices(ModifierData *md)
{
if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) {
return true;
@@ -364,6 +364,12 @@ static bool crazyspace_modifier_supports_deform(ModifierData *md)
return (mti->type == eModifierTypeType_OnlyDeform);
}
+static bool crazyspace_modifier_supports_deform(ModifierData *md)
+{
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ return (mti->type == eModifierTypeType_OnlyDeform);
+}
+
int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
Scene *scene,
Object *object,
@@ -391,13 +397,12 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
md = modifiers_getVirtualModifierList(&object_eval, &virtualModifierData);
for (; md; md = md->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
continue;
}
- if (mti->type == eModifierTypeType_OnlyDeform) {
+ if (crazyspace_modifier_supports_deform_matrices(md)) {
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (defmats == NULL) {
/* NOTE: Evaluated object si re-set to its original undeformed
* state. */
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index cbd3c91acc7..46f6a604eaa 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -624,7 +624,7 @@ void BKE_displist_fill(ListBase *dispbase,
static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
{
- const float z_up[3] = {0.0f, 0.0f, 1.0f};
+ const float z_up[3] = {0.0f, 0.0f, -1.0f};
ListBase front, back;
DispList *dl, *dlnew;
float *fp, *fp1;
@@ -703,7 +703,7 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis
bevels_to_filledpoly(cu, dispbase);
}
else {
- const float z_up[3] = {0.0f, 0.0f, 1.0f};
+ const float z_up[3] = {0.0f, 0.0f, -1.0f};
BKE_displist_fill(dispbase, dispbase, z_up, false);
}
}
@@ -1730,11 +1730,11 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
if (cu->bevobj && (cu->flag & CU_FILL_CAPS) && !(nu->flagu & CU_NURB_CYCLIC)) {
if (a == 1) {
fillBevelCap(nu, dlb, cur_data - 3 * dlb->nr, &bottom_capbase);
- negate_v3_v3(bottom_no, bevp->dir);
+ copy_v3_v3(bottom_no, bevp->dir);
}
if (a == steps - 1) {
fillBevelCap(nu, dlb, cur_data, &top_capbase);
- copy_v3_v3(top_no, bevp->dir);
+ negate_v3_v3(top_no, bevp->dir);
}
}
}
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 48c0258bf47..10499ae0b5c 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -821,7 +821,7 @@ static void fcm_noise_evaluate(
FMod_Noise *data = (FMod_Noise *)fcm->data;
float noise;
- /* generate noise using good ol' Blender Noise
+ /* generate noise using good old Blender Noise
* - 0.1 is passed as the 'z' value, otherwise evaluation fails for size = phase = 1
* with evaltime being an integer (which happens when evaluating on frame by frame basis)
*/
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index b55635560be..250e6ff6a7b 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -397,6 +397,9 @@ static void build_underline(Curve *cu,
copy_v4_fl4(bp[2].vec, rect->xmax, (rect->ymin + yofs), 0.0f, 1.0f);
copy_v4_fl4(bp[3].vec, rect->xmin, (rect->ymin + yofs), 0.0f, 1.0f);
+ /* Used by curve extrusion. */
+ bp[0].radius = bp[1].radius = bp[2].radius = bp[3].radius = 1.0f;
+
nu2->bp = bp;
BLI_addtail(nubase, nu2);
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index f78833a0ebe..e885aa04881 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1397,6 +1397,7 @@ void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
bGPdata *gpd = ob->data;
MDeformVert *dvert = NULL;
const int def_nr = BLI_findindex(&ob->defbase, defgroup);
+ const int totgrp = BLI_listbase_count(&ob->defbase);
/* Remove points data */
if (gpd) {
@@ -1411,9 +1412,9 @@ void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
defvert_remove_group(dvert, dw);
}
else {
- /* reorganize weights in other strokes */
- for (int g = 0; g < gps->dvert->totweight; g++) {
- dw = &dvert->dw[g];
+ /* Reorganize weights for other groups after deleted one. */
+ for (int g = 0; g < totgrp; g++) {
+ dw = defvert_find_index(dvert, g);
if ((dw != NULL) && (dw->def_nr > def_nr)) {
dw->def_nr--;
}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index bc682ffb8c8..332549c6b47 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -569,7 +569,7 @@ Image *BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exist
char str[FILE_MAX], strtest[FILE_MAX];
STRNCPY(str, filepath);
- BLI_path_abs(str, BKE_main_blendfile_path_from_global());
+ BLI_path_abs(str, bmain->name);
/* first search an identical filepath */
for (ima = bmain->images.first; ima; ima = ima->id.next) {
@@ -5310,7 +5310,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
char str[FILE_MAX];
STRNCPY(str, iv->filepath);
- BLI_path_abs(str, BKE_main_blendfile_path_from_global());
+ BLI_path_abs(str, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
/* exists? */
file = BLI_open(str, O_BINARY | O_RDONLY, 0);
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 9b18052ef1e..fd5b4b6e506 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -44,6 +44,7 @@
#include "DNA_object_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_workspace_types.h"
@@ -56,9 +57,10 @@
#include "MEM_guardedalloc.h"
/* Set of flags which are dependent on a collection settings. */
-static const short g_base_collection_flags = (BASE_VISIBLE | BASE_SELECTABLE |
- BASE_ENABLED_VIEWPORT | BASE_ENABLED_RENDER |
- BASE_HOLDOUT | BASE_INDIRECT_ONLY);
+static const short g_base_collection_flags = (BASE_VISIBLE_DEPSGRAPH | BASE_VISIBLE_VIEWLAYER |
+ BASE_SELECTABLE | BASE_ENABLED_VIEWPORT |
+ BASE_ENABLED_RENDER | BASE_HOLDOUT |
+ BASE_INDIRECT_ONLY);
/* prototype */
static void object_bases_iterator_next(BLI_Iterator *iter, const int flag);
@@ -735,9 +737,15 @@ static short layer_collection_sync(ViewLayer *view_layer,
lc->runtime_flag = child_runtime_flag;
}
- if (((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) &&
+ /* We separate restrict viewport and visible view layer because a layer collection can be
+ * hidden in the view layer yet (locally) visible in a viewport (if it is not restricted).*/
+ if (child_restrict & COLLECTION_RESTRICT_VIEWPORT) {
+ lc->runtime_flag |= LAYER_COLLECTION_RESTRICT_VIEWPORT;
+ }
+
+ if (((lc->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) == 0) &&
((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0)) {
- lc->runtime_flag |= LAYER_COLLECTION_VISIBLE;
+ lc->runtime_flag |= LAYER_COLLECTION_VISIBLE_VIEW_LAYER;
}
/* Sync objects, except if collection was excluded. */
@@ -771,12 +779,12 @@ static short layer_collection_sync(ViewLayer *view_layer,
}
if ((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) {
- base->flag_from_collection |= BASE_ENABLED_VIEWPORT;
+ base->flag_from_collection |= (BASE_ENABLED_VIEWPORT | BASE_VISIBLE_DEPSGRAPH);
if ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0) {
- base->flag_from_collection |= BASE_VISIBLE;
- if (((child_restrict & COLLECTION_RESTRICT_SELECT) == 0)) {
- base->flag_from_collection |= BASE_SELECTABLE;
- }
+ base->flag_from_collection |= BASE_VISIBLE_VIEWLAYER;
+ }
+ if (((child_restrict & COLLECTION_RESTRICT_SELECT) == 0)) {
+ base->flag_from_collection |= BASE_SELECTABLE;
}
}
@@ -974,7 +982,7 @@ bool BKE_layer_collection_has_selected_objects(ViewLayer *view_layer, LayerColle
for (CollectionObject *cob = lc->collection->gobject.first; cob; cob = cob->next) {
Base *base = BKE_view_layer_base_find(view_layer, cob->ob);
- if (base && (base->flag & BASE_SELECTED) && (base->flag & BASE_VISIBLE)) {
+ if (base && (base->flag & BASE_SELECTED) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) {
return true;
}
}
@@ -1026,6 +1034,60 @@ void BKE_base_set_visible(Scene *scene, ViewLayer *view_layer, Base *base, bool
BKE_layer_collection_sync(scene, view_layer);
}
+bool BKE_base_is_visible(const View3D *v3d, const Base *base)
+{
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
+ return false;
+ }
+
+ if (v3d == NULL) {
+ return base->flag & BASE_VISIBLE_VIEWLAYER;
+ }
+
+ if ((v3d->localvd) && ((v3d->local_view_uuid & base->local_view_bits) == 0)) {
+ return false;
+ }
+
+ if (((1 << (base->object->type)) & v3d->object_type_exclude_viewport) != 0) {
+ return false;
+ }
+
+ if (v3d->flag & V3D_LOCAL_COLLECTIONS) {
+ return (v3d->local_collections_uuid & base->local_collections_bits) != 0;
+ }
+
+ return base->flag & BASE_VISIBLE_VIEWLAYER;
+}
+
+bool BKE_object_is_visible_in_viewport(const struct View3D *v3d, const struct Object *ob)
+{
+ BLI_assert(v3d != NULL);
+
+ if (ob->restrictflag & OB_RESTRICT_VIEWPORT) {
+ return false;
+ }
+
+ if ((v3d->object_type_exclude_viewport & (1 << ob->type)) != 0) {
+ return false;
+ }
+
+ if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
+ return false;
+ }
+
+ if ((v3d->flag & V3D_LOCAL_COLLECTIONS) &&
+ ((v3d->local_collections_uuid & ob->runtime.local_collections_bits) == 0)) {
+ return false;
+ }
+
+ /* If not using local view or local collection the object may still be in a hidden collection. */
+ if (((v3d->localvd) == NULL) && ((v3d->flag & V3D_LOCAL_COLLECTIONS) == 0)) {
+ return (ob->base_flag & BASE_VISIBLE_VIEWLAYER) != 0;
+ }
+
+ return true;
+}
+
static void layer_collection_flag_set_recursive(LayerCollection *lc, const int flag)
{
lc->flag |= flag;
@@ -1050,13 +1112,13 @@ static void layer_collection_flag_unset_recursive(LayerCollection *lc, const int
* If the collection or any of its parents is disabled, make it enabled.
* Don't change the children disable state though.
*/
-void BKE_layer_collection_isolate(Scene *scene,
- ViewLayer *view_layer,
- LayerCollection *lc,
- bool extend)
+void BKE_layer_collection_isolate_global(Scene *scene,
+ ViewLayer *view_layer,
+ LayerCollection *lc,
+ bool extend)
{
LayerCollection *lc_master = view_layer->layer_collections.first;
- bool hide_it = extend && (lc->runtime_flag & LAYER_COLLECTION_VISIBLE);
+ bool hide_it = extend && (lc->runtime_flag & LAYER_COLLECTION_VISIBLE_VIEW_LAYER);
if (!extend) {
/* Hide all collections . */
@@ -1163,9 +1225,9 @@ void BKE_layer_collection_local_sync(ViewLayer *view_layer, View3D *v3d)
/**
* Isolate the collection locally
*
- * Same as BKE_layer_collection_local_isolate but for a viewport
+ * Same as BKE_layer_collection_isolate_local but for a viewport
*/
-void BKE_layer_collection_local_isolate(ViewLayer *view_layer,
+void BKE_layer_collection_isolate_local(ViewLayer *view_layer,
View3D *v3d,
LayerCollection *lc,
bool extend)
@@ -1436,12 +1498,12 @@ static void objects_iterator_end(BLI_Iterator *iter)
void BKE_view_layer_selected_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
{
- objects_iterator_begin(iter, data_in, BASE_VISIBLE | BASE_SELECTED);
+ objects_iterator_begin(iter, data_in, BASE_VISIBLE_DEPSGRAPH | BASE_SELECTED);
}
void BKE_view_layer_selected_objects_iterator_next(BLI_Iterator *iter)
{
- objects_iterator_next(iter, BASE_VISIBLE | BASE_SELECTED);
+ objects_iterator_next(iter, BASE_VISIBLE_DEPSGRAPH | BASE_SELECTED);
}
void BKE_view_layer_selected_objects_iterator_end(BLI_Iterator *iter)
@@ -1478,7 +1540,7 @@ void BKE_view_layer_visible_objects_iterator_end(BLI_Iterator *iter)
void BKE_view_layer_selected_editable_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
{
- objects_iterator_begin(iter, data_in, BASE_VISIBLE | BASE_SELECTED);
+ objects_iterator_begin(iter, data_in, BASE_VISIBLE_DEPSGRAPH | BASE_SELECTED);
if (iter->valid) {
if (BKE_object_is_libdata((Object *)iter->current) == false) {
// First object is valid (selectable and not libdata) -> all good.
@@ -1495,7 +1557,7 @@ void BKE_view_layer_selected_editable_objects_iterator_next(BLI_Iterator *iter)
{
// Search while there are objects and the one we have is not editable (editable = not libdata).
do {
- objects_iterator_next(iter, BASE_VISIBLE | BASE_SELECTED);
+ objects_iterator_next(iter, BASE_VISIBLE_DEPSGRAPH | BASE_SELECTED);
} while (iter->valid && BKE_object_is_libdata((Object *)iter->current) != false);
}
@@ -1512,12 +1574,12 @@ void BKE_view_layer_selected_editable_objects_iterator_end(BLI_Iterator *iter)
void BKE_view_layer_selected_bases_iterator_begin(BLI_Iterator *iter, void *data_in)
{
- objects_iterator_begin(iter, data_in, BASE_VISIBLE | BASE_SELECTED);
+ objects_iterator_begin(iter, data_in, BASE_VISIBLE_DEPSGRAPH | BASE_SELECTED);
}
void BKE_view_layer_selected_bases_iterator_next(BLI_Iterator *iter)
{
- object_bases_iterator_next(iter, BASE_VISIBLE | BASE_SELECTED);
+ object_bases_iterator_next(iter, BASE_VISIBLE_DEPSGRAPH | BASE_SELECTED);
}
void BKE_view_layer_selected_bases_iterator_end(BLI_Iterator *iter)
@@ -1617,7 +1679,8 @@ void BKE_view_layer_bases_in_mode_iterator_end(BLI_Iterator *UNUSED(iter))
/* Evaluation */
/* Applies object's restrict flags on top of flags coming from the collection
- * and stores those in base->flag. BASE_VISIBLE is based on viewport visibility. */
+ * and stores those in base->flag. BASE_VISIBLE_DEPSGRAPH ignores viewport flags visibility
+ * (i.e., restriction and local collection). */
void BKE_base_eval_flags(Base *base)
{
/* Apply collection flags. */
@@ -1640,7 +1703,7 @@ void BKE_base_eval_flags(Base *base)
* can change these again, but for tools we always want the viewport
* visibility to be in sync regardless if depsgraph was evaluated. */
if (!(base->flag & BASE_ENABLED_VIEWPORT) || (base->flag & BASE_HIDDEN)) {
- base->flag &= ~(BASE_VISIBLE | BASE_SELECTABLE);
+ base->flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_VISIBLE_VIEWLAYER | BASE_SELECTABLE);
}
/* Deselect unselectable objects. */
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 468d0e97ece..909db9c7b52 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -1468,8 +1468,12 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
new_id->flag = (new_id->flag & ~copy_idflag_mask) | (id->flag & copy_idflag_mask);
+ /* We do not want any handling of usercount in code duplicating the data here, we do that all
+ * at once in id_copy_libmanagement_cb() at the end. */
+ const int copy_data_flag = orig_flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+
if (id->properties) {
- new_id->properties = IDP_CopyProperty_ex(id->properties, flag);
+ new_id->properties = IDP_CopyProperty_ex(id->properties, copy_data_flag);
}
/* XXX Again... We need a way to control what we copy in a much more refined way.
@@ -1488,10 +1492,9 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
if ((flag & LIB_ID_COPY_NO_ANIMDATA) == 0) {
/* Note that even though horrors like root nodetrees are not in bmain, the actions they use
* in their anim data *are* in bmain... super-mega-hooray. */
- int animdata_flag = orig_flag;
- BLI_assert((animdata_flag & LIB_ID_COPY_ACTIONS) == 0 ||
- (animdata_flag & LIB_ID_CREATE_NO_MAIN) == 0);
- iat->adt = BKE_animdata_copy(bmain, iat->adt, animdata_flag);
+ BLI_assert((copy_data_flag & LIB_ID_COPY_ACTIONS) == 0 ||
+ (copy_data_flag & LIB_ID_CREATE_NO_MAIN) == 0);
+ iat->adt = BKE_animdata_copy(bmain, iat->adt, copy_data_flag);
}
else {
iat->adt = NULL;
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index e03903c05e4..e6cfea6fb03 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -589,7 +589,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
(do_aspect_correct && width > height) ? (float)height / (float)width : 1.0f,
(do_aspect_correct && width < height) ? (float)width / (float)height : 1.0f};
- const float zvec[3] = {0.0f, 0.0f, 1.0f};
+ const float zvec[3] = {0.0f, 0.0f, -1.0f};
MaskLayer *masklay;
unsigned int masklay_index;
MemArena *sf_arena;
diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.c b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
index 8419a72f97e..b93fe157f2a 100644
--- a/source/blender/blenkernel/intern/mesh_remesh_voxel.c
+++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
@@ -295,7 +295,10 @@ Mesh *BKE_mesh_remesh_quadriflow_to_mesh_nomain(Mesh *mesh,
return new_mesh;
}
-Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(Mesh *mesh, float voxel_size, float adaptivity)
+Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(Mesh *mesh,
+ float voxel_size,
+ float adaptivity,
+ float isovalue)
{
Mesh *new_mesh = NULL;
#ifdef WITH_OPENVDB
@@ -304,7 +307,7 @@ Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(Mesh *mesh, float voxel_size, float a
OpenVDBTransform_create_linear_transform(xform, (double)voxel_size);
level_set = BKE_mesh_remesh_voxel_ovdb_mesh_to_level_set_create(mesh, xform);
new_mesh = BKE_mesh_remesh_voxel_ovdb_volume_to_mesh_nomain(
- level_set, 0.0, (float)adaptivity, false);
+ level_set, (double)isovalue, (double)adaptivity, false);
OpenVDBLevelSet_free(level_set);
OpenVDBTransform_free(xform);
#else
@@ -444,6 +447,12 @@ struct Mesh *BKE_mesh_remesh_voxel_fix_poles(struct Mesh *mesh)
}
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+ BM_mesh_elem_hflag_enable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BMO_op_callf(bm,
+ (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
+ "recalc_face_normals faces=%hf",
+ BM_ELEM_TAG);
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
Mesh *result = BKE_mesh_from_bmesh_nomain(bm,
(&(struct BMeshToMeshParams){
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index c8e75532075..fa03aec3e08 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -1619,6 +1619,12 @@ void BKE_mesh_calc_edges_loose(Mesh *mesh)
for (int i = 0; i < mesh->totloop; i++, ml++) {
mesh->medge[ml->e].flag &= ~ME_LOOSEEDGE;
}
+ med = mesh->medge;
+ for (int i = 0; i < mesh->totedge; i++, med++) {
+ if (med->flag & ME_LOOSEEDGE) {
+ med->flag |= ME_EDGEDRAW;
+ }
+ }
}
/**
diff --git a/source/blender/blenkernel/intern/mirror.c b/source/blender/blenkernel/intern/mirror.c
index c429b953015..02e0a2bb3b9 100644
--- a/source/blender/blenkernel/intern/mirror.c
+++ b/source/blender/blenkernel/intern/mirror.c
@@ -169,13 +169,13 @@ Mesh *BKE_mirror_apply_mirror_on_axis(MirrorModifierData *mmd,
result = BKE_mesh_new_nomain_from_template(
mesh, maxVerts * 2, maxEdges * 2, 0, maxLoops * 2, maxPolys * 2);
- /*copy customdata to original geometry*/
+ /* Copy custom-data to original geometry. */
CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, maxVerts);
CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, maxEdges);
CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, maxLoops);
CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, maxPolys);
- /* Subsurf for eg won't have mesh data in the custom data arrays.
+ /* Subsurf for eg won't have mesh data in the custom-data arrays.
* now add mvert/medge/mpoly layers. */
if (!CustomData_has_layer(&mesh->vdata, CD_MVERT)) {
memcpy(result->mvert, mesh->mvert, sizeof(*result->mvert) * mesh->totvert);
@@ -188,8 +188,8 @@ Mesh *BKE_mirror_apply_mirror_on_axis(MirrorModifierData *mmd,
memcpy(result->mpoly, mesh->mpoly, sizeof(*result->mpoly) * mesh->totpoly);
}
- /* copy customdata to new geometry,
- * copy from its self because this data may have been created in the checks above */
+ /* Copy custom-data to new geometry,
+ * copy from its self because this data may have been created in the checks above. */
CustomData_copy_data(&result->vdata, &result->vdata, 0, maxVerts, maxVerts);
CustomData_copy_data(&result->edata, &result->edata, 0, maxEdges, maxEdges);
/* loops are copied later */
@@ -321,6 +321,12 @@ Mesh *BKE_mirror_apply_mirror_on_axis(MirrorModifierData *mmd,
MLoopNorSpaceArray lnors_spacearr = {NULL};
float(*poly_normals)[3] = MEM_mallocN(sizeof(*poly_normals) * totpoly, __func__);
+ /* The transform matrix of a normal must be
+ * the transpose of inverse of transform matrix of the geometry... */
+ float mtx_nor[4][4];
+ invert_m4_m4(mtx_nor, mtx);
+ transpose_m4(mtx_nor);
+
/* calculate custom normals into loop_normals, then mirror first half into second half */
BKE_mesh_calc_normals_poly(result->mvert,
@@ -361,7 +367,7 @@ Mesh *BKE_mirror_apply_mirror_on_axis(MirrorModifierData *mmd,
mirrorj += mpmirror->totloop - (j - mp->loopstart);
}
copy_v3_v3(loop_normals[mirrorj], loop_normals[j]);
- loop_normals[mirrorj][axis] = -loop_normals[j][axis];
+ mul_m4_v3(mtx_nor, loop_normals[mirrorj]);
BKE_lnor_space_custom_normal_to_data(
lnors_spacearr.lspacearr[mirrorj], loop_normals[mirrorj], clnors[mirrorj]);
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 656ec50f31b..1c83bec17e5 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -761,6 +761,23 @@ Object *modifiers_isDeformedByCurve(Object *ob)
return NULL;
}
+bool modifiers_usesMultires(Object *ob)
+{
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+ MultiresModifierData *mmd = NULL;
+
+ for (; md; md = md->next) {
+ if (md->type == eModifierType_Multires) {
+ mmd = (MultiresModifierData *)md;
+ if (mmd->totlvl != 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
bool modifiers_usesArmature(Object *ob, bArmature *arm)
{
VirtualModifierData virtualModifierData;
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index f67bc419210..9385a9ae24d 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -409,8 +409,8 @@ typedef struct MovieClipCache {
/* cache for undistorted shot */
float principal[2];
- float polynomial_k1, polynomial_k2, polynomial_k3;
- float division_k1, division_k2;
+ float polynomial_k1;
+ float division_k1;
short distortion_model;
bool undistortion_used;
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 2cc1083aba3..09581debd99 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -1488,7 +1488,7 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
/* set default flags */
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
- fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+ fcu->auto_smoothing = U.auto_smoothing_new;
/* store path - make copy, and store that */
fcu->rna_path = BLI_strdupn("influence", 9);
@@ -1515,7 +1515,7 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
/* set default flags */
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
- fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+ fcu->auto_smoothing = U.auto_smoothing_new;
/* store path - make copy, and store that */
fcu->rna_path = BLI_strdupn("strip_time", 10);
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 0ef35bd3d06..779728cb037 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -950,7 +950,8 @@ void nodeChainIter(const bNodeTree *ntree,
static void iter_backwards_ex(const bNodeTree *ntree,
const bNode *node_start,
bool (*callback)(bNode *, bNode *, void *),
- void *userdata)
+ void *userdata,
+ char recursion_mask)
{
LISTBASE_FOREACH (bNodeSocket *, sock, &node_start->inputs) {
bNodeLink *link = sock->link;
@@ -961,18 +962,17 @@ static void iter_backwards_ex(const bNodeTree *ntree,
/* Skip links marked as cyclic. */
continue;
}
- if (link->fromnode->iter_flag) {
- /* Only iter on nodes once. */
+ if (link->fromnode->iter_flag & recursion_mask) {
continue;
}
else {
- link->fromnode->iter_flag = 1;
+ link->fromnode->iter_flag |= recursion_mask;
}
if (!callback(link->fromnode, link->tonode, userdata)) {
return;
}
- iter_backwards_ex(ntree, link->fromnode, callback, userdata);
+ iter_backwards_ex(ntree, link->fromnode, callback, userdata, recursion_mask);
}
}
@@ -981,6 +981,8 @@ static void iter_backwards_ex(const bNodeTree *ntree,
* \a callback for each node (which can return false to end iterator).
*
* Faster than nodeChainIter. Iter only once per node.
+ * Can be called recursively (using another nodeChainIterBackwards) by
+ * setting the recursion_lvl accordingly.
*
* \note Needs updated socket links (ntreeUpdateTree).
* \note Recursive
@@ -988,14 +990,23 @@ static void iter_backwards_ex(const bNodeTree *ntree,
void nodeChainIterBackwards(const bNodeTree *ntree,
const bNode *node_start,
bool (*callback)(bNode *, bNode *, void *),
- void *userdata)
+ void *userdata,
+ int recursion_lvl)
{
+ if (!node_start) {
+ return;
+ }
+
+ /* Limited by iter_flag type. */
+ BLI_assert(recursion_lvl < 8);
+ char recursion_mask = (1 << recursion_lvl);
+
/* Reset flag. */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- node->iter_flag = 0;
+ node->iter_flag &= ~recursion_mask;
}
- iter_backwards_ex(ntree, node_start, callback, userdata);
+ iter_backwards_ex(ntree, node_start, callback, userdata, recursion_mask);
}
/**
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index f10930a2ba7..773e2d19b22 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -680,7 +680,7 @@ bool BKE_object_is_mode_compat(const struct Object *ob, eObjectMode object_mode)
*/
int BKE_object_visibility(const Object *ob, const int dag_eval_mode)
{
- if ((ob->base_flag & BASE_VISIBLE) == 0) {
+ if ((ob->base_flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
return 0;
}
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 01f3f2e309b..21ca5e6d6a6 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -439,10 +439,10 @@ void BKE_object_eval_eval_base_flags(Depsgraph *depsgraph,
* assumed viewport visibility. Select-ability does not matter here. */
if (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER) {
if (base->flag & BASE_ENABLED_RENDER) {
- base->flag |= BASE_VISIBLE;
+ base->flag |= BASE_VISIBLE_DEPSGRAPH;
}
else {
- base->flag &= ~BASE_VISIBLE;
+ base->flag &= ~BASE_VISIBLE_DEPSGRAPH;
}
}
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index cc3b10b1207..5fa3352d497 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -267,11 +267,7 @@ void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
}
if (tot > 0) {
- BKE_reportf(reports,
- RPT_INFO,
- tot == 1 ? "Packed %d file" :
- "Packed %d files",
- tot);
+ BKE_reportf(reports, RPT_INFO, "Packed %d file(s)", tot);
}
else if (verbose) {
BKE_report(reports, RPT_INFO, "No new files have been packed");
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 983127372ca..cc9d1b98ba4 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -224,7 +224,6 @@ const EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(ePaintMode mode)
return rna_enum_brush_image_tool_items;
case PAINT_MODE_SCULPT_UV:
return rna_enum_brush_uv_sculpt_tool_items;
- return NULL;
case PAINT_MODE_GPENCIL:
return rna_enum_brush_gpencil_types_items;
case PAINT_MODE_INVALID:
@@ -1185,7 +1184,7 @@ static void sculpt_update_object(
Mesh *me = BKE_object_get_original_mesh(ob);
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
- ss->modifiers_active = sculpt_modifiers_active(scene, sd, ob);
+ ss->deform_modifiers_active = sculpt_modifiers_active(scene, sd, ob);
ss->show_mask = (sd->flags & SCULPT_HIDE_MASK) == 0;
ss->building_vp_handle = false;
@@ -1206,7 +1205,7 @@ static void sculpt_update_object(
/* tessfaces aren't used and will become invalid */
BKE_mesh_tessface_clear(me);
- ss->kb = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL;
+ ss->shapekey_active = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL;
/* NOTE: Weight pPaint require mesh info for loop lookup, but it never uses multires code path,
* so no extra checks is needed here. */
@@ -1241,14 +1240,15 @@ static void sculpt_update_object(
pbvh_show_mask_set(ss->pbvh, ss->show_mask);
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
if (!ss->orig_cos) {
int a;
BKE_sculptsession_free_deformMats(ss);
- ss->orig_cos = (ss->kb) ? BKE_keyblock_convert_to_vertcos(ob, ss->kb) :
- BKE_mesh_vert_coords_alloc(me, NULL);
+ ss->orig_cos = (ss->shapekey_active) ?
+ BKE_keyblock_convert_to_vertcos(ob, ss->shapekey_active) :
+ BKE_mesh_vert_coords_alloc(me, NULL);
BKE_crazyspace_build_sculpt(depsgraph, scene, ob, &ss->deform_imats, &ss->deform_cos);
BKE_pbvh_vert_coords_apply(ss->pbvh, ss->deform_cos, me->totvert);
@@ -1262,15 +1262,15 @@ static void sculpt_update_object(
BKE_sculptsession_free_deformMats(ss);
}
- if (ss->kb != NULL && ss->deform_cos == NULL) {
- ss->deform_cos = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
+ if (ss->shapekey_active != NULL && ss->deform_cos == NULL) {
+ ss->deform_cos = BKE_keyblock_convert_to_vertcos(ob, ss->shapekey_active);
}
/* if pbvh is deformed, key block is already applied to it */
- if (ss->kb) {
+ if (ss->shapekey_active) {
bool pbvh_deformed = BKE_pbvh_is_deformed(ss->pbvh);
if (!pbvh_deformed || ss->deform_cos == NULL) {
- float(*vertCos)[3] = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
+ float(*vertCos)[3] = BKE_keyblock_convert_to_vertcos(ob, ss->shapekey_active);
if (vertCos) {
if (!pbvh_deformed) {
@@ -1449,17 +1449,17 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc
* on birth of PBVH and sculpt "layer" levels, so use PBVH only for internal brush
* stuff and show final evaluated mesh so user would see actual object shape.
*/
- deformed |= object->sculpt->modifiers_active;
+ deformed |= object->sculpt->deform_modifiers_active;
if (for_construction) {
- deformed |= object->sculpt->kb != NULL;
+ deformed |= object->sculpt->shapekey_active != NULL;
}
else {
/* As in case with modifiers, we can't synchronize deformation made against
* PBVH and non-locked keyblock, so also use PBVH only for brushes and
* final DM to give final result to user.
*/
- deformed |= object->sculpt->kb && (object->shapeflag & OB_SHAPE_LOCK) == 0;
+ deformed |= object->sculpt->shapekey_active && (object->shapeflag & OB_SHAPE_LOCK) == 0;
}
return deformed;
@@ -1489,6 +1489,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform)
BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
BKE_pbvh_build_mesh(pbvh,
+ me,
me->mpoly,
me->mloop,
me->mvert,
@@ -1588,7 +1589,7 @@ bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const View3D *v3d)
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
/* Regular mesh only draws from PBVH without modifiers and shape keys. */
const bool full_shading = (v3d && (v3d->shading.type > OB_SOLID));
- return !(ss->kb || ss->modifiers_active || full_shading);
+ return !(ss->shapekey_active || ss->deform_modifiers_active || full_shading);
}
else {
/* Multires and dyntopo always draw directly from the PBVH. */
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 7ed986204d5..01612ded396 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -27,6 +27,7 @@
#include "BLI_ghash.h"
#include "BLI_task.h"
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_pbvh.h"
@@ -533,6 +534,7 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
* (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply().
*/
void BKE_pbvh_build_mesh(PBVH *bvh,
+ const Mesh *mesh,
const MPoly *mpoly,
const MLoop *mloop,
MVert *verts,
@@ -545,6 +547,7 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
BBC *prim_bbc = NULL;
BB cb;
+ bvh->mesh = mesh;
bvh->type = PBVH_FACES;
bvh->mpoly = mpoly;
bvh->mloop = mloop;
@@ -1093,12 +1096,11 @@ static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode)
.vnors = vnors,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
- BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings);
-
- BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings);
MEM_freeN(vnors);
}
@@ -1148,9 +1150,9 @@ static void pbvh_update_mask_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, in
.flag = flag,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
- BLI_task_parallel_range(0, totnode, &data, pbvh_update_mask_redraw_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_mask_redraw_task_cb, &settings);
}
static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata,
@@ -1186,9 +1188,9 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
.flag = flag,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
- BLI_task_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings);
}
static int pbvh_get_buffers_update_flags(PBVH *bvh, bool show_vcol)
@@ -1222,7 +1224,8 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
bvh->looptri,
bvh->verts,
node->prim_indices,
- node->totprim);
+ node->totprim,
+ bvh->mesh);
break;
case PBVH_BMESH:
node->draw_buffers = GPU_pbvh_bmesh_buffers_build(bvh->flags &
@@ -1295,9 +1298,9 @@ static void pbvh_update_draw_buffers(
.show_vcol = show_vcol,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
- BLI_task_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings);
}
static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
@@ -1905,14 +1908,11 @@ static bool pbvh_faces_node_raycast(PBVH *bvh,
const MVert *vert = bvh->verts;
const MLoop *mloop = bvh->mloop;
const int *faces = node->prim_indices;
- int i, totface = node->totprim;
+ int totface = node->totprim;
bool hit = false;
- float min_depth = FLT_MAX;
- float location[3] = {0.0f};
- float nearest_vertex_co[3];
- copy_v3_fl(nearest_vertex_co, 0.0f);
+ float nearest_vertex_co[3] = {0.0f};
- for (i = 0; i < totface; i++) {
+ for (int i = 0; i < totface; i++) {
const MLoopTri *lt = &bvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i];
@@ -1920,35 +1920,33 @@ static bool pbvh_faces_node_raycast(PBVH *bvh,
continue;
}
+ const float *co[3];
if (origco) {
/* intersect with backuped original coordinates */
- hit |= ray_face_intersection_tri(ray_start,
- isect_precalc,
- origco[face_verts[0]],
- origco[face_verts[1]],
- origco[face_verts[2]],
- depth);
+ co[0] = origco[face_verts[0]];
+ co[1] = origco[face_verts[1]];
+ co[2] = origco[face_verts[2]];
}
else {
/* intersect with current coordinates */
- hit |= ray_face_intersection_tri(ray_start,
- isect_precalc,
- vert[mloop[lt->tri[0]].v].co,
- vert[mloop[lt->tri[1]].v].co,
- vert[mloop[lt->tri[2]].v].co,
- depth);
-
- if (hit && *depth < min_depth) {
- min_depth = *depth;
- normal_tri_v3(r_face_normal,
- vert[mloop[lt->tri[0]].v].co,
- vert[mloop[lt->tri[1]].v].co,
- vert[mloop[lt->tri[2]].v].co);
+ co[0] = vert[mloop[lt->tri[0]].v].co;
+ co[1] = vert[mloop[lt->tri[1]].v].co;
+ co[2] = vert[mloop[lt->tri[2]].v].co;
+ }
+
+ if (ray_face_intersection_tri(ray_start, isect_precalc, co[0], co[1], co[2], depth)) {
+ hit = true;
+
+ if (r_face_normal) {
+ normal_tri_v3(r_face_normal, co[0], co[1], co[2]);
+ }
+
+ if (r_active_vertex_index) {
+ float location[3] = {0.0f};
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
for (int j = 0; j < 3; j++) {
- if (len_squared_v3v3(location, vert[mloop[lt->tri[j]].v].co) <
- len_squared_v3v3(location, nearest_vertex_co)) {
- copy_v3_v3(nearest_vertex_co, vert[mloop[lt->tri[j]].v].co);
+ if (len_squared_v3v3(location, co[j]) < len_squared_v3v3(location, nearest_vertex_co)) {
+ copy_v3_v3(nearest_vertex_co, co[j]);
*r_active_vertex_index = mloop[lt->tri[j]].v;
}
}
@@ -1963,22 +1961,28 @@ static bool pbvh_grids_node_raycast(PBVH *bvh,
PBVHNode *node,
float (*origco)[3],
const float ray_start[3],
+ const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
- float *depth)
+ float *depth,
+ int *r_active_vertex_index,
+ float *r_face_normal)
{
const int totgrid = node->totprim;
const int gridsize = bvh->gridkey.grid_size;
bool hit = false;
+ float nearest_vertex_co[3] = {0.0};
+ const CCGKey *gridkey = &bvh->gridkey;
for (int i = 0; i < totgrid; i++) {
- CCGElem *grid = bvh->grids[node->prim_indices[i]];
+ const int grid_index = node->prim_indices[i];
+ CCGElem *grid = bvh->grids[grid_index];
BLI_bitmap *gh;
if (!grid) {
continue;
}
- gh = bvh->grid_hidden[node->prim_indices[i]];
+ gh = bvh->grid_hidden[grid_index];
for (int y = 0; y < gridsize - 1; y++) {
for (int x = 0; x < gridsize - 1; x++) {
@@ -1989,23 +1993,40 @@ static bool pbvh_grids_node_raycast(PBVH *bvh,
}
}
+ const float *co[4];
if (origco) {
- hit |= ray_face_intersection_quad(ray_start,
- isect_precalc,
- origco[y * gridsize + x],
- origco[y * gridsize + x + 1],
- origco[(y + 1) * gridsize + x + 1],
- origco[(y + 1) * gridsize + x],
- depth);
+ co[0] = origco[y * gridsize + x];
+ co[1] = origco[y * gridsize + x + 1];
+ co[2] = origco[(y + 1) * gridsize + x + 1];
+ co[3] = origco[(y + 1) * gridsize + x];
}
else {
- hit |= ray_face_intersection_quad(ray_start,
- isect_precalc,
- CCG_grid_elem_co(&bvh->gridkey, grid, x, y),
- CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y),
- CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1),
- CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1),
- depth);
+ co[0] = CCG_grid_elem_co(gridkey, grid, x, y);
+ co[1] = CCG_grid_elem_co(gridkey, grid, x + 1, y);
+ co[2] = CCG_grid_elem_co(gridkey, grid, x + 1, y + 1);
+ co[3] = CCG_grid_elem_co(gridkey, grid, x, y + 1);
+ }
+
+ if (ray_face_intersection_quad(
+ ray_start, isect_precalc, co[0], co[1], co[2], co[3], depth)) {
+ hit = true;
+
+ if (r_face_normal) {
+ normal_quad_v3(r_face_normal, co[0], co[1], co[2], co[3]);
+ }
+
+ if (r_active_vertex_index) {
+ float location[3] = {0.0};
+ madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
+ for (int j = 0; j < 4; j++) {
+ if (len_squared_v3v3(location, co[j]) <
+ len_squared_v3v3(location, nearest_vertex_co)) {
+ copy_v3_v3(nearest_vertex_co, co[j]);
+ *r_active_vertex_index = gridkey->grid_area * grid_index + y * gridkey->grid_size +
+ x;
+ }
+ }
+ }
}
}
}
@@ -2048,7 +2069,15 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
face_normal);
break;
case PBVH_GRIDS:
- hit |= pbvh_grids_node_raycast(bvh, node, origco, ray_start, isect_precalc, depth);
+ hit |= pbvh_grids_node_raycast(bvh,
+ node,
+ origco,
+ ray_start,
+ ray_normal,
+ isect_precalc,
+ depth,
+ active_vertex_index,
+ face_normal);
break;
case PBVH_BMESH:
BM_mesh_elem_index_ensure(bvh->bm, BM_VERT);
@@ -2712,13 +2741,10 @@ void pbvh_show_mask_set(PBVH *bvh, bool show_mask)
bvh->show_mask = show_mask;
}
-void BKE_pbvh_parallel_range_settings(TaskParallelSettings *settings,
+void BKE_pbvh_parallel_range_settings(PBVHParallelSettings *settings,
bool use_threading,
int totnode)
{
- const int threaded_limit = 1;
- BLI_parallel_range_settings_defaults(settings);
- settings->use_threading = use_threading && (totnode > threaded_limit);
- settings->min_iter_per_thread = 1;
- settings->scheduling_mode = TASK_SCHEDULING_DYNAMIC;
+ memset(settings, 0, sizeof(*settings));
+ settings->use_threading = use_threading && totnode > 1;
}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index c04e172f116..6d38ae13994 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -1516,10 +1516,8 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
float *r_face_normal)
{
bool hit = false;
-
- float min_depth = FLT_MAX;
float nearest_vertex_co[3] = {0.0f};
- float location[3] = {0.0f};
+
if (use_original && node->bm_tot_ortri) {
for (int i = 0; i < node->bm_tot_ortri; i++) {
const int *t = node->bm_ortri[i];
@@ -1542,18 +1540,24 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
BMVert *v_tri[3];
BM_face_as_array_vert_tri(f, v_tri);
- hit |= ray_face_intersection_tri(
- ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth);
-
- if (hit && *depth < min_depth) {
- min_depth = *depth;
- normal_tri_v3(r_face_normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
- madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
- for (int j = 0; j < 3; j++) {
- if (len_squared_v3v3(location, v_tri[j]->co) <
- len_squared_v3v3(location, nearest_vertex_co)) {
- copy_v3_v3(nearest_vertex_co, v_tri[j]->co);
- *r_active_vertex_index = BM_elem_index_get(v_tri[j]);
+
+ if (ray_face_intersection_tri(
+ ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth)) {
+ hit = true;
+
+ if (r_face_normal) {
+ normal_tri_v3(r_face_normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
+ }
+
+ if (r_active_vertex_index) {
+ float location[3] = {0.0f};
+ madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
+ for (int j = 0; j < 3; j++) {
+ if (len_squared_v3v3(location, v_tri[j]->co) <
+ len_squared_v3v3(location, nearest_vertex_co)) {
+ copy_v3_v3(nearest_vertex_co, v_tri[j]->co);
+ *r_active_vertex_index = BM_elem_index_get(v_tri[j]);
+ }
}
}
}
@@ -1974,7 +1978,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
if (mode & PBVH_Collapse) {
EdgeQueue q;
- BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert * [2]), 0, 128, BLI_MEMPOOL_NOP);
+ BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 0, 128, BLI_MEMPOOL_NOP);
EdgeQueueContext eq_ctx = {
&q,
queue_pool,
@@ -1993,7 +1997,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
if (mode & PBVH_Subdivide) {
EdgeQueue q;
- BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert * [2]), 0, 128, BLI_MEMPOOL_NOP);
+ BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 0, 128, BLI_MEMPOOL_NOP);
EdgeQueueContext eq_ctx = {
&q,
queue_pool,
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index bad103743eb..bdee05f1aab 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -127,6 +127,7 @@ struct PBVH {
int leaf_limit;
/* Mesh data */
+ const struct Mesh *mesh;
MVert *verts;
const MPoly *mpoly;
const MLoop *mloop;
diff --git a/source/blender/blenkernel/intern/pbvh_parallel.cc b/source/blender/blenkernel/intern/pbvh_parallel.cc
new file mode 100644
index 00000000000..aa4c659c8bd
--- /dev/null
+++ b/source/blender/blenkernel/intern/pbvh_parallel.cc
@@ -0,0 +1,145 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_task.h"
+#include "BLI_threads.h"
+
+#include "BKE_pbvh.h"
+
+#include "atomic_ops.h"
+
+#ifdef WITH_TBB
+
+# include <tbb/tbb.h>
+
+/* Functor for running TBB parallel_for and parallel_reduce. */
+struct PBVHTask {
+ PBVHParallelRangeFunc func;
+ void *userdata;
+ const PBVHParallelSettings *settings;
+
+ void *userdata_chunk;
+
+ /* Root constructor. */
+ PBVHTask(PBVHParallelRangeFunc func, void *userdata, const PBVHParallelSettings *settings)
+ : func(func), userdata(userdata), settings(settings)
+ {
+ init_chunk(settings->userdata_chunk);
+ }
+
+ /* Copy constructor. */
+ PBVHTask(const PBVHTask &other)
+ : func(other.func), userdata(other.userdata), settings(other.settings)
+ {
+ init_chunk(other.userdata_chunk);
+ }
+
+ /* Splitting constructor for parallel reduce. */
+ PBVHTask(PBVHTask &other, tbb::split)
+ : func(other.func), userdata(other.userdata), settings(other.settings)
+ {
+ init_chunk(settings->userdata_chunk);
+ }
+
+ ~PBVHTask()
+ {
+ MEM_SAFE_FREE(userdata_chunk);
+ }
+
+ void init_chunk(void *from_chunk)
+ {
+ if (from_chunk) {
+ userdata_chunk = MEM_mallocN(settings->userdata_chunk_size, "PBVHTask");
+ memcpy(userdata_chunk, from_chunk, settings->userdata_chunk_size);
+ }
+ else {
+ userdata_chunk = NULL;
+ }
+ }
+
+ void operator()(const tbb::blocked_range<int> &r) const
+ {
+ TaskParallelTLS tls;
+ tls.thread_id = get_thread_id();
+ tls.userdata_chunk = userdata_chunk;
+ for (int i = r.begin(); i != r.end(); ++i) {
+ func(userdata, i, &tls);
+ }
+ }
+
+ void join(const PBVHTask &other)
+ {
+ settings->func_reduce(userdata, userdata_chunk, other.userdata_chunk);
+ }
+
+ int get_thread_id() const
+ {
+ /* Get a unique thread ID for texture nodes. In the future we should get rid
+ * of the thread ID and change texture evaluation to not require per-thread
+ * storage that can't be efficiently allocated on the stack. */
+ static tbb::enumerable_thread_specific<int> pbvh_thread_id(-1);
+ static int pbvh_thread_id_counter = 0;
+
+ int &thread_id = pbvh_thread_id.local();
+ if (thread_id == -1) {
+ thread_id = atomic_fetch_and_add_int32(&pbvh_thread_id_counter, 1);
+ if (thread_id >= BLENDER_MAX_THREADS) {
+ BLI_assert(!"Maximum number of threads exceeded for sculpting");
+ thread_id = thread_id % BLENDER_MAX_THREADS;
+ }
+ }
+ return thread_id;
+ }
+};
+
+#endif
+
+void BKE_pbvh_parallel_range(const int start,
+ const int stop,
+ void *userdata,
+ PBVHParallelRangeFunc func,
+ const struct PBVHParallelSettings *settings)
+{
+#ifdef WITH_TBB
+ /* Multithreading. */
+ if (settings->use_threading) {
+ PBVHTask task(func, userdata, settings);
+
+ if (settings->func_reduce) {
+ parallel_reduce(tbb::blocked_range<int>(start, stop), task);
+ if (settings->userdata_chunk) {
+ memcpy(settings->userdata_chunk, task.userdata_chunk, settings->userdata_chunk_size);
+ }
+ }
+ else {
+ parallel_for(tbb::blocked_range<int>(start, stop), task);
+ }
+
+ return;
+ }
+#endif
+
+ /* Single threaded. Nothing to reduce as everything is accumulated into the
+ * main userdata chunk directly. */
+ TaskParallelTLS tls;
+ tls.thread_id = 0;
+ tls.userdata_chunk = settings->userdata_chunk;
+ for (int i = start; i < stop; i++) {
+ func(userdata, i, &tls);
+ }
+}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 514f000d73d..c57808f3dee 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -51,6 +51,7 @@
#include "BKE_collection.h"
#include "BKE_effect.h"
+#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
@@ -61,7 +62,6 @@
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
#ifdef WITH_BULLET
-# include "BKE_global.h"
# include "BKE_library.h"
# include "BKE_library_query.h"
#endif
@@ -174,13 +174,22 @@ void BKE_rigidbody_free_object(Object *ob, RigidBodyWorld *rbw)
/* free physics references */
if (is_orig) {
if (rbo->shared->physics_object) {
- BLI_assert(rbw);
- if (rbw) {
+ if (rbw != NULL) {
/* We can only remove the body from the world if the world is known.
* The world is generally only unknown if it's an evaluated copy of
* an object that's being freed, in which case this code isn't run anyway. */
RB_dworld_remove_body(rbw->shared->physics_world, rbo->shared->physics_object);
}
+ else {
+ /* We have no access to 'owner' RBW when deleting the object ID itself... No choice bu to
+ * loop over all scenes then. */
+ for (Scene *scene = G_MAIN->scenes.first; scene != NULL; scene = scene->id.next) {
+ RigidBodyWorld *scene_rbw = scene->rigidbody_world;
+ if (scene_rbw != NULL) {
+ RB_dworld_remove_body(scene_rbw->shared->physics_world, rbo->shared->physics_object);
+ }
+ }
+ }
RB_body_delete(rbo->shared->physics_object);
rbo->shared->physics_object = NULL;
@@ -1415,7 +1424,7 @@ bool BKE_rigidbody_add_object(Main *bmain, Scene *scene, Object *ob, int type, R
return true;
}
-void BKE_rigidbody_remove_object(Main *bmain, Scene *scene, Object *ob)
+void BKE_rigidbody_remove_object(Main *bmain, Scene *scene, Object *ob, const bool free_us)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
RigidBodyCon *rbc;
@@ -1438,8 +1447,13 @@ void BKE_rigidbody_remove_object(Main *bmain, Scene *scene, Object *ob)
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->constraints, obt) {
if (obt && obt->rigidbody_constraint) {
rbc = obt->rigidbody_constraint;
- if (ELEM(ob, rbc->ob1, rbc->ob2)) {
- BKE_rigidbody_remove_constraint(scene, obt);
+ if (rbc->ob1 == ob) {
+ rbc->ob1 = NULL;
+ DEG_id_tag_update(&obt->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ if (rbc->ob2 == ob) {
+ rbc->ob2 = NULL;
+ DEG_id_tag_update(&obt->id, ID_RECALC_COPY_ON_WRITE);
}
}
}
@@ -1454,7 +1468,7 @@ void BKE_rigidbody_remove_object(Main *bmain, Scene *scene, Object *ob)
* when we remove them from RB simulation. */
BKE_collection_object_add(bmain, scene->master_collection, ob);
}
- BKE_collection_object_remove(bmain, rbw->group, ob, false);
+ BKE_collection_object_remove(bmain, rbw->group, ob, free_us);
}
/* remove object's settings */
@@ -1468,15 +1482,24 @@ void BKE_rigidbody_remove_object(Main *bmain, Scene *scene, Object *ob)
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
-void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
+void BKE_rigidbody_remove_constraint(Main *bmain, Scene *scene, Object *ob, const bool free_us)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
RigidBodyCon *rbc = ob->rigidbody_constraint;
- /* remove from rigidbody world, free object won't do this */
- if (rbw && rbw->shared->physics_world && rbc->physics_constraint) {
- RB_dworld_remove_constraint(rbw->shared->physics_world, rbc->physics_constraint);
+ if (rbw != NULL) {
+ /* Remove from RBW constraints collection. */
+ if (rbw->constraints != NULL) {
+ BKE_collection_object_remove(bmain, rbw->constraints, ob, free_us);
+ DEG_id_tag_update(&rbw->constraints->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ /* remove from rigidbody world, free object won't do this */
+ if (rbw->shared->physics_world && rbc->physics_constraint) {
+ RB_dworld_remove_constraint(rbw->shared->physics_world, rbc->physics_constraint);
+ }
}
+
/* remove object's settings */
BKE_rigidbody_free_constraint(ob);
@@ -1657,9 +1680,12 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph,
float ctime = DEG_get_ctime(depsgraph);
/* update world */
- if (rebuild) {
- BKE_rigidbody_validate_sim_world(scene, rbw, true);
+ /* Note physics_world can get NULL when undoing the deletion of the last object in it (see
+ * T70667). */
+ if (rebuild || rbw->shared->physics_world == NULL) {
+ BKE_rigidbody_validate_sim_world(scene, rbw, rebuild);
}
+
rigidbody_update_sim_world(scene, rbw);
/* XXX TODO For rebuild: remove all constraints first.
@@ -2086,10 +2112,10 @@ bool BKE_rigidbody_add_object(Main *bmain, Scene *scene, Object *ob, int type, R
return false;
}
-void BKE_rigidbody_remove_object(struct Main *bmain, Scene *scene, Object *ob)
+void BKE_rigidbody_remove_object(struct Main *bmain, Scene *scene, Object *ob, const bool free_us)
{
}
-void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
+void BKE_rigidbody_remove_constraint(Main *bmain, Scene *scene, Object *ob, const bool free_us)
{
}
void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 4f855bd7d98..53e5f1fdfe5 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -1008,19 +1008,19 @@ Object *BKE_scene_camera_switch_find(Scene *scene)
}
#endif
-int BKE_scene_camera_switch_update(Scene *scene)
+bool BKE_scene_camera_switch_update(Scene *scene)
{
#ifdef DURIAN_CAMERA_SWITCH
Object *camera = BKE_scene_camera_switch_find(scene);
- if (camera) {
+ if (camera && (camera != scene->camera)) {
scene->camera = camera;
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- return 1;
+ return true;
}
#else
(void)scene;
#endif
- return 0;
+ return false;
}
char *BKE_scene_find_marker_name(Scene *scene, int frame)
@@ -1076,15 +1076,18 @@ int BKE_scene_frame_snap_by_seconds(Scene *scene, double interval_in_seconds, in
return (delta_prev < delta_next) ? second_prev : second_next;
}
-void BKE_scene_remove_rigidbody_object(struct Main *bmain, Scene *scene, Object *ob)
+void BKE_scene_remove_rigidbody_object(struct Main *bmain,
+ Scene *scene,
+ Object *ob,
+ const bool free_us)
{
/* remove rigid body constraint from world before removing object */
if (ob->rigidbody_constraint) {
- BKE_rigidbody_remove_constraint(scene, ob);
+ BKE_rigidbody_remove_constraint(bmain, scene, ob, free_us);
}
/* remove rigid body object from world before removing object */
if (ob->rigidbody_object) {
- BKE_rigidbody_remove_object(bmain, scene, ob);
+ BKE_rigidbody_remove_object(bmain, scene, ob, free_us);
}
}
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
index d12710690df..ccb1869ee21 100644
--- a/source/blender/blenkernel/intern/seqcache.c
+++ b/source/blender/blenkernel/intern/seqcache.c
@@ -244,7 +244,8 @@ static SeqCacheKey *seq_cache_choose_key(Scene *scene, SeqCacheKey *lkey, SeqCac
* We could use temp cache as a shield and later make it a non-temporary entry,
* but it is not worth of increasing system complexity.
*/
- if (scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) {
+ if (scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE &&
+ BKE_sequencer_prefetch_job_is_running(scene)) {
int pfjob_start, pfjob_end;
BKE_sequencer_prefetch_get_time_range(scene, &pfjob_start, &pfjob_end);
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index dbdaaaa5fc3..236fb43e89c 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -3822,7 +3822,7 @@ void BKE_sequencer_text_font_load(TextVars *data, const bool do_id_user)
char path[FILE_MAX];
STRNCPY(path, data->text_font->name);
BLI_assert(BLI_thread_is_main());
- BLI_path_abs(path, BKE_main_blendfile_path_from_global());
+ BLI_path_abs(path, ID_BLEND_PATH_FROM_GLOBAL(&data->text_font->id));
data->text_blf_id = BLF_load(path);
}
diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c
index a7543881dad..57b8c92de3e 100644
--- a/source/blender/blenkernel/intern/seqmodifier.c
+++ b/source/blender/blenkernel/intern/seqmodifier.c
@@ -34,6 +34,7 @@
#include "BLT_translation.h"
+#include "DNA_mask_types.h"
#include "DNA_sequence_types.h"
#include "DNA_scene_types.h"
@@ -1044,7 +1045,7 @@ ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context,
frame_offset = seq->start;
}
else /*if (smd->mask_time == SEQUENCE_MASK_TIME_ABSOLUTE)*/ {
- frame_offset = 0;
+ frame_offset = ((Mask *)smd->mask_id)->sfra;
}
ImBuf *mask = modifier_mask_get(smd, context, cfra, frame_offset, ibuf->rect_float != NULL);
diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c
index c1109347e76..6dd1c47407f 100644
--- a/source/blender/blenkernel/intern/seqprefetch.c
+++ b/source/blender/blenkernel/intern/seqprefetch.c
@@ -31,6 +31,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_anim_types.h"
#include "BLI_listbase.h"
#include "BLI_threads.h"
@@ -55,6 +56,7 @@ typedef struct PrefetchJob {
struct PrefetchJob *next, *prev;
struct Main *bmain;
+ struct Main *bmain_eval;
struct Scene *scene;
struct Scene *scene_eval;
struct Depsgraph *depsgraph;
@@ -109,7 +111,7 @@ static PrefetchJob *seq_prefetch_job_get(Scene *scene)
return NULL;
}
-static bool seq_prefetch_job_is_running(Scene *scene)
+bool BKE_sequencer_prefetch_job_is_running(Scene *scene)
{
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
@@ -185,12 +187,12 @@ static void seq_prefetch_free_depsgraph(PrefetchJob *pfjob)
static void seq_prefetch_update_depsgraph(PrefetchJob *pfjob)
{
DEG_evaluate_on_framechange(
- pfjob->bmain, pfjob->depsgraph, pfjob->cfra + pfjob->num_frames_prefetched);
+ pfjob->bmain_eval, pfjob->depsgraph, pfjob->cfra + pfjob->num_frames_prefetched);
}
static void seq_prefetch_init_depsgraph(PrefetchJob *pfjob)
{
- Main *bmain = pfjob->bmain;
+ Main *bmain = pfjob->bmain_eval;
Scene *scene = pfjob->scene;
ViewLayer *view_layer = BKE_view_layer_default_render(scene);
@@ -198,7 +200,7 @@ static void seq_prefetch_init_depsgraph(PrefetchJob *pfjob)
DEG_debug_name_set(pfjob->depsgraph, "SEQUENCER PREFETCH");
/* Make sure there is a correct evaluated scene pointer. */
- DEG_graph_build_for_render_pipeline(pfjob->depsgraph, pfjob->bmain, scene, view_layer);
+ DEG_graph_build_for_render_pipeline(pfjob->depsgraph, bmain, scene, view_layer);
/* Update immediately so we have proper evaluated scene. */
seq_prefetch_update_depsgraph(pfjob);
@@ -229,7 +231,9 @@ static void seq_prefetch_update_area(PrefetchJob *pfjob)
}
}
-/* Use also to update scene and context changes */
+/* Use also to update scene and context changes
+ * This function should almost always be called by cache invalidation, not directly.
+ */
void BKE_sequencer_prefetch_stop(Scene *scene)
{
PrefetchJob *pfjob;
@@ -251,7 +255,7 @@ static void seq_prefetch_update_context(const SeqRenderData *context)
PrefetchJob *pfjob;
pfjob = seq_prefetch_job_get(context->scene);
- BKE_sequencer_new_render_data(pfjob->bmain,
+ BKE_sequencer_new_render_data(pfjob->bmain_eval,
pfjob->depsgraph,
pfjob->scene_eval,
context->rectx,
@@ -314,6 +318,7 @@ void BKE_sequencer_prefetch_free(Scene *scene)
BLI_mutex_end(&pfjob->prefetch_suspend_mutex);
BLI_condition_end(&pfjob->prefetch_suspend_cond);
seq_prefetch_free_depsgraph(pfjob);
+ BKE_main_free(pfjob->bmain_eval);
MEM_freeN(pfjob);
scene->ed->prefetch_job = NULL;
}
@@ -322,16 +327,26 @@ static void *seq_prefetch_frames(void *job)
{
PrefetchJob *pfjob = (PrefetchJob *)job;
- /* set to NULL before return! */
- pfjob->scene_eval->ed->prefetch_job = pfjob;
+ while (pfjob->cfra + pfjob->num_frames_prefetched <= pfjob->scene->r.efra) {
+ pfjob->scene_eval->ed->prefetch_job = NULL;
- while (pfjob->cfra + pfjob->num_frames_prefetched < pfjob->scene->r.efra) {
- BKE_animsys_evaluate_all_animation(pfjob->context_cpy.bmain,
- pfjob->context_cpy.depsgraph,
- pfjob->context_cpy.scene,
- pfjob->cfra + pfjob->num_frames_prefetched);
+ AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id);
+ BKE_animsys_evaluate_animdata(pfjob->context_cpy.scene,
+ &pfjob->context_cpy.scene->id,
+ adt,
+ pfjob->cfra + pfjob->num_frames_prefetched,
+ ADT_RECALC_ALL,
+ false);
seq_prefetch_update_depsgraph(pfjob);
+ /* This is quite hacky solution:
+ * We need cross-reference original scene with copy for cache.
+ * However depsgraph must not have this data, because it will try to kill this job.
+ * Scene copy don't reference original scene. Perhaps, this could be done by depsgraph.
+ * Set to NULL before return!
+ */
+ pfjob->scene_eval->ed->prefetch_job = pfjob;
+
ImBuf *ibuf = BKE_sequencer_give_ibuf(
&pfjob->context_cpy, pfjob->cfra + pfjob->num_frames_prefetched, 0);
BKE_sequencer_cache_free_temp_cache(
@@ -373,8 +388,7 @@ static void *seq_prefetch_frames(void *job)
static PrefetchJob *seq_prefetch_start(const SeqRenderData *context, float cfra)
{
- PrefetchJob *pfjob;
- pfjob = seq_prefetch_job_get(context->scene);
+ PrefetchJob *pfjob = seq_prefetch_job_get(context->scene);
if (!pfjob) {
if (context->scene->ed) {
@@ -386,6 +400,7 @@ static PrefetchJob *seq_prefetch_start(const SeqRenderData *context, float cfra)
BLI_condition_init(&pfjob->prefetch_suspend_cond);
pfjob->bmain = context->bmain;
+ pfjob->bmain_eval = BKE_main_new();
pfjob->scene = context->scene;
seq_prefetch_init_depsgraph(pfjob);
@@ -419,7 +434,7 @@ void BKE_sequencer_prefetch_start(const SeqRenderData *context, float cfra, floa
if (!context->is_prefetch_render && !context->is_proxy_render) {
bool playing = seq_prefetch_is_playing(context->bmain);
bool scrubbing = seq_prefetch_is_scrubbing(context->bmain);
- bool running = seq_prefetch_job_is_running(scene);
+ bool running = BKE_sequencer_prefetch_job_is_running(scene);
seq_prefetch_resume(scene);
/* conditions to start:
* prefetch enabled, prefetch not running, not scrubbing,
@@ -437,7 +452,7 @@ bool BKE_sequencer_prefetch_need_redraw(Main *bmain, Scene *scene)
{
bool playing = seq_prefetch_is_playing(bmain);
bool scrubbing = seq_prefetch_is_scrubbing(bmain);
- bool running = seq_prefetch_job_is_running(scene);
+ bool running = BKE_sequencer_prefetch_job_is_running(scene);
bool suspended = seq_prefetch_job_is_waiting(scene);
/* force redraw, when prefetching and using cache view. */
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 3e88db787ee..26dd9aab511 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -3340,7 +3340,8 @@ static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr
/* anim-data */
adt = BKE_animdata_from_id(&mask->id);
- BKE_animsys_evaluate_animdata(context->scene, &mask_temp->id, adt, nr, ADT_RECALC_ANIM, false);
+ BKE_animsys_evaluate_animdata(
+ context->scene, &mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false);
maskbuf = MEM_mallocN(sizeof(float) * context->rectx * context->recty, __func__);
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 797ae0f0a8a..28f552cec2e 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -1516,6 +1516,7 @@ void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object
ssmd.shrinkType = MOD_SHRINKWRAP_TARGET_PROJECT;
ssmd.shrinkMode = MOD_SHRINKWRAP_ON_SURFACE;
ssmd.keepDist = 0.0f;
+ ssmd.projLimit = target_me->remesh_voxel_size;
float(*vertexCos)[3] = BKE_mesh_vert_coords_alloc(src_me, &totvert);
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index e6c414b92da..3db51c95fcb 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -2527,17 +2527,13 @@ static void update_flowsfluids(
}
/* sample subframes */
else {
-# if 0
int scene_frame = (int)DEG_get_ctime(depsgraph);
-# endif
// float scene_subframe = scene->r.subframe; // UNUSED
int subframe;
for (subframe = 0; subframe <= subframes; subframe++) {
EmissionMap em_temp = {NULL};
float sample_size = 1.0f / (float)(subframes + 1);
-# if 0
float prev_frame_pos = sample_size * (float)(subframe + 1);
-# endif
float sdt = dt * sample_size;
int hires_multiplier = 1;
@@ -2545,8 +2541,6 @@ static void update_flowsfluids(
hires_multiplier = sds->amplify + 1;
}
- /* TODO: setting the scene frame no longer works with the new depsgraph. */
-# if 0
/* set scene frame to match previous frame + subframe
* or use current frame for last sample */
if (subframe < subframes) {
@@ -2557,7 +2551,6 @@ static void update_flowsfluids(
scene->r.cfra = scene_frame;
scene->r.subframe = 0.0f;
}
-# endif
if (sfs->source == MOD_SMOKE_FLOW_SOURCE_PARTICLES) {
/* emit_from_particles() updates timestep internally */
@@ -2569,8 +2562,13 @@ static void update_flowsfluids(
else { /* MOD_SMOKE_FLOW_SOURCE_MESH */
/* update flow object frame */
BLI_mutex_lock(&object_update_lock);
- BKE_object_modifier_update_subframe(
- depsgraph, scene, collob, true, 5, DEG_get_ctime(depsgraph), eModifierType_Smoke);
+ BKE_object_modifier_update_subframe(depsgraph,
+ scene,
+ collob,
+ true,
+ 5,
+ BKE_scene_frame_get(scene),
+ eModifierType_Smoke);
BLI_mutex_unlock(&object_update_lock);
/* apply flow */
diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c
index 471cca53900..8654c50a783 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg.c
@@ -129,6 +129,7 @@ static void subdiv_ccg_alloc_elements(SubdivCCG *subdiv_ccg, Subdiv *subdiv)
const int num_grids = topology_refiner_count_face_corners(topology_refiner);
const int grid_size = BKE_subdiv_grid_size_from_level(subdiv_ccg->level);
const int grid_area = grid_size * grid_size;
+ subdiv_ccg->grid_element_size = element_size;
subdiv_ccg->num_grids = num_grids;
subdiv_ccg->grids = MEM_calloc_arrayN(num_grids, sizeof(CCGElem *), "subdiv ccg grids");
subdiv_ccg->grids_storage = MEM_calloc_arrayN(
@@ -385,25 +386,33 @@ static void subdiv_ccg_allocate_adjacent_edges(SubdivCCG *subdiv_ccg, const int
subdiv_ccg->num_adjacent_edges, sizeof(*subdiv_ccg->adjacent_edges), "ccg adjacent edges");
}
+static SubdivCCGCoord subdiv_ccg_coord(int grid_index, int x, int y)
+{
+ SubdivCCGCoord coord = {.grid_index = grid_index, .x = x, .y = y};
+ return coord;
+}
+
+static CCGElem *subdiv_ccg_coord_to_elem(const CCGKey *key,
+ const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord)
+{
+ return CCG_grid_elem(key, subdiv_ccg->grids[coord->grid_index], coord->x, coord->y);
+}
+
/* Returns storage where boundary elements are to be stored. */
-static CCGElem **subdiv_ccg_adjacent_edge_add_face(SubdivCCG *subdiv_ccg,
- SubdivCCGAdjacentEdge *adjacent_edge,
- SubdivCCGFace *face)
+static SubdivCCGCoord *subdiv_ccg_adjacent_edge_add_face(SubdivCCG *subdiv_ccg,
+ SubdivCCGAdjacentEdge *adjacent_edge)
{
const int grid_size = subdiv_ccg->grid_size * 2;
const int adjacent_face_index = adjacent_edge->num_adjacent_faces;
++adjacent_edge->num_adjacent_faces;
- /* Store new adjacent face. */
- adjacent_edge->faces = MEM_reallocN(
- adjacent_edge->faces, adjacent_edge->num_adjacent_faces * sizeof(*adjacent_edge->faces));
- adjacent_edge->faces[adjacent_face_index] = face;
/* Allocate memory for the boundary elements. */
- adjacent_edge->boundary_elements = MEM_reallocN(adjacent_edge->boundary_elements,
- adjacent_edge->num_adjacent_faces *
- sizeof(*adjacent_edge->boundary_elements));
- adjacent_edge->boundary_elements[adjacent_face_index] = MEM_malloc_arrayN(
- grid_size * 2, sizeof(CCGElem *), "ccg adjacent boundary");
- return adjacent_edge->boundary_elements[adjacent_face_index];
+ adjacent_edge->boundary_coords = MEM_reallocN(adjacent_edge->boundary_coords,
+ adjacent_edge->num_adjacent_faces *
+ sizeof(*adjacent_edge->boundary_coords));
+ adjacent_edge->boundary_coords[adjacent_face_index] = MEM_malloc_arrayN(
+ grid_size * 2, sizeof(SubdivCCGCoord), "ccg adjacent boundary");
+ return adjacent_edge->boundary_coords[adjacent_face_index];
}
static void subdiv_ccg_init_faces_edge_neighborhood(SubdivCCG *subdiv_ccg)
@@ -423,9 +432,6 @@ static void subdiv_ccg_init_faces_edge_neighborhood(SubdivCCG *subdiv_ccg)
StaticOrHeapIntStorage face_edges_storage;
static_or_heap_storage_init(&face_vertices_storage);
static_or_heap_storage_init(&face_edges_storage);
- /* Key to access elements. */
- CCGKey key;
- BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
/* Store adjacency for all faces. */
const int num_faces = subdiv_ccg->num_faces;
for (int face_index = 0; face_index < num_faces; face_index++) {
@@ -447,34 +453,32 @@ static void subdiv_ccg_init_faces_edge_neighborhood(SubdivCCG *subdiv_ccg)
const bool is_edge_flipped = (edge_vertices[0] != vertex_index);
/* Grid which is adjacent to the current corner. */
const int current_grid_index = face->start_grid_index + corner;
- CCGElem *current_grid = subdiv_ccg->grids[current_grid_index];
/* Grid which is adjacent to the next corner. */
const int next_grid_index = face->start_grid_index + (corner + 1) % num_face_grids;
- CCGElem *next_grid = subdiv_ccg->grids[next_grid_index];
/* Add new face to the adjacent edge. */
SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[edge_index];
- CCGElem **boundary_elements = subdiv_ccg_adjacent_edge_add_face(
- subdiv_ccg, adjacent_edge, face);
+ SubdivCCGCoord *boundary_coords = subdiv_ccg_adjacent_edge_add_face(subdiv_ccg,
+ adjacent_edge);
/* Fill CCG elements along the edge. */
int boundary_element_index = 0;
if (is_edge_flipped) {
for (int i = 0; i < grid_size; i++) {
- boundary_elements[boundary_element_index++] = CCG_grid_elem(
- &key, next_grid, grid_size - i - 1, grid_size - 1);
+ boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
+ next_grid_index, grid_size - i - 1, grid_size - 1);
}
for (int i = 0; i < grid_size; i++) {
- boundary_elements[boundary_element_index++] = CCG_grid_elem(
- &key, current_grid, grid_size - 1, i);
+ boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
+ current_grid_index, grid_size - 1, i);
}
}
else {
for (int i = 0; i < grid_size; i++) {
- boundary_elements[boundary_element_index++] = CCG_grid_elem(
- &key, current_grid, grid_size - 1, grid_size - i - 1);
+ boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
+ current_grid_index, grid_size - 1, grid_size - i - 1);
}
for (int i = 0; i < grid_size; i++) {
- boundary_elements[boundary_element_index++] = CCG_grid_elem(
- &key, next_grid, i, grid_size - 1);
+ boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
+ next_grid_index, i, grid_size - 1);
}
}
}
@@ -494,21 +498,16 @@ static void subdiv_ccg_allocate_adjacent_vertices(SubdivCCG *subdiv_ccg, const i
/* Returns storage where corner elements are to be stored. This is a pointer
* to the actual storage. */
-static CCGElem **subdiv_ccg_adjacent_vertex_add_face(SubdivCCGAdjacentVertex *adjacent_vertex,
- SubdivCCGFace *face)
+static SubdivCCGCoord *subdiv_ccg_adjacent_vertex_add_face(
+ SubdivCCGAdjacentVertex *adjacent_vertex)
{
const int adjacent_face_index = adjacent_vertex->num_adjacent_faces;
++adjacent_vertex->num_adjacent_faces;
- /* Store new adjacent face. */
- adjacent_vertex->faces = MEM_reallocN(adjacent_vertex->faces,
- adjacent_vertex->num_adjacent_faces *
- sizeof(*adjacent_vertex->faces));
- adjacent_vertex->faces[adjacent_face_index] = face;
/* Allocate memory for the boundary elements. */
- adjacent_vertex->corner_elements = MEM_reallocN(adjacent_vertex->corner_elements,
- adjacent_vertex->num_adjacent_faces *
- sizeof(*adjacent_vertex->corner_elements));
- return &adjacent_vertex->corner_elements[adjacent_face_index];
+ adjacent_vertex->corner_coords = MEM_reallocN(adjacent_vertex->corner_coords,
+ adjacent_vertex->num_adjacent_faces *
+ sizeof(*adjacent_vertex->corner_coords));
+ return &adjacent_vertex->corner_coords[adjacent_face_index];
}
static void subdiv_ccg_init_faces_vertex_neighborhood(SubdivCCG *subdiv_ccg)
@@ -541,11 +540,10 @@ static void subdiv_ccg_init_faces_vertex_neighborhood(SubdivCCG *subdiv_ccg)
const int vertex_index = face_vertices[corner];
/* Grid which is adjacent to the current corner. */
const int grid_index = face->start_grid_index + corner;
- CCGElem *grid = subdiv_ccg->grids[grid_index];
/* Add new face to the adjacent edge. */
SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[vertex_index];
- CCGElem **corner_element = subdiv_ccg_adjacent_vertex_add_face(adjacent_vertex, face);
- *corner_element = CCG_grid_elem(&key, grid, grid_size - 1, grid_size - 1);
+ SubdivCCGCoord *corner_coord = subdiv_ccg_adjacent_vertex_add_face(adjacent_vertex);
+ *corner_coord = subdiv_ccg_coord(grid_index, grid_size - 1, grid_size - 1);
}
}
/* Free possibly heap-allocated storage. */
@@ -593,7 +591,7 @@ Mesh *BKE_subdiv_to_ccg_mesh(Subdiv *subdiv,
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_CCG);
if (!BKE_subdiv_eval_update_from_mesh(subdiv, coarse_mesh, NULL)) {
if (coarse_mesh->totpoly) {
- return false;
+ return NULL;
}
}
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_CCG);
@@ -638,17 +636,15 @@ void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg)
for (int i = 0; i < subdiv_ccg->num_adjacent_edges; i++) {
SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[i];
for (int face_index = 0; face_index < adjacent_edge->num_adjacent_faces; face_index++) {
- MEM_SAFE_FREE(adjacent_edge->boundary_elements[face_index]);
+ MEM_SAFE_FREE(adjacent_edge->boundary_coords[face_index]);
}
- MEM_SAFE_FREE(adjacent_edge->faces);
- MEM_SAFE_FREE(adjacent_edge->boundary_elements);
+ MEM_SAFE_FREE(adjacent_edge->boundary_coords);
}
MEM_SAFE_FREE(subdiv_ccg->adjacent_edges);
/* Free map of adjacent vertices. */
for (int i = 0; i < subdiv_ccg->num_adjacent_vertices; i++) {
SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[i];
- MEM_SAFE_FREE(adjacent_vertex->faces);
- MEM_SAFE_FREE(adjacent_vertex->corner_elements);
+ MEM_SAFE_FREE(adjacent_vertex->corner_coords);
}
MEM_SAFE_FREE(subdiv_ccg->adjacent_vertices);
MEM_freeN(subdiv_ccg);
@@ -1051,7 +1047,8 @@ static void subdiv_ccg_average_grids_boundary(SubdivCCG *subdiv_ccg,
}
for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
for (int i = 1; i < grid_size2 - 1; i++) {
- CCGElem *grid_element = adjacent_edge->boundary_elements[face_index][i];
+ CCGElem *grid_element = subdiv_ccg_coord_to_elem(
+ key, subdiv_ccg, &adjacent_edge->boundary_coords[face_index][i]);
element_accumulator_add(&tls->accumulators[i], subdiv_ccg, key, grid_element);
}
}
@@ -1061,7 +1058,8 @@ static void subdiv_ccg_average_grids_boundary(SubdivCCG *subdiv_ccg,
/* Copy averaged value to all the other faces. */
for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
for (int i = 1; i < grid_size2 - 1; i++) {
- CCGElem *grid_element = adjacent_edge->boundary_elements[face_index][i];
+ CCGElem *grid_element = subdiv_ccg_coord_to_elem(
+ key, subdiv_ccg, &adjacent_edge->boundary_coords[face_index][i]);
element_accumulator_copy(subdiv_ccg, key, grid_element, &tls->accumulators[i]);
}
}
@@ -1103,13 +1101,15 @@ static void subdiv_ccg_average_grids_corners(SubdivCCG *subdiv_ccg,
GridElementAccumulator accumulator;
element_accumulator_init(&accumulator);
for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
- CCGElem *grid_element = adjacent_vertex->corner_elements[face_index];
+ CCGElem *grid_element = subdiv_ccg_coord_to_elem(
+ key, subdiv_ccg, &adjacent_vertex->corner_coords[face_index]);
element_accumulator_add(&accumulator, subdiv_ccg, key, grid_element);
}
element_accumulator_mul_fl(&accumulator, 1.0f / (float)num_adjacent_faces);
/* Copy averaged value to all the other faces. */
for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
- CCGElem *grid_element = adjacent_vertex->corner_elements[face_index];
+ CCGElem *grid_element = subdiv_ccg_coord_to_elem(
+ key, subdiv_ccg, &adjacent_vertex->corner_coords[face_index]);
element_accumulator_copy(subdiv_ccg, key, grid_element, &accumulator);
}
}
@@ -1243,3 +1243,540 @@ void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg,
*r_num_faces = num_grids * (grid_size - 1) * (grid_size - 1);
*r_num_loops = *r_num_faces * 4;
}
+
+/* =============================================================================
+ * Neighbors.
+ */
+
+void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord *coord)
+{
+ printf("%s: grid index: %d, coord: (%d, %d)\n", message, coord->grid_index, coord->x, coord->y);
+}
+
+bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
+{
+ if (coord->grid_index < 0 || coord->grid_index >= subdiv_ccg->num_grids) {
+ return false;
+ }
+ const int grid_size = subdiv_ccg->grid_size;
+ if (coord->x < 0 || coord->x >= grid_size) {
+ return false;
+ }
+ if (coord->y < 0 || coord->y >= grid_size) {
+ return false;
+ }
+ return true;
+}
+
+BLI_INLINE void subdiv_ccg_neighbors_init(SubdivCCGNeighbors *neighbors,
+ const int num_unique,
+ const int num_duplicates)
+{
+ const int size = num_unique + num_duplicates;
+ neighbors->size = size;
+ neighbors->num_duplicates = num_duplicates;
+ if (size < ARRAY_SIZE(neighbors->coords_fixed)) {
+ neighbors->coords = neighbors->coords_fixed;
+ }
+ else {
+ neighbors->coords = MEM_mallocN(sizeof(*neighbors->coords) * size,
+ "SubdivCCGNeighbors.coords");
+ }
+}
+
+/* Check whether given coordinate belongs to a grid corner. */
+BLI_INLINE bool is_corner_grid_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
+{
+ const int grid_size_1 = subdiv_ccg->grid_size - 1;
+ return (coord->x == 0 && coord->y == 0) || (coord->x == 0 && coord->y == grid_size_1) ||
+ (coord->x == grid_size_1 && coord->y == grid_size_1) ||
+ (coord->x == grid_size_1 && coord->y == 0);
+}
+
+/* Check whether given coordinate belongs to a grid boundary. */
+BLI_INLINE bool is_boundary_grid_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
+{
+ const int grid_size_1 = subdiv_ccg->grid_size - 1;
+ return coord->x == 0 || coord->y == 0 || coord->x == grid_size_1 || coord->y == grid_size_1;
+}
+
+/* Check whether coordinate is at the boundary between two grids of the same face. */
+BLI_INLINE bool is_inner_edge_grid_coordinate(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord)
+{
+ const int grid_size_1 = subdiv_ccg->grid_size - 1;
+ if (coord->x == 0) {
+ return coord->y > 0 && coord->y < grid_size_1;
+ }
+ if (coord->y == 0) {
+ return coord->x > 0 && coord->x < grid_size_1;
+ }
+ return false;
+}
+
+BLI_INLINE SubdivCCGCoord coord_at_prev_row(const SubdivCCG *UNUSED(subdiv_ccg),
+ const SubdivCCGCoord *coord)
+{
+ BLI_assert(coord->y > 0);
+ SubdivCCGCoord result = *coord;
+ result.y -= 1;
+ return result;
+}
+BLI_INLINE SubdivCCGCoord coord_at_next_row(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord)
+{
+ UNUSED_VARS_NDEBUG(subdiv_ccg);
+ BLI_assert(coord->y < subdiv_ccg->grid_size - 1);
+ SubdivCCGCoord result = *coord;
+ result.y += 1;
+ return result;
+}
+
+BLI_INLINE SubdivCCGCoord coord_at_prev_col(const SubdivCCG *UNUSED(subdiv_ccg),
+ const SubdivCCGCoord *coord)
+{
+ BLI_assert(coord->x > 0);
+ SubdivCCGCoord result = *coord;
+ result.x -= 1;
+ return result;
+}
+BLI_INLINE SubdivCCGCoord coord_at_next_col(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord)
+{
+ UNUSED_VARS_NDEBUG(subdiv_ccg);
+ BLI_assert(coord->x < subdiv_ccg->grid_size - 1);
+ SubdivCCGCoord result = *coord;
+ result.x += 1;
+ return result;
+}
+
+/* For the input coordinate which is at the boundary of the grid do one step inside. */
+static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord)
+
+{
+ SubdivCCGCoord result = *coord;
+ const int grid_size_1 = subdiv_ccg->grid_size - 1;
+ if (result.x == grid_size_1) {
+ --result.x;
+ }
+ else if (result.y == grid_size_1) {
+ --result.y;
+ }
+ else if (result.x == 0) {
+ ++result.x;
+ }
+ else if (result.y == 0) {
+ ++result.y;
+ }
+ else {
+ BLI_assert(!"non-boundary element given");
+ }
+ return result;
+}
+
+BLI_INLINE
+int next_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
+{
+ SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
+ const int face_grid_index = coord->grid_index;
+ int next_face_grid_index = face_grid_index + 1 - face->start_grid_index;
+ if (next_face_grid_index == face->num_grids) {
+ next_face_grid_index = 0;
+ }
+ return face->start_grid_index + next_face_grid_index;
+}
+BLI_INLINE int prev_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
+{
+ SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
+ const int face_grid_index = coord->grid_index;
+ int prev_face_grid_index = face_grid_index - 1 - face->start_grid_index;
+ if (prev_face_grid_index < 0) {
+ prev_face_grid_index = face->num_grids - 1;
+ }
+ return face->start_grid_index + prev_face_grid_index;
+}
+
+/* Simple case of getting neighbors of a corner coordinate: the corner is a face center, so
+ * can only iterate over grid of a single face, without looking into adjacency. */
+static void neighbor_coords_corner_center_get(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ const bool include_duplicates,
+ SubdivCCGNeighbors *r_neighbors)
+{
+ SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
+ const int num_adjacent_grids = face->num_grids;
+
+ subdiv_ccg_neighbors_init(
+ r_neighbors, num_adjacent_grids, (include_duplicates) ? num_adjacent_grids - 1 : 0);
+
+ int duplicate_face_grid_index = num_adjacent_grids;
+ for (int face_grid_index = 0; face_grid_index < num_adjacent_grids; ++face_grid_index) {
+ SubdivCCGCoord neighbor_coord;
+ neighbor_coord.grid_index = face->start_grid_index + face_grid_index;
+ neighbor_coord.x = 1;
+ neighbor_coord.y = 0;
+ r_neighbors->coords[face_grid_index] = neighbor_coord;
+
+ if (include_duplicates && neighbor_coord.grid_index != coord->grid_index) {
+ neighbor_coord.x = 0;
+ r_neighbors->coords[duplicate_face_grid_index++] = neighbor_coord;
+ }
+ }
+}
+
+/* Get index within adjacent_vertices array for the given CCG coordinate. */
+static int adjacent_vertex_index_from_coord(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord)
+{
+ Subdiv *subdiv = subdiv_ccg->subdiv;
+ OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
+
+ const SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
+ const int face_index = face - subdiv_ccg->faces;
+ const int face_grid_index = coord->grid_index - face->start_grid_index;
+ const int num_face_grids = face->num_grids;
+ const int num_face_vertices = num_face_grids;
+
+ StaticOrHeapIntStorage face_vertices_storage;
+ static_or_heap_storage_init(&face_vertices_storage);
+
+ int *face_vertices = static_or_heap_storage_get(&face_vertices_storage, num_face_vertices);
+ topology_refiner->getFaceVertices(topology_refiner, face_index, face_vertices);
+
+ const int adjacent_vertex_index = face_vertices[face_grid_index];
+ static_or_heap_storage_free(&face_vertices_storage);
+ return adjacent_vertex_index;
+}
+
+/* The corner is adjacent to a coarse vertex. */
+static void neighbor_coords_corner_vertex_get(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ const bool include_duplicates,
+ SubdivCCGNeighbors *r_neighbors)
+{
+ Subdiv *subdiv = subdiv_ccg->subdiv;
+ OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
+
+ const int adjacent_vertex_index = adjacent_vertex_index_from_coord(subdiv_ccg, coord);
+ BLI_assert(adjacent_vertex_index >= 0);
+ BLI_assert(adjacent_vertex_index < subdiv_ccg->num_adjacent_vertices);
+ const int num_vertex_edges = topology_refiner->getNumVertexEdges(topology_refiner,
+ adjacent_vertex_index);
+
+ SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[adjacent_vertex_index];
+ const int num_adjacent_faces = adjacent_vertex->num_adjacent_faces;
+
+ subdiv_ccg_neighbors_init(
+ r_neighbors, num_vertex_edges, (include_duplicates) ? num_adjacent_faces - 1 : 0);
+
+ StaticOrHeapIntStorage vertex_edges_storage;
+ static_or_heap_storage_init(&vertex_edges_storage);
+
+ int *vertex_edges = static_or_heap_storage_get(&vertex_edges_storage, num_vertex_edges);
+ topology_refiner->getVertexEdges(topology_refiner, adjacent_vertex_index, vertex_edges);
+
+ for (int i = 0; i < num_vertex_edges; ++i) {
+ const int edge_index = vertex_edges[i];
+
+ /* Use very first grid of every edge. */
+ const int edge_face_index = 0;
+
+ /* Depending edge orientation we use first (zero-based) or previous-to-last point. */
+ int edge_vertices_indices[2];
+ topology_refiner->getEdgeVertices(topology_refiner, edge_index, edge_vertices_indices);
+ int edge_point_index, duplicate_edge_point_index;
+ if (edge_vertices_indices[0] == adjacent_vertex_index) {
+ duplicate_edge_point_index = 0;
+ edge_point_index = duplicate_edge_point_index + 1;
+ }
+ else {
+ /* Edge "consists" of 2 grids, which makes it 2 * grid_size elements per edge.
+ * The index of last edge element is 2 * grid_size - 1 (due to zero-based indices),
+ * and we are interested in previous to last element. */
+ duplicate_edge_point_index = subdiv_ccg->grid_size * 2 - 1;
+ edge_point_index = duplicate_edge_point_index - 1;
+ }
+
+ SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[edge_index];
+ r_neighbors->coords[i] = adjacent_edge->boundary_coords[edge_face_index][edge_point_index];
+ }
+
+ if (include_duplicates) {
+ /* Add duplicates of the current grid vertex in adjacent faces if requested. */
+ for (int i = 0, duplicate_i = num_vertex_edges; i < num_adjacent_faces; i++) {
+ SubdivCCGCoord neighbor_coord = adjacent_vertex->corner_coords[i];
+ if (neighbor_coord.grid_index != coord->grid_index) {
+ r_neighbors->coords[duplicate_i++] = neighbor_coord;
+ }
+ }
+ }
+
+ static_or_heap_storage_free(&vertex_edges_storage);
+}
+
+static int adjacent_edge_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
+{
+ Subdiv *subdiv = subdiv_ccg->subdiv;
+ OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
+ SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
+
+ const int face_grid_index = coord->grid_index - face->start_grid_index;
+ const int face_index = face - subdiv_ccg->faces;
+ const int num_face_edges = topology_refiner->getNumFaceEdges(topology_refiner, face_index);
+
+ StaticOrHeapIntStorage face_edges_storage;
+ static_or_heap_storage_init(&face_edges_storage);
+ int *face_edges_indices = static_or_heap_storage_get(&face_edges_storage, num_face_edges);
+ topology_refiner->getFaceEdges(topology_refiner, face_index, face_edges_indices);
+
+ const int grid_size_1 = subdiv_ccg->grid_size - 1;
+ int adjacent_edge_index = -1;
+ if (coord->x == grid_size_1) {
+ adjacent_edge_index = face_edges_indices[face_grid_index];
+ }
+ else {
+ BLI_assert(coord->y == grid_size_1);
+ adjacent_edge_index =
+ face_edges_indices[face_grid_index == 0 ? face->num_grids - 1 : face_grid_index - 1];
+ }
+
+ static_or_heap_storage_free(&face_edges_storage);
+
+ return adjacent_edge_index;
+}
+
+static int adjacent_edge_point_index_from_coord(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ const int adjacent_edge_index)
+{
+ Subdiv *subdiv = subdiv_ccg->subdiv;
+ OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
+
+ const int adjacent_vertex_index = adjacent_vertex_index_from_coord(subdiv_ccg, coord);
+ int edge_vertices_indices[2];
+ topology_refiner->getEdgeVertices(topology_refiner, adjacent_edge_index, edge_vertices_indices);
+
+ /* Vertex index of an edge which is used to see whether edge points in the right direction.
+ * Tricky part here is that depending whether input coordinate is are maximum X or Y coordinate
+ * of the grid we need to use different edge direction.
+ * Basically, the edge adjacent to a previous loop needs to point opposite direction. */
+ int directional_edge_vertex_index = -1;
+
+ const int grid_size_1 = subdiv_ccg->grid_size - 1;
+ int adjacent_edge_point_index = -1;
+ if (coord->x == grid_size_1) {
+ adjacent_edge_point_index = subdiv_ccg->grid_size - coord->y - 1;
+ directional_edge_vertex_index = edge_vertices_indices[0];
+ }
+ else {
+ BLI_assert(coord->y == grid_size_1);
+ adjacent_edge_point_index = subdiv_ccg->grid_size + coord->x;
+ directional_edge_vertex_index = edge_vertices_indices[1];
+ }
+
+ /* Flip the index if the edde points opposite direction. */
+ if (adjacent_vertex_index != directional_edge_vertex_index) {
+ const int num_edge_points = subdiv_ccg->grid_size * 2;
+ adjacent_edge_point_index = num_edge_points - adjacent_edge_point_index - 1;
+ }
+
+ return adjacent_edge_point_index;
+}
+
+/* Adjacent edge has two points in the middle which corresponds to grid corners, but which are
+ * the same point in the final geometry.
+ * So need to use extra step when calculating next/previous points, so we don't go from a corner
+ * of one grid to a corner of adjacent grid. */
+static int next_adjacent_edge_point_index(const SubdivCCG *subdiv_ccg, const int point_index)
+{
+ if (point_index == subdiv_ccg->grid_size - 1) {
+ return point_index + 2;
+ }
+ return point_index + 1;
+}
+static int prev_adjacent_edge_point_index(const SubdivCCG *subdiv_ccg, const int point_index)
+{
+ if (point_index == subdiv_ccg->grid_size) {
+ return point_index - 2;
+ }
+ return point_index - 1;
+}
+
+/* Common implementation of neighbor calculation when input coordinate is at the edge between two
+ * coarse faces, but is not at the coarse vertex. */
+static void neighbor_coords_edge_get(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ const bool include_duplicates,
+ SubdivCCGNeighbors *r_neighbors)
+
+{
+ const int adjacent_edge_index = adjacent_edge_index_from_coord(subdiv_ccg, coord);
+ BLI_assert(adjacent_edge_index >= 0);
+ BLI_assert(adjacent_edge_index < subdiv_ccg->num_adjacent_edges);
+ const SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[adjacent_edge_index];
+
+ /* 2 neighbor points along the edge, plus one inner point per every adjacent grid. */
+ const int num_adjacent_faces = adjacent_edge->num_adjacent_faces;
+ subdiv_ccg_neighbors_init(
+ r_neighbors, num_adjacent_faces + 2, (include_duplicates) ? num_adjacent_faces - 1 : 0);
+
+ const int point_index = adjacent_edge_point_index_from_coord(
+ subdiv_ccg, coord, adjacent_edge_index);
+ const int next_point_index = next_adjacent_edge_point_index(subdiv_ccg, point_index);
+ const int prev_point_index = prev_adjacent_edge_point_index(subdiv_ccg, point_index);
+
+ for (int i = 0, duplicate_i = num_adjacent_faces; i < num_adjacent_faces; ++i) {
+ SubdivCCGCoord *boundary_coords = adjacent_edge->boundary_coords[i];
+ /* One step into the grid from the edge for each adjacent face. */
+ SubdivCCGCoord grid_coord = boundary_coords[point_index];
+ r_neighbors->coords[i + 2] = coord_step_inside_from_boundary(subdiv_ccg, &grid_coord);
+
+ if (grid_coord.grid_index == coord->grid_index) {
+ /* Prev and next along the edge for the current grid. */
+ r_neighbors->coords[0] = boundary_coords[prev_point_index];
+ r_neighbors->coords[1] = boundary_coords[next_point_index];
+ }
+ else if (include_duplicates) {
+ /* Same coordinate on neighboring grids if requested. */
+ r_neighbors->coords[duplicate_i + 2] = grid_coord;
+ duplicate_i++;
+ }
+ }
+}
+
+/* The corner is at the middle of edge between faces. */
+static void neighbor_coords_corner_edge_get(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ const bool include_duplicates,
+ SubdivCCGNeighbors *r_neighbors)
+{
+ neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
+}
+
+/* Input coordinate is at one of 4 corners of its grid corners. */
+static void neighbor_coords_corner_get(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ const bool include_duplicates,
+ SubdivCCGNeighbors *r_neighbors)
+{
+ if (coord->x == 0 && coord->y == 0) {
+ neighbor_coords_corner_center_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
+ }
+ else {
+ const int grid_size_1 = subdiv_ccg->grid_size - 1;
+ if (coord->x == grid_size_1 && coord->y == grid_size_1) {
+ neighbor_coords_corner_vertex_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
+ }
+ else {
+ neighbor_coords_corner_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
+ }
+ }
+}
+
+/* Simple case of getting neighbors of a boundary coordinate: the input coordinate is at the
+ * boundary between two grids of the same face and there is no need to check adjacency with
+ * other faces. */
+static void neighbor_coords_boundary_inner_get(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ const bool include_duplicates,
+ SubdivCCGNeighbors *r_neighbors)
+{
+ subdiv_ccg_neighbors_init(r_neighbors, 4, (include_duplicates) ? 1 : 0);
+
+ if (coord->x == 0) {
+ r_neighbors->coords[0] = coord_at_prev_row(subdiv_ccg, coord);
+ r_neighbors->coords[1] = coord_at_next_row(subdiv_ccg, coord);
+ r_neighbors->coords[2] = coord_at_next_col(subdiv_ccg, coord);
+
+ r_neighbors->coords[3].grid_index = prev_grid_index_from_coord(subdiv_ccg, coord);
+ r_neighbors->coords[3].x = coord->y;
+ r_neighbors->coords[3].y = 1;
+
+ if (include_duplicates) {
+ r_neighbors->coords[4] = r_neighbors->coords[3];
+ r_neighbors->coords[4].y = 0;
+ }
+ }
+ else if (coord->y == 0) {
+ r_neighbors->coords[0] = coord_at_prev_col(subdiv_ccg, coord);
+ r_neighbors->coords[1] = coord_at_next_col(subdiv_ccg, coord);
+ r_neighbors->coords[2] = coord_at_next_row(subdiv_ccg, coord);
+
+ r_neighbors->coords[3].grid_index = next_grid_index_from_coord(subdiv_ccg, coord);
+ r_neighbors->coords[3].x = 1;
+ r_neighbors->coords[3].y = coord->x;
+
+ if (include_duplicates) {
+ r_neighbors->coords[4] = r_neighbors->coords[3];
+ r_neighbors->coords[4].x = 0;
+ }
+ }
+}
+
+/* Input coordinate is on an edge between two faces. Need to check adjacency. */
+static void neighbor_coords_boundary_outer_get(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ const bool include_duplicates,
+ SubdivCCGNeighbors *r_neighbors)
+{
+ neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
+}
+
+/* Input coordinate is at one of 4 boundaries of its grid.
+ * It could either be an inner boundary (which connects face center to the face edge) or could be
+ * a part of coarse face edge. */
+static void neighbor_coords_boundary_get(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ const bool include_duplicates,
+ SubdivCCGNeighbors *r_neighbors)
+{
+ if (is_inner_edge_grid_coordinate(subdiv_ccg, coord)) {
+ neighbor_coords_boundary_inner_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
+ }
+ else {
+ neighbor_coords_boundary_outer_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
+ }
+}
+
+/* Input coordinate is inside of its grid, all the neighbors belong to the same grid. */
+static void neighbor_coords_inner_get(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ SubdivCCGNeighbors *r_neighbors)
+{
+ subdiv_ccg_neighbors_init(r_neighbors, 4, 0);
+
+ r_neighbors->coords[0] = coord_at_prev_row(subdiv_ccg, coord);
+ r_neighbors->coords[1] = coord_at_next_row(subdiv_ccg, coord);
+ r_neighbors->coords[2] = coord_at_prev_col(subdiv_ccg, coord);
+ r_neighbors->coords[3] = coord_at_next_col(subdiv_ccg, coord);
+}
+
+void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ const bool include_duplicates,
+ SubdivCCGNeighbors *r_neighbors)
+{
+ BLI_assert(coord->grid_index >= 0);
+ BLI_assert(coord->grid_index < subdiv_ccg->num_grids);
+ BLI_assert(coord->x >= 0);
+ BLI_assert(coord->x < subdiv_ccg->grid_size);
+ BLI_assert(coord->y >= 0);
+ BLI_assert(coord->y < subdiv_ccg->grid_size);
+
+ if (is_corner_grid_coord(subdiv_ccg, coord)) {
+ neighbor_coords_corner_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
+ }
+ else if (is_boundary_grid_coord(subdiv_ccg, coord)) {
+ neighbor_coords_boundary_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
+ }
+ else {
+ neighbor_coords_inner_get(subdiv_ccg, coord, r_neighbors);
+ }
+
+#ifndef NDEBUG
+ for (int i = 0; i < r_neighbors->size; i++) {
+ BLI_assert(BKE_subdiv_ccg_check_coord_valid(subdiv_ccg, &r_neighbors->coords[i]));
+ }
+#endif
+}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 83be64e84c9..5c050dde990 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -312,7 +312,7 @@ bool BKE_text_reload(Text *text)
}
BLI_strncpy(filepath_abs, text->name, FILE_MAX);
- BLI_path_abs(filepath_abs, BKE_main_blendfile_path_from_global());
+ BLI_path_abs(filepath_abs, ID_BLEND_PATH_FROM_GLOBAL(&text->id));
buffer = BLI_file_read_text_as_mem(filepath_abs, 0, &buffer_len);
if (buffer == NULL) {
@@ -352,7 +352,7 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const
buffer = BLI_file_read_text_as_mem(filepath_abs, 0, &buffer_len);
if (buffer == NULL) {
- return false;
+ return NULL;
}
ta = BKE_libblock_alloc(bmain, ID_TXT, BLI_path_basename(filepath_abs), 0);
@@ -477,7 +477,7 @@ int BKE_text_file_modified_check(Text *text)
}
BLI_strncpy(file, text->name, FILE_MAX);
- BLI_path_abs(file, BKE_main_blendfile_path_from_global());
+ BLI_path_abs(file, ID_BLEND_PATH_FROM_GLOBAL(&text->id));
if (!BLI_exists(file)) {
return 2;
@@ -511,7 +511,7 @@ void BKE_text_file_modified_ignore(Text *text)
}
BLI_strncpy(file, text->name, FILE_MAX);
- BLI_path_abs(file, BKE_main_blendfile_path_from_global());
+ BLI_path_abs(file, ID_BLEND_PATH_FROM_GLOBAL(&text->id));
if (!BLI_exists(file)) {
return;
@@ -1218,6 +1218,58 @@ void txt_sel_line(Text *text)
text->selc = text->sell->len;
}
+void txt_sel_set(Text *text, int startl, int startc, int endl, int endc)
+{
+ TextLine *froml, *tol;
+ int fromllen, tollen;
+
+ /* Support negative indices. */
+ if (startl < 0 || endl < 0) {
+ int end = BLI_listbase_count(&text->lines) - 1;
+ if (startl < 0) {
+ startl = end + startl + 1;
+ }
+ if (endl < 0) {
+ endl = end + endl + 1;
+ }
+ }
+ CLAMP_MIN(startl, 0);
+ CLAMP_MIN(endl, 0);
+
+ froml = BLI_findlink(&text->lines, startl);
+ if (froml == NULL) {
+ froml = text->lines.last;
+ }
+ if (startl == endl) {
+ tol = froml;
+ }
+ else {
+ tol = BLI_findlink(&text->lines, endl);
+ if (tol == NULL) {
+ tol = text->lines.last;
+ }
+ }
+
+ fromllen = BLI_strlen_utf8(froml->line);
+ tollen = BLI_strlen_utf8(tol->line);
+
+ /* Support negative indices. */
+ if (startc < 0) {
+ startc = fromllen + startc + 1;
+ }
+ if (endc < 0) {
+ endc = tollen + endc + 1;
+ }
+
+ CLAMP(startc, 0, fromllen);
+ CLAMP(endc, 0, tollen);
+
+ text->curl = froml;
+ text->curc = BLI_str_utf8_offset_from_index(froml->line, startc);
+ text->sell = tol;
+ text->selc = BLI_str_utf8_offset_from_index(tol->line, endc);
+}
+
/* -------------------------------------------------------------------- */
/** \name Buffer Conversion for Undo/Redo
*
diff --git a/source/blender/blenlib/BLI_compiler_compat.h b/source/blender/blenlib/BLI_compiler_compat.h
index bd1cd327d3c..312991e7f15 100644
--- a/source/blender/blenlib/BLI_compiler_compat.h
+++ b/source/blender/blenlib/BLI_compiler_compat.h
@@ -15,7 +15,7 @@
*/
#ifndef __BLI_COMPILER_COMPAT_H__
-# define __BLI_COMPILER_COMPAT_H__
+#define __BLI_COMPILER_COMPAT_H__
/** \file
* \ingroup bli
@@ -23,32 +23,32 @@
* Use to help with cross platform portability.
*/
-# if defined(_MSC_VER)
-# define alloca _alloca
-# endif
+#if defined(_MSC_VER)
+# define alloca _alloca
+#endif
-# if (defined(__GNUC__) || defined(__clang__)) && defined(__cplusplus)
+#if (defined(__GNUC__) || defined(__clang__)) && defined(__cplusplus)
extern "C++" {
/* Some magic to be sure we don't have reference in the type. */
template<typename T> static inline T decltype_helper(T x)
{
return x;
}
-# define typeof(x) decltype(decltype_helper(x))
+# define typeof(x) decltype(decltype_helper(x))
}
-# endif
+#endif
/* little macro so inline keyword works */
-# if defined(_MSC_VER)
-# define BLI_INLINE static __forceinline
-# else
-# define BLI_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__))
-# endif
+#if defined(_MSC_VER)
+# define BLI_INLINE static __forceinline
+#else
+# define BLI_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__))
+#endif
-# if defined(__GNUC__)
-# define BLI_NOINLINE __attribute__((noinline))
-# else
-# define BLI_NOINLINE
-# endif
+#if defined(__GNUC__)
+# define BLI_NOINLINE __attribute__((noinline))
+#else
+# define BLI_NOINLINE
+#endif
#endif /* __BLI_COMPILER_COMPAT_H__ */
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index d78f167a8fd..bdf7588291f 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -50,6 +50,7 @@ int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BLI_copy(const char *path, const char *to) ATTR_NONNULL();
int BLI_rename(const char *from, const char *to) ATTR_NONNULL();
int BLI_delete(const char *path, bool dir, bool recursive) ATTR_NONNULL();
+int BLI_delete_soft(const char *path, const char **error_message) ATTR_NONNULL();
#if 0 /* Unused */
int BLI_move(const char *path, const char *to) ATTR_NONNULL();
int BLI_create_symlink(const char *path, const char *to) ATTR_NONNULL();
diff --git a/source/blender/blenlib/BLI_gsqueue.h b/source/blender/blenlib/BLI_gsqueue.h
index 4bd53dfddbe..b8a87e9d9fa 100644
--- a/source/blender/blenlib/BLI_gsqueue.h
+++ b/source/blender/blenlib/BLI_gsqueue.h
@@ -26,7 +26,7 @@
typedef struct _GSQueue GSQueue;
-GSQueue *BLI_gsqueue_new(size_t elem_size);
+GSQueue *BLI_gsqueue_new(const size_t elem_size);
bool BLI_gsqueue_is_empty(const GSQueue *gq);
size_t BLI_gsqueue_len(const GSQueue *gq);
void BLI_gsqueue_pop(GSQueue *gq, void *r_item);
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 87517ebe060..eec5d214473 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -97,10 +97,10 @@ bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3],
bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
bool is_poly_convex_v2(const float verts[][2], unsigned int nr);
int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
-bool is_quad_flip_v3_first_third_fast(const float v0[3],
- const float v1[3],
+bool is_quad_flip_v3_first_third_fast(const float v1[3],
const float v2[3],
- const float v3[3]);
+ const float v3[3],
+ const float v4[3]);
/********************************* Distance **********************************/
diff --git a/source/blender/blenlib/intern/BLI_temporary_allocator.cc b/source/blender/blenlib/intern/BLI_temporary_allocator.cc
index e41cf36f66d..b145e65530d 100644
--- a/source/blender/blenlib/intern/BLI_temporary_allocator.cc
+++ b/source/blender/blenlib/intern/BLI_temporary_allocator.cc
@@ -73,7 +73,7 @@ struct ThreadLocalBuffers {
}
};
-thread_local ThreadLocalBuffers local_storage;
+static thread_local ThreadLocalBuffers local_storage;
void *BLI_temporary_allocate(uint size)
{
diff --git a/source/blender/blenlib/intern/BLI_timer.c b/source/blender/blenlib/intern/BLI_timer.c
index 0443dea9a2e..af987587d90 100644
--- a/source/blender/blenlib/intern/BLI_timer.c
+++ b/source/blender/blenlib/intern/BLI_timer.c
@@ -42,7 +42,6 @@ typedef struct TimedFunction {
typedef struct TimerContainer {
ListBase funcs;
- bool file_load_cb_registered;
} TimerContainer;
static TimerContainer GlobalTimer = {{0}};
diff --git a/source/blender/blenlib/intern/delaunay_2d.c b/source/blender/blenlib/intern/delaunay_2d.c
index d5dcd40346f..af4fa9fa54e 100644
--- a/source/blender/blenlib/intern/delaunay_2d.c
+++ b/source/blender/blenlib/intern/delaunay_2d.c
@@ -325,6 +325,18 @@ static bool exists_edge(const CDTVert *a, const CDTVert *b)
return false;
}
+/** Is the vertex v incident on face f? */
+static bool vert_touches_face(const CDTVert *v, const CDTFace *f)
+{
+ SymEdge *se = v->symedge;
+ do {
+ if (se->face == f) {
+ return true;
+ }
+ } while ((se = se->rot) != v->symedge);
+ return false;
+}
+
/**
* Assume s1 and s2 are both SymEdges in a face with > 3 sides,
* and one is not the next of the other.
@@ -1901,35 +1913,108 @@ static void dissolve_symedge(CDT_state *cdt, SymEdge *se)
delete_edge(cdt, se);
}
-static void remove_non_constraint_edges(CDT_state *cdt, const bool valid_bmesh)
+/* Remove all non-constraint edges. */
+static void remove_non_constraint_edges(CDT_state *cdt)
+{
+ LinkNode *ln;
+ CDTEdge *e;
+ SymEdge *se;
+
+ for (ln = cdt->edges; ln; ln = ln->next) {
+ e = (CDTEdge *)ln->link;
+ se = &e->symedges[0];
+ if (!is_deleted_edge(e) && !is_constrained_edge(e)) {
+ dissolve_symedge(cdt, se);
+ }
+ }
+}
+
+/*
+ * Remove the non-constraint edges, but leave enough of them so that all of the
+ * faces that would be bmesh faces (that is, the faces that have some input representative)
+ * are valid: they can't have holes, they can't have repeated vertices, and they can't have
+ * repeated edges.
+ *
+ * Not essential, but to make the result look more aesthetically nice,
+ * remove the edges in order of decreasing length, so that it is more likely that the
+ * final remaining support edges are short, and therefore likely to make a fairly
+ * direct path from an outer face to an inner hole face.
+ */
+
+/* For sorting edges by decreasing length (squared). */
+struct EdgeToSort {
+ double len_squared;
+ CDTEdge *e;
+};
+
+static int edge_to_sort_cmp(const void *a, const void *b)
+{
+ const struct EdgeToSort *e1 = a;
+ const struct EdgeToSort *e2 = b;
+
+ if (e1->len_squared > e2->len_squared) {
+ return -1;
+ }
+ else if (e1->len_squared < e2->len_squared) {
+ return 1;
+ }
+ return 0;
+}
+
+static void remove_non_constraint_edges_leave_valid_bmesh(CDT_state *cdt)
{
LinkNode *ln;
CDTEdge *e;
SymEdge *se, *se2;
CDTFace *fleft, *fright;
bool dissolve;
+ size_t nedges;
+ int i, ndissolvable;
+ const double *co1, *co2;
+ struct EdgeToSort *sorted_edges;
+ nedges = 0;
+ for (ln = cdt->edges; ln; ln = ln->next) {
+ nedges++;
+ }
+ if (nedges == 0) {
+ return;
+ }
+ sorted_edges = BLI_memarena_alloc(cdt->arena, nedges * sizeof(*sorted_edges));
+ i = 0;
for (ln = cdt->edges; ln; ln = ln->next) {
e = (CDTEdge *)ln->link;
- dissolve = !is_deleted_edge(e) && !is_constrained_edge(e);
- if (dissolve) {
- se = &e->symedges[0];
- if (valid_bmesh && !edge_touches_frame(e)) {
- fleft = se->face;
- fright = sym(se)->face;
- if (fleft != cdt->outer_face && fright != cdt->outer_face &&
- (fleft->input_ids != NULL || fright->input_ids != NULL)) {
- /* Is there another symedge with same left and right faces? */
- for (se2 = se->next; dissolve && se2 != se; se2 = se2->next) {
- if (sym(se2)->face == fright) {
- dissolve = false;
- }
+ if (!is_deleted_edge(e) && !is_constrained_edge(e)) {
+ sorted_edges[i].e = e;
+ co1 = e->symedges[0].vert->co;
+ co2 = e->symedges[1].vert->co;
+ sorted_edges[i].len_squared = len_squared_v2v2_db(co1, co2);
+ i++;
+ }
+ }
+ ndissolvable = i;
+ qsort(sorted_edges, ndissolvable, sizeof(*sorted_edges), edge_to_sort_cmp);
+ for (i = 0; i < ndissolvable; i++) {
+ e = sorted_edges[i].e;
+ se = &e->symedges[0];
+ dissolve = true;
+ if (!edge_touches_frame(e)) {
+ fleft = se->face;
+ fright = sym(se)->face;
+ if (fleft != cdt->outer_face && fright != cdt->outer_face &&
+ (fleft->input_ids != NULL || fright->input_ids != NULL)) {
+ /* Is there another symedge with same left and right faces?
+ * Or is there a vertex not part of e touching the same left and right faces? */
+ for (se2 = se->next; dissolve && se2 != se; se2 = se2->next) {
+ if (sym(se2)->face == fright ||
+ (se2->vert != se->next->vert && vert_touches_face(se2->vert, fright))) {
+ dissolve = false;
}
}
}
- if (dissolve) {
- dissolve_symedge(cdt, se);
- }
+ }
+ if (dissolve) {
+ dissolve_symedge(cdt, se);
}
}
}
@@ -2066,8 +2151,11 @@ static void prepare_cdt_for_output(CDT_state *cdt, const CDT_output_type output_
UNUSED_VARS(f);
#endif
- if (output_type == CDT_CONSTRAINTS || output_type == CDT_CONSTRAINTS_VALID_BMESH) {
- remove_non_constraint_edges(cdt, output_type == CDT_CONSTRAINTS_VALID_BMESH);
+ if (output_type == CDT_CONSTRAINTS) {
+ remove_non_constraint_edges(cdt);
+ }
+ else if (output_type == CDT_CONSTRAINTS_VALID_BMESH) {
+ remove_non_constraint_edges_leave_valid_bmesh(cdt);
}
else if (output_type == CDT_FULL || output_type == CDT_INSIDE) {
remove_outer_edges(cdt, output_type == CDT_INSIDE);
diff --git a/source/blender/blenlib/intern/expr_pylike_eval.c b/source/blender/blenlib/intern/expr_pylike_eval.c
index 14fc4c5bf26..c7631f8991e 100644
--- a/source/blender/blenlib/intern/expr_pylike_eval.c
+++ b/source/blender/blenlib/intern/expr_pylike_eval.c
@@ -504,7 +504,9 @@ static bool parse_add_func(ExprParseState *state, eOpCode code, int args, void *
if (jmp_gap >= 1 && prev_ops[-1].opcode == OPCODE_CONST) {
UnaryOpFunc func = funcptr;
- double result = func(prev_ops[-1].arg.dval);
+ /* volatile because some compilers overly aggressive optimize this call out.
+ * see D6012 for details. */
+ volatile double result = func(prev_ops[-1].arg.dval);
if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) {
prev_ops[-1].arg.dval = result;
@@ -520,7 +522,9 @@ static bool parse_add_func(ExprParseState *state, eOpCode code, int args, void *
prev_ops[-1].opcode == OPCODE_CONST) {
BinaryOpFunc func = funcptr;
- double result = func(prev_ops[-2].arg.dval, prev_ops[-1].arg.dval);
+ /* volatile because some compilers overly aggressive optimize this call out.
+ * see D6012 for details. */
+ volatile double result = func(prev_ops[-2].arg.dval, prev_ops[-1].arg.dval);
if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) {
prev_ops[-2].arg.dval = result;
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index 99149f5ea42..3a45989fb63 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -33,16 +33,24 @@
#include "zlib.h"
#ifdef WIN32
+# include <windows.h>
+# include <shellapi.h>
+# include <shobjidl.h>
# include <io.h>
# include "BLI_winstuff.h"
# include "BLI_fileops_types.h"
# include "utf_winfunc.h"
# include "utfconv.h"
#else
+# if defined(__APPLE__)
+# include <CoreFoundation/CoreFoundation.h>
+# include <objc/runtime.h>
+# include <objc/message.h>
+# endif
# include <sys/param.h>
# include <dirent.h>
# include <unistd.h>
-# include <sys/stat.h>
+# include <sys/wait.h>
#endif
#include "MEM_guardedalloc.h"
@@ -288,6 +296,64 @@ int BLI_access(const char *filename, int mode)
return uaccess(filename, mode);
}
+static bool delete_soft(const wchar_t *path_16, const char **error_message)
+{
+ /* Deletes file or directory to recycling bin. The latter moves all contained files and
+ * directories recursively to the recycling bin as well. */
+ IFileOperation *pfo;
+ IShellItem *pSI;
+
+ HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+
+ if (FAILED(hr)) {
+ *error_message = "Failed to initialize COM";
+ goto error_1;
+ }
+
+ hr = CoCreateInstance(
+ &CLSID_FileOperation, NULL, CLSCTX_ALL, &IID_IFileOperation, (void **)&pfo);
+ if (FAILED(hr)) {
+ *error_message = "Failed to create FileOperation instance";
+ goto error_2;
+ }
+
+ /* Flags for deletion:
+ * FOF_ALLOWUNDO: Enables moving file to recycling bin.
+ * FOF_SILENT: Don't show progress dialog box.
+ * FOF_WANTNUKEWARNING: Show dialog box if file can't be moved to recycling bin. */
+ hr = pfo->lpVtbl->SetOperationFlags(pfo, FOF_ALLOWUNDO | FOF_SILENT | FOF_WANTNUKEWARNING);
+
+ if (FAILED(hr)) {
+ *error_message = "Failed to set operation flags";
+ goto error_2;
+ }
+
+ hr = SHCreateItemFromParsingName(path_16, NULL, &IID_IShellItem, (void **)&pSI);
+ if (FAILED(hr)) {
+ *error_message = "Failed to parse path";
+ goto error_2;
+ }
+
+ hr = pfo->lpVtbl->DeleteItem(pfo, pSI, NULL);
+ if (FAILED(hr)) {
+ *error_message = "Failed to prepare delete operation";
+ goto error_2;
+ }
+
+ hr = pfo->lpVtbl->PerformOperations(pfo);
+
+ if (FAILED(hr)) {
+ *error_message = "Failed to delete file or directory";
+ }
+
+error_2:
+ pfo->lpVtbl->Release(pfo);
+ CoUninitialize(); /* Has to be uninitialized when CoInitializeEx returns either S_OK or S_FALSE
+ */
+error_1:
+ return FAILED(hr);
+}
+
static bool delete_unique(const char *path, const bool dir)
{
bool err;
@@ -370,6 +436,24 @@ int BLI_delete(const char *file, bool dir, bool recursive)
return err;
}
+/**
+ * Moves the files or directories to the recycling bin.
+ */
+int BLI_delete_soft(const char *file, const char **error_message)
+{
+ int err;
+
+ BLI_assert(!BLI_path_is_rel(file));
+
+ UTF16_ENCODE(file);
+
+ err = delete_soft(file_16, error_message);
+
+ UTF16_UN_ENCODE(file);
+
+ return err;
+}
+
/* Not used anywhere! */
# if 0
int BLI_move(const char *file, const char *to)
@@ -720,6 +804,100 @@ static int delete_single_file(const char *from, const char *UNUSED(to))
return RecursiveOp_Callback_OK;
}
+# ifdef __APPLE__
+static int delete_soft(const char *file, const char **error_message)
+{
+ int ret = -1;
+
+ Class NSAutoreleasePoolClass = objc_getClass("NSAutoreleasePool");
+ SEL allocSel = sel_registerName("alloc");
+ SEL initSel = sel_registerName("init");
+ id poolAlloc = ((id(*)(Class, SEL))objc_msgSend)(NSAutoreleasePoolClass, allocSel);
+ id pool = ((id(*)(id, SEL))objc_msgSend)(poolAlloc, initSel);
+
+ Class NSStringClass = objc_getClass("NSString");
+ SEL stringWithUTF8StringSel = sel_registerName("stringWithUTF8String:");
+ id pathString = ((id(*)(Class, SEL, const char *))objc_msgSend)(
+ NSStringClass, stringWithUTF8StringSel, file);
+
+ Class NSFileManagerClass = objc_getClass("NSFileManager");
+ SEL defaultManagerSel = sel_registerName("defaultManager");
+ id fileManager = ((id(*)(Class, SEL))objc_msgSend)(NSFileManagerClass, defaultManagerSel);
+
+ Class NSURLClass = objc_getClass("NSURL");
+ SEL fileURLWithPathSel = sel_registerName("fileURLWithPath:");
+ id nsurl = ((id(*)(Class, SEL, id))objc_msgSend)(NSURLClass, fileURLWithPathSel, pathString);
+
+ SEL trashItemAtURLSel = sel_registerName("trashItemAtURL:resultingItemURL:error:");
+ BOOL deleteSuccessful = ((BOOL(*)(id, SEL, id, id, id))objc_msgSend)(
+ fileManager, trashItemAtURLSel, nsurl, nil, nil);
+
+ if (deleteSuccessful) {
+ ret = 0;
+ }
+ else {
+ *error_message = "The Cocoa API call to delete file or directory failed";
+ }
+
+ SEL drainSel = sel_registerName("drain");
+ ((void (*)(id, SEL))objc_msgSend)(pool, drainSel);
+
+ return ret;
+}
+# else
+static int delete_soft(const char *file, const char **error_message)
+{
+ const char *args[5];
+ const char *process_failed;
+
+ char *xdg_current_desktop = getenv("XDG_CURRENT_DESKTOP");
+ char *xdg_session_desktop = getenv("XDG_SESSION_DESKTOP");
+
+ if ((xdg_current_desktop != NULL && strcmp(xdg_current_desktop, "KDE") == 0) ||
+ (xdg_session_desktop != NULL && strcmp(xdg_session_desktop, "KDE") == 0)) {
+ args[0] = "kioclient5";
+ args[1] = "move";
+ args[2] = file;
+ args[3] = "trash:/";
+ args[4] = NULL;
+ process_failed = "kioclient5 reported failure";
+ }
+ else {
+ args[0] = "gio";
+ args[1] = "trash";
+ args[2] = file;
+ args[3] = NULL;
+ process_failed = "gio reported failure";
+ }
+
+ int pid = fork();
+
+ if (pid != 0) {
+ /* Parent process */
+ int wstatus = 0;
+
+ waitpid(pid, &wstatus, 0);
+
+ if (!WIFEXITED(wstatus)) {
+ *error_message =
+ "Blender may not support moving files or directories to trash on your system.";
+ return -1;
+ }
+ else if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus)) {
+ *error_message = process_failed;
+ return -1;
+ }
+
+ return 0;
+ }
+
+ execvp(args[0], (char **)args);
+
+ *error_message = "Forking process failed.";
+ return -1; /* This should only be reached if execvp fails and stack isn't replaced. */
+}
+# endif
+
FILE *BLI_fopen(const char *filename, const char *mode)
{
BLI_assert(!BLI_path_is_rel(filename));
@@ -770,6 +948,19 @@ int BLI_delete(const char *file, bool dir, bool recursive)
}
/**
+ * Soft deletes the specified file or directory (depending on dir) by moving the files to the
+ * recycling bin, optionally doing recursive delete of directory contents.
+ *
+ * \return zero on success (matching 'remove' behavior).
+ */
+int BLI_delete_soft(const char *file, const char **error_message)
+{
+ BLI_assert(!BLI_path_is_rel(file));
+
+ return delete_soft(file, error_message);
+}
+
+/**
* Do the two paths denote the same file-system object?
*/
static bool check_the_same(const char *path_a, const char *path_b)
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index 08c3653153e..c9b0eb3ed5e 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -907,7 +907,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const
return 0;
}
- axis_dominant_v3_to_m3(mat_2d, n);
+ axis_dominant_v3_to_m3_negate(mat_2d, n);
}
/* STEP 1: COUNT POLYS */
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 05a2d766fe0..fd5de717a24 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -209,7 +209,6 @@ int BLI_exists(const char *name)
BLI_stat_t st;
wchar_t *tmp_16 = alloc_utf16_from_8(name, 1);
int len, res;
- unsigned int old_error_mode;
len = wcslen(tmp_16);
/* in Windows #stat doesn't recognize dir ending on a slash
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 545659d06c2..7257c26e1d2 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -8240,9 +8240,9 @@ void blo_lib_link_restore(Main *oldmain,
}
/* Restore all ID pointers in Main database itself
- * (especially IDProperties might point to some worspace of other 'weirdly unchanged' ID
+ * (especially IDProperties might point to some word-space of other 'weirdly unchanged' ID
* pointers, see T69146).
- * Note that this will re;ap again a few pointers in workspaces or so,
+ * Note that this will re-apply again a few pointers in workspaces or so,
* but since we are remapping final ones already set above,
* that is just some minor harmless double-processing. */
lib_link_main_data_restore(id_map, newmain);
@@ -10101,7 +10101,7 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
}
else {
/* Convert any previously read weak link to regular link
- * to signal that we want to read this datablock. */
+ * to signal that we want to read this data-block. */
if (id->tag & LIB_TAG_ID_LINK_PLACEHOLDER) {
id->flag &= ~LIB_INDIRECT_WEAK_LINK;
}
@@ -10151,7 +10151,7 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
}
else {
/* Convert any previously read weak link to regular link
- * to signal that we want to read this datablock. */
+ * to signal that we want to read this data-block. */
if (id->tag & LIB_TAG_ID_LINK_PLACEHOLDER) {
id->flag &= ~LIB_INDIRECT_WEAK_LINK;
}
@@ -12002,7 +12002,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
Main *main_newid = BKE_main_new();
for (Main *mainptr = mainl->next; mainptr; mainptr = mainptr->next) {
- /* Drop weak links for which no datablock was found. */
+ /* Drop weak links for which no data-block was found. */
read_library_clear_weak_links(basefd, mainlist, mainptr);
/* Do versioning for newly added linked data-locks. If no data-locks
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 72013bc6eed..d8e4f3d97a5 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -1673,15 +1673,13 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
}
for (scene = bmain->scenes.first; scene; scene = scene->id.next) {
- if (scene) {
- Sequence *seq;
- SEQ_BEGIN (scene->ed, seq) {
- if (seq->sat == 0.0f) {
- seq->sat = 1.0f;
- }
+ Sequence *seq;
+ SEQ_BEGIN (scene->ed, seq) {
+ if (seq->sat == 0.0f) {
+ seq->sat = 1.0f;
}
- SEQ_END;
}
+ SEQ_END;
}
/* GSOC 2010 Sculpt - New settings for Brush */
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 7ea1d25f86d..9e0d3b7a419 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -585,13 +585,18 @@ static void do_versions_fix_annotations(bGPdata *gpd)
}
}
-static void do_versions_remove_region(ListBase *regionbase, int regiontype)
+static void do_versions_remove_region(ListBase *regionbase, ARegion *ar)
+{
+ BLI_freelinkN(regionbase, ar);
+}
+
+static void do_versions_remove_regions_by_type(ListBase *regionbase, int regiontype)
{
ARegion *ar, *ar_next;
for (ar = regionbase->first; ar; ar = ar_next) {
ar_next = ar->next;
if (ar->regiontype == regiontype) {
- BLI_freelinkN(regionbase, ar);
+ do_versions_remove_region(regionbase, ar);
}
}
}
@@ -1267,6 +1272,22 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
ma->blend_method = MA_BM_BLEND;
}
}
+
+ {
+ /* Update all ruler layers to set new flag. */
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ bGPdata *gpd = scene->gpd;
+ if (gpd == NULL) {
+ continue;
+ }
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (STREQ(gpl->info, "RulerData3D")) {
+ gpl->flag |= GP_LAYER_IS_RULER;
+ break;
+ }
+ }
+ }
+ }
}
}
@@ -3340,7 +3361,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
/* Remove multiple footers that were added by mistake. */
- do_versions_remove_region(regionbase, RGN_TYPE_FOOTER);
+ do_versions_remove_regions_by_type(regionbase, RGN_TYPE_FOOTER);
/* Add footer. */
ARegion *ar = do_versions_add_region(RGN_TYPE_FOOTER, "footer for text");
@@ -3844,8 +3865,13 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
- {
- /* Versioning code until next subversion bump goes here. */
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 15)) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ if (scene->toolsettings->snap_node_mode == SCE_SNAP_MODE_NODE_X) {
+ scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
+ }
+ }
+
if (!DNA_struct_elem_find(
fd->filesdna, "LayerCollection", "short", "local_collections_bits")) {
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
@@ -3887,7 +3913,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
/* We temporarily had two tools regions, get rid of the second one. */
if (ar_next && ar_next->regiontype == RGN_TYPE_TOOLS) {
- do_versions_remove_region(regionbase, RGN_TYPE_TOOLS);
+ do_versions_remove_region(regionbase, ar_next);
}
BLI_remlink(regionbase, ar_tools);
@@ -3903,4 +3929,8 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+
+ {
+ /* Versioning code until next subversion bump goes here. */
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 62bd605a2c2..1b30c7371a2 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -1705,19 +1705,17 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
/* add default radius values to old curve points */
for (cu = bmain->curves.first; cu; cu = cu->id.next) {
for (nu = cu->nurb.first; nu; nu = nu->next) {
- if (nu) {
- if (nu->bezt) {
- for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
- if (!bezt->radius) {
- bezt->radius = 1.0;
- }
+ if (nu->bezt) {
+ for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
+ if (!bezt->radius) {
+ bezt->radius = 1.0;
}
}
- else if (nu->bp) {
- for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
- if (!bp->radius) {
- bp->radius = 1.0;
- }
+ }
+ else if (nu->bp) {
+ for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
+ if (!bp->radius) {
+ bp->radius = 1.0;
}
}
}
@@ -2515,17 +2513,15 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
for (cu = bmain->curves.first; cu; cu = cu->id.next) {
for (nu = cu->nurb.first; nu; nu = nu->next) {
- if (nu) {
- nu->radius_interp = 3;
-
- /* resolu and resolv are now used differently for surfaces
- * rather than using the resolution to define the entire number of divisions,
- * use it for the number of divisions per segment
- */
- if (nu->pntsv > 1) {
- nu->resolu = MAX2(1, (int)(((float)nu->resolu / (float)nu->pntsu) + 0.5f));
- nu->resolv = MAX2(1, (int)(((float)nu->resolv / (float)nu->pntsv) + 0.5f));
- }
+ nu->radius_interp = 3;
+
+ /* resolu and resolv are now used differently for surfaces
+ * rather than using the resolution to define the entire number of divisions,
+ * use it for the number of divisions per segment
+ */
+ if (nu->pntsv > 1) {
+ nu->resolu = MAX2(1, (int)(((float)nu->resolu / (float)nu->pntsu) + 0.5f));
+ nu->resolv = MAX2(1, (int)(((float)nu->resolv / (float)nu->pntsv) + 0.5f));
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index bbae1c8e85e..d2192f1e22a 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -30,6 +30,7 @@
#include "DNA_windowmanager_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
+#include "DNA_anim_types.h"
#include "BKE_addon.h"
#include "BKE_colorband.h"
@@ -146,14 +147,18 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
FROM_DEFAULT_V4_UCHAR(space_outliner.active);
}
- /**
- * Include next version bump.
- */
- {
+ if (!USER_VERSION_ATLEAST(281, 14)) {
FROM_DEFAULT_V4_UCHAR(space_file.execution_buts);
FROM_DEFAULT_V4_UCHAR(tui.icon_folder);
FROM_DEFAULT_V4_UCHAR(space_clip.path_keyframe_before);
FROM_DEFAULT_V4_UCHAR(space_clip.path_keyframe_after);
+ copy_v4_v4_uchar(btheme->space_nla.nla_track, btheme->space_nla.header);
+ }
+
+ /**
+ * Include next version bump.
+ */
+ {
}
#undef FROM_DEFAULT_V4_UCHAR
@@ -623,15 +628,20 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef)
userdef->filebrowser_display_type = USER_TEMP_SPACE_DISPLAY_WINDOW;
}
+ if (!USER_VERSION_ATLEAST(281, 13)) {
+ userdef->auto_smoothing_new = FCURVE_SMOOTH_CONT_ACCEL;
+
+ if (userdef->file_space_data.display_type == FILE_DEFAULTDISPLAY) {
+ memcpy(
+ &userdef->file_space_data, &U_default.file_space_data, sizeof(userdef->file_space_data));
+ }
+ }
+
/**
* Include next version bump.
*/
{
/* pass */
- if (userdef->file_space_data.display_type == FILE_DEFAULTDISPLAY) {
- memcpy(
- &userdef->file_space_data, &U_default.file_space_data, sizeof(userdef->file_space_data));
- }
}
if (userdef->pixelsize == 0.0f) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index aae5072c8de..d24fca4391a 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -26,35 +26,36 @@
* FILE FORMAT
* ===========
*
- * IFF-style structure (but not IFF compatible!)
+ * IFF-style structure (but not IFF compatible!)
*
- * start file:
+ * Start file:
* <pre>
- * BLENDER_V100 12 bytes (version 1.00)
- * V = big endian, v = little endian
- * _ = 4 byte pointer, - = 8 byte pointer
+ * `BLENDER_V100` `12` bytes (version 1.00 is just an example).
+ * `V` = big endian, `v` = little endian.
+ * `_` = 4 byte pointer, `-` = 8 byte pointer.
* </pre>
*
* data-blocks: (also see struct #BHead).
* <pre>
- * <bh.code> 4 chars
- * <bh.len> int, len data after BHead
- * <bh.old> void, old pointer
- * <bh.SDNAnr> int
- * <bh.nr> int, in case of array: number of structs
- * data
- * ...
- * ...
+ * `bh.code` `char[4]` see `BLO_blend_defs.h` for a list of known types.
+ * `bh.len` `int32` length data after #BHead in bytes.
+ * `bh.old` `void *` old pointer (the address at the time of writing the file).
+ * `bh.SDNAnr` `int32` struct index of structs stored in #DNA1 data.
+ * `bh.nr` `int32` in case of array: number of structs.
+ * data
+ * ...
+ * ...
* </pre>
*
* Almost all data in Blender are structures. Each struct saved
* gets a BHead header. With BHead the struct can be linked again
- * and compared with StructDNA .
+ * and compared with #StructDNA.
+
* WRITE
* =====
*
* Preferred writing order: (not really a must, but why would you do it random?)
- * Any case: direct data is ALWAYS after the lib block
+ * Any case: direct data is ALWAYS after the lib block.
*
* (Local file data)
* - for each LibBlock
diff --git a/source/blender/blentranslation/msgfmt/CMakeLists.txt b/source/blender/blentranslation/msgfmt/CMakeLists.txt
index 1b46efb1bb5..0361137f5b1 100644
--- a/source/blender/blentranslation/msgfmt/CMakeLists.txt
+++ b/source/blender/blentranslation/msgfmt/CMakeLists.txt
@@ -32,6 +32,10 @@ set(SRC
add_cc_flags_custom_test(msgfmt)
+if(APPLE)
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}")
+endif()
+
add_executable(msgfmt ${SRC})
target_link_libraries(msgfmt bf_blenlib)
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index ff7dcc388b3..64687ac154c 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -1507,7 +1507,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW);
}
- BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001);
+ BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.0000005 * depth);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 79593f07383..47325c4dece 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -104,7 +104,7 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
fcu->array_index = 0;
- fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+ fcu->auto_smoothing = U.auto_smoothing_new;
for (unsigned int j = 0; j < curve->getKeyCount(); j++) {
BezTriple bez;
diff --git a/source/blender/collada/BCAnimationCurve.cpp b/source/blender/collada/BCAnimationCurve.cpp
index bf32ec9148c..f944a77196c 100644
--- a/source/blender/collada/BCAnimationCurve.cpp
+++ b/source/blender/collada/BCAnimationCurve.cpp
@@ -383,7 +383,7 @@ void BCAnimationCurve::adjust_range(const int frame_index)
void BCAnimationCurve::add_value(const float val, const int frame_index)
{
FCurve *fcu = get_edit_fcurve();
- fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+ fcu->auto_smoothing = U.auto_smoothing_new;
insert_vert_fcurve(fcu, frame_index, val, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NOFLAGS);
if (fcu->totvert == 1) {
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index 71201c8a55c..6e31e17fb26 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -107,7 +107,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
/* make absolute source path */
BLI_strncpy(source_path, image->name, sizeof(source_path));
- BLI_path_abs(source_path, BKE_main_blendfile_path_from_global());
+ BLI_path_abs(source_path, ID_BLEND_PATH_FROM_GLOBAL(&image->id));
BLI_cleanup_path(NULL, source_path);
if (use_copies) {
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index 2a8914c8cd9..f0685b169fa 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -566,6 +566,7 @@ if(WITH_OPENIMAGEDENOISE)
add_definitions(-DOIDN_STATIC_LIB)
list(APPEND INC_SYS
${OPENIMAGEDENOISE_INCLUDE_DIRS}
+ ${TBB_INCLUDE_DIRS}
)
endif()
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index e44dddbcf54..d5a93d21b99 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -179,14 +179,14 @@ void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func, DEG_EditorUpdateSce
/* Evaluation ----------------------------------- */
+bool DEG_is_evaluating(struct Depsgraph *depsgraph);
+
bool DEG_is_active(const struct Depsgraph *depsgraph);
void DEG_make_active(struct Depsgraph *depsgraph);
void DEG_make_inactive(struct Depsgraph *depsgraph);
/* Evaluation Debug ------------------------------ */
-bool DEG_debug_is_evaluating(struct Depsgraph *depsgraph);
-
void DEG_debug_print_begin(struct Depsgraph *depsgraph);
void DEG_debug_print_eval(struct Depsgraph *depsgraph,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 7dfc863b847..d0e40d49527 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -527,6 +527,9 @@ void DepsgraphNodeBuilder::build_object(int base_index,
eDepsNode_LinkedState_Type linked_state,
bool is_visible)
{
+ if (object->proxy != NULL) {
+ object->proxy->proxy_from = object;
+ }
const bool has_object = built_map_.checkIsBuiltAndTag(object);
/* Skip rest of components if the ID node was already there. */
if (has_object) {
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index dcdea87fe1a..8f9595d2476 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -76,7 +76,7 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati
ctime(BKE_scene_frame_get(scene)),
scene_cow(NULL),
is_active(false),
- debug_is_evaluating(false),
+ is_evaluating(false),
is_render_pipeline_depsgraph(false)
{
BLI_spin_init(&lock);
@@ -334,6 +334,12 @@ void DEG_graph_free(Depsgraph *graph)
OBJECT_GUARDED_DELETE(deg_depsgraph, Depsgraph);
}
+bool DEG_is_evaluating(struct Depsgraph *depsgraph)
+{
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ return deg_graph->is_evaluating;
+}
+
bool DEG_is_active(const struct Depsgraph *depsgraph)
{
if (depsgraph == NULL) {
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index 30ae4edde34..43829f4e045 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -198,7 +198,7 @@ struct Depsgraph {
int debug_flags;
string debug_name;
- bool debug_is_evaluating;
+ bool is_evaluating;
/* Is set to truth for dependency graph which are used for post-processing (compositor and
* sequencer).
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index d079c958e04..bb60db5209c 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -246,12 +246,6 @@ void DEG_stats_simple(const Depsgraph *graph,
}
}
-bool DEG_debug_is_evaluating(struct Depsgraph *depsgraph)
-{
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
- return deg_graph->debug_is_evaluating;
-}
-
static DEG::string depsgraph_name_for_logging(struct Depsgraph *depsgraph)
{
const char *name = DEG_debug_name_get(depsgraph);
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index b2b7d2a9d00..665a32b886c 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -73,7 +73,7 @@ void DEG_evaluate_on_framechange(Main *bmain, Depsgraph *graph, float ctime)
/* Update time on primary timesource. */
DEG::TimeSourceNode *tsrc = deg_graph->find_time_source();
tsrc->cfra = ctime;
- tsrc->tag_update(deg_graph, DEG::DEG_UPDATE_SOURCE_TIME);
+ deg_graph->need_update_time = true;
DEG::deg_graph_flush_updates(bmain, deg_graph);
/* Update time in scene. */
if (deg_graph->scene_cow) {
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index 28789968286..db469612f76 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -152,7 +152,7 @@ bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
copy_v4_v4(temp_dupli_object->color, dupli_parent->color);
/* Duplicated elements shouldn't care whether their original collection is visible or not. */
- temp_dupli_object->base_flag |= BASE_VISIBLE;
+ temp_dupli_object->base_flag |= BASE_VISIBLE_DEPSGRAPH;
int ob_visibility = BKE_object_visibility(temp_dupli_object, data->eval_mode);
if ((ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) == 0) {
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 2fdce0e30a5..ce5917110d6 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -367,7 +367,7 @@ static void graph_id_tag_update_single_flag(Main *bmain,
eUpdateSource update_source)
{
if (tag == ID_RECALC_EDITORS) {
- if (graph != NULL) {
+ if (graph != NULL && graph->is_active) {
depsgraph_update_editors_tag(bmain, graph, id);
}
return;
@@ -462,7 +462,8 @@ const char *update_source_as_string(eUpdateSource source)
int deg_recalc_flags_for_legacy_zero()
{
- return ID_RECALC_ALL & ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION | ID_RECALC_SOURCE);
+ return ID_RECALC_ALL & ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION | ID_RECALC_SOURCE |
+ ID_RECALC_TIME | ID_RECALC_EDITORS);
}
int deg_recalc_flags_effective(Depsgraph *graph, int flags)
@@ -510,6 +511,14 @@ void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph, const bool do_ti
* to evaluation though) with `do_time=true`. This means early output checks should be aware of
* this. */
for (DEG::IDNode *id_node : graph->id_nodes) {
+ const ID_Type id_type = GS(id_node->id_orig->name);
+ if (id_type == ID_OB) {
+ Object *object_orig = reinterpret_cast<Object *>(id_node->id_orig);
+ if (object_orig->proxy != NULL) {
+ object_orig->proxy->proxy_from = object_orig;
+ }
+ }
+
if (!id_node->visible_components_mask) {
/* ID has no components which affects anything visible.
* No need bother with it to tag or anything. */
@@ -536,7 +545,6 @@ void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph, const bool do_ti
* other type of cache).
*
* TODO(sergey): Need to generalize this somehow. */
- const ID_Type id_type = GS(id_node->id_orig->name);
if (id_type == ID_OB) {
flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
}
@@ -614,6 +622,12 @@ void graph_id_tag_update(
Main *bmain, Depsgraph *graph, ID *id, int flag, eUpdateSource update_source)
{
const int debug_flags = (graph != NULL) ? DEG_debug_flags_get((::Depsgraph *)graph) : G.debug;
+ if (graph != NULL && graph->is_evaluating) {
+ if (debug_flags & G_DEBUG_DEPSGRAPH) {
+ printf("ID tagged for update during dependency graph evaluation.");
+ }
+ return;
+ }
if (debug_flags & G_DEBUG_DEPSGRAPH_TAG) {
printf("%s: id=%s flags=%s source=%s\n",
__func__,
@@ -808,24 +822,6 @@ static void deg_graph_clear_id_recalc_flags(ID *id)
}
}
-static void deg_graph_clear_id_node_func(void *__restrict data_v,
- const int i,
- const TaskParallelTLS *__restrict /*tls*/)
-{
- /* TODO: we clear original ID recalc flags here, but this may not work
- * correctly when there are multiple depsgraph with others still using
- * the recalc flag. */
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(data_v);
- DEG::IDNode *id_node = deg_graph->id_nodes[i];
-
- id_node->is_user_modified = false;
-
- deg_graph_clear_id_recalc_flags(id_node->id_cow);
- if (deg_graph->is_active) {
- deg_graph_clear_id_recalc_flags(id_node->id_orig);
- }
-}
-
void DEG_ids_clear_recalc(Main *UNUSED(bmain), Depsgraph *depsgraph)
{
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
@@ -835,10 +831,15 @@ void DEG_ids_clear_recalc(Main *UNUSED(bmain), Depsgraph *depsgraph)
return;
}
/* Go over all ID nodes nodes, clearing tags. */
- const int num_id_nodes = deg_graph->id_nodes.size();
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 1024;
- BLI_task_parallel_range(0, num_id_nodes, deg_graph, deg_graph_clear_id_node_func, &settings);
+ for (DEG::IDNode *id_node : deg_graph->id_nodes) {
+ /* TODO: we clear original ID recalc flags here, but this may not work
+ * correctly when there are multiple depsgraph with others still using
+ * the recalc flag. */
+ id_node->is_user_modified = false;
+ deg_graph_clear_id_recalc_flags(id_node->id_cow);
+ if (deg_graph->is_active) {
+ deg_graph_clear_id_recalc_flags(id_node->id_orig);
+ }
+ }
memset(deg_graph->id_type_updated, 0, sizeof(deg_graph->id_type_updated));
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index b2415c9e89d..d6b3c54a149 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -91,10 +91,6 @@ static void deg_task_run_func(TaskPool *pool, void *taskdata, int thread_id)
BLI_task_pool_delayed_push_end(pool, thread_id);
}
-struct CalculatePendingData {
- Depsgraph *graph;
-};
-
static bool check_operation_node_visible(OperationNode *op_node)
{
const ComponentNode *comp_node = op_node->owner;
@@ -106,13 +102,8 @@ static bool check_operation_node_visible(OperationNode *op_node)
return comp_node->affects_directly_visible;
}
-static void calculate_pending_func(void *__restrict data_v,
- const int i,
- const TaskParallelTLS *__restrict /*tls*/)
+static void calculate_pending_parents_for_node(OperationNode *node)
{
- CalculatePendingData *data = (CalculatePendingData *)data_v;
- Depsgraph *graph = data->graph;
- OperationNode *node = graph->operations[i];
/* Update counters, applies for both visible and invisible IDs. */
node->num_links_pending = 0;
node->scheduled = false;
@@ -134,7 +125,7 @@ static void calculate_pending_func(void *__restrict data_v,
if (!check_operation_node_visible(from)) {
continue;
}
- /* No need to vait for operation which is up to date. */
+ /* No need to wait for operation which is up to date. */
if ((from->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
continue;
}
@@ -145,13 +136,9 @@ static void calculate_pending_func(void *__restrict data_v,
static void calculate_pending_parents(Depsgraph *graph)
{
- const int num_operations = graph->operations.size();
- CalculatePendingData data;
- data.graph = graph;
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 1024;
- BLI_task_parallel_range(0, num_operations, &data, calculate_pending_func, &settings);
+ for (OperationNode *node : graph->operations) {
+ calculate_pending_parents_for_node(node);
+ }
}
static void initialize_execution(DepsgraphEvalState *state, Depsgraph *graph)
@@ -221,7 +208,7 @@ static void schedule_node(
static void schedule_graph(TaskPool *pool, Depsgraph *graph)
{
for (OperationNode *node : graph->operations) {
- schedule_node(pool, graph, node, false, 0);
+ schedule_node(pool, graph, node, false, -1);
}
}
@@ -270,7 +257,7 @@ void deg_evaluate_on_refresh(Depsgraph *graph)
}
const bool do_time_debug = ((G.debug & G_DEBUG_DEPSGRAPH_TIME) != 0);
const double start_time = do_time_debug ? PIL_check_seconds_timer() : 0;
- graph->debug_is_evaluating = true;
+ graph->is_evaluating = true;
depsgraph_ensure_view_layer(graph);
/* Set up evaluation state. */
DepsgraphEvalState state;
@@ -311,7 +298,7 @@ void deg_evaluate_on_refresh(Depsgraph *graph)
if (need_free_scheduler) {
BLI_task_scheduler_free(task_scheduler);
}
- graph->debug_is_evaluating = false;
+ graph->is_evaluating = false;
if (do_time_debug) {
printf("Depsgraph updated in %f seconds.\n", PIL_check_seconds_timer() - start_time);
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index 2479373b687..96e2974a7ab 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -87,15 +87,6 @@ typedef std::deque<OperationNode *> FlushQueue;
namespace {
-void flush_init_operation_node_func(void *__restrict data_v,
- const int i,
- const TaskParallelTLS *__restrict /*tls*/)
-{
- Depsgraph *graph = (Depsgraph *)data_v;
- OperationNode *node = graph->operations[i];
- node->scheduled = false;
-}
-
void flush_init_id_node_func(void *__restrict data_v,
const int i,
const TaskParallelTLS *__restrict /*tls*/)
@@ -110,13 +101,10 @@ void flush_init_id_node_func(void *__restrict data_v,
BLI_INLINE void flush_prepare(Depsgraph *graph)
{
- {
- const int num_operations = graph->operations.size();
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 1024;
- BLI_task_parallel_range(0, num_operations, graph, flush_init_operation_node_func, &settings);
+ for (OperationNode *node : graph->operations) {
+ node->scheduled = false;
}
+
{
const int num_id_nodes = graph->id_nodes.size();
TaskParallelSettings settings;
@@ -351,9 +339,6 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
BLI_assert(bmain != NULL);
BLI_assert(graph != NULL);
/* Nothing to update, early out. */
- if (BLI_gset_len(graph->entry_tags) == 0 && !graph->need_update_time) {
- return;
- }
if (graph->need_update_time) {
const Scene *scene_orig = graph->scene;
const float ctime = BKE_scene_frame_get(scene_orig);
@@ -361,6 +346,9 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
graph->ctime = ctime;
time_source->tag_update(graph, DEG::DEG_UPDATE_SOURCE_TIME);
}
+ if (BLI_gset_len(graph->entry_tags) == 0) {
+ return;
+ }
/* Reset all flags, get ready for the flush. */
flush_prepare(graph);
/* Starting from the tagged "entry" nodes, flush outwards. */
@@ -395,27 +383,13 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
invalidate_tagged_evaluated_data(graph);
}
-static void graph_clear_operation_func(void *__restrict data_v,
- const int i,
- const TaskParallelTLS *__restrict /*tls*/)
-{
- Depsgraph *graph = (Depsgraph *)data_v;
- OperationNode *node = graph->operations[i];
- /* Clear node's "pending update" settings. */
- node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE |
- DEPSOP_FLAG_USER_MODIFIED);
-}
-
/* Clear tags from all operation nodes. */
void deg_graph_clear_tags(Depsgraph *graph)
{
/* Go over all operation nodes, clearing tags. */
- {
- const int num_operations = graph->operations.size();
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 1024;
- BLI_task_parallel_range(0, num_operations, graph, graph_clear_operation_func, &settings);
+ for (OperationNode *node : graph->operations) {
+ node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE |
+ DEPSOP_FLAG_USER_MODIFIED);
}
/* Clear any entry tags which haven't been flushed. */
BLI_gset_clear(graph->entry_tags, NULL);
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index 188e252a285..0dd1a4fd686 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -72,7 +72,6 @@ static struct {
typedef struct BASIC_PrivateData {
DRWShadingGroup *depth_shgrp;
DRWShadingGroup *depth_shgrp_cull;
- DRWShadingGroup *depth_shgrp_hair;
} BASIC_PrivateData; /* Transient data */
/* Functions */
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 7df1c299454..d59d1f56e92 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -29,6 +29,7 @@
#include "eevee_private.h"
#include "GPU_texture.h"
#include "GPU_extensions.h"
+#include "GPU_platform.h"
#include "GPU_state.h"
static struct {
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 19f3983998e..4b0af273f7f 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -51,7 +51,6 @@ static struct {
struct GPUTexture *planar_pool_placeholder;
struct GPUTexture *depth_placeholder;
struct GPUTexture *depth_array_placeholder;
- struct GPUTexture *cube_face_minmaxz;
struct GPUVertFormat *format_probe_display_cube;
struct GPUVertFormat *format_probe_display_planar;
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index f01c6363ccb..701d73461fc 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -1588,7 +1588,9 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
/* Shadow Pass */
struct GPUMaterial *gpumat;
- switch (ma_array[i]->blend_shadow) {
+ const bool use_gpumat = (ma_array[i]->use_nodes && ma_array[i]->nodetree);
+ char blend_shadow = use_gpumat ? ma_array[i]->blend_shadow : MA_BS_SOLID;
+ switch (blend_shadow) {
case MA_BS_SOLID:
EEVEE_shadows_caster_add(sldata, stl, mat_geom[i], ob);
*cast_shadow = true;
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index 924b3d3b19b..48e9b5bcc13 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -33,6 +33,7 @@
#include "eevee_private.h"
#include "GPU_extensions.h"
+#include "GPU_platform.h"
#include "GPU_state.h"
static struct {
@@ -40,7 +41,6 @@ static struct {
struct GPUShader *gtao_sh;
struct GPUShader *gtao_layer_sh;
struct GPUShader *gtao_debug_sh;
- struct GPUTexture *src_depth;
struct GPUTexture *dummy_horizon_tx;
} e_data = {NULL}; /* Engine data */
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index 2daf2388d63..591ca31017c 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -46,7 +46,6 @@ static struct {
/* These are just references, not actually allocated */
struct GPUTexture *depth_src;
- struct GPUTexture *color_src;
} e_data = {{NULL}}; /* Engine data */
extern char datatoc_ambient_occlusion_lib_glsl[];
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index fac87bad41a..aaa351a1922 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -54,7 +54,6 @@ static struct {
struct GPUShader *volumetric_integration_sh;
struct GPUShader *volumetric_resolve_sh;
- GPUTexture *color_src;
GPUTexture *depth_src;
GPUTexture *dummy_density;
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index 98012aea303..1f68935403c 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -918,14 +918,15 @@ void main()
Closure cl = nodetree_exec();
float holdout = 1.0 - saturate(cl.holdout);
+ float transmit = saturate(avg(cl.transmittance));
+ float alpha = 1.0 - transmit;
# ifdef USE_ALPHA_BLEND
vec2 uvs = gl_FragCoord.xy * volCoordScale.zw;
vec3 vol_transmit, vol_scatter;
volumetric_resolve(uvs, gl_FragCoord.z, vol_transmit, vol_scatter);
- float transmit = saturate(avg(cl.transmittance));
- outRadiance = vec4(cl.radiance * vol_transmit + vol_scatter, (1.0 - transmit) * holdout);
+ outRadiance = vec4(cl.radiance * vol_transmit + vol_scatter, alpha * holdout);
outTransmittance = vec4(cl.transmittance, transmit * holdout);
# else
outRadiance = vec4(cl.radiance, holdout);
@@ -953,6 +954,15 @@ void main()
outRadiance.rgb += cl.sss_irradiance.rgb * cl.sss_albedo.rgb * fac;
# endif
+
+# ifndef USE_ALPHA_BLEND
+ float alpha_div = 1.0 / max(1e-8, alpha);
+ outRadiance *= alpha_div;
+ ssrData.rgb *= alpha_div;
+# ifdef USE_SSS
+ sssAlbedo.rgb *= alpha_div;
+# endif
+# endif
}
# endif /* MESH_SHADER && !SHADOW_SHADER */
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index 33e6d73eeeb..f9df1342bf8 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -50,10 +50,6 @@ static bool gpencil_has_noninstanced_object(Object *ob_instance)
if (ob->type != OB_GPENCIL) {
continue;
}
- /* object must be visible (invisible objects don't create VBO data) */
- if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) {
- continue;
- }
/* is not duplicated and the name is equals */
if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
if (STREQ(ob->id.name, ob_instance->id.name)) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
index ce5d8cbf732..0997568ed22 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -37,7 +37,6 @@
#include "DNA_gpencil_types.h"
#include "DNA_material_types.h"
#include "DNA_view3d_types.h"
-#include "DNA_gpencil_modifier_types.h"
/* If builtin shaders are needed */
#include "GPU_shader.h"
@@ -141,13 +140,9 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
Object *ob = cache_ob->ob;
const DRWContextState *draw_ctx = DRW_context_state_get();
- const bool main_onion = draw_ctx->v3d != NULL ?
- (draw_ctx->v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) :
- true;
+ const bool main_onion = stl->storage->is_main_onion;
const bool playing = stl->storage->is_playing;
- const bool overlay = draw_ctx->v3d != NULL ?
- (bool)((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) :
- true;
+ const bool overlay = stl->storage->is_main_overlay;
const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && overlay &&
main_onion && !playing && gpencil_onion_active(gpd);
@@ -225,23 +220,6 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
cache->b_point.tot_vertex = cache_ob->tot_vertex;
cache->b_edit.tot_vertex = cache_ob->tot_vertex;
cache->b_edlin.tot_vertex = cache_ob->tot_vertex;
-
- /* some modifiers can change the number of points */
- int factor = 0;
- GpencilModifierData *md;
- for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
- /* only modifiers that change size */
- if (mti && mti->getDuplicationFactor) {
- factor = mti->getDuplicationFactor(md);
-
- cache->b_fill.tot_vertex *= factor;
- cache->b_stroke.tot_vertex *= factor;
- cache->b_point.tot_vertex *= factor;
- cache->b_edit.tot_vertex *= factor;
- cache->b_edlin.tot_vertex *= factor;
- }
- }
}
/* Helper for doing all the checks on whether a stroke can be drawn */
@@ -1781,8 +1759,8 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data,
const bool overlay = draw_ctx->v3d != NULL ?
(bool)((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) :
true;
- const bool main_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true;
- const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && main_onion &&
+ const bool screen_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true;
+ const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && screen_onion &&
overlay && gpencil_onion_active(gpd);
int start_stroke = 0;
@@ -2062,13 +2040,9 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data,
bGPdata *gpd_eval = (bGPdata *)ob->data;
bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
- const bool main_onion = draw_ctx->v3d != NULL ?
- (draw_ctx->v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) :
- true;
+ const bool main_onion = stl->storage->is_main_onion;
const bool playing = stl->storage->is_playing;
- const bool overlay = draw_ctx->v3d != NULL ?
- (bool)((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) :
- true;
+ const bool overlay = stl->storage->is_main_overlay;
const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && overlay &&
main_onion && !playing && gpencil_onion_active(gpd);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 7d9f2d1fdf3..aed6789fe26 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -24,11 +24,13 @@
#include "BKE_gpencil.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_shader_fx.h"
#include "DNA_gpencil_types.h"
+#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "draw_mode_engines.h"
@@ -310,6 +312,43 @@ static void GPENCIL_engine_free(void)
GPENCIL_delete_fx_shaders(&e_data);
}
+/* Helper: Check if the main overlay and onion switches are enabled in any screen.
+ *
+ * This is required to generate the onion skin and limit the times the cache is updated because the
+ * cache is generated only in the first screen and if the first screen has the onion disabled the
+ * cache for onion skin is not generated. The loop adds time, but always is faster than regenerate
+ * the cache all the times.
+ */
+static void gpencil_check_screen_switches(const DRWContextState *draw_ctx,
+ GPENCIL_StorageList *stl)
+{
+ stl->storage->is_main_overlay = false;
+ stl->storage->is_main_onion = false;
+ /* Check if main onion switch is enabled in any screen. */
+ Main *bmain = CTX_data_main(draw_ctx->evil_C);
+
+ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa && sa->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = sa->spacedata.first;
+ if (v3d == NULL) {
+ continue;
+ }
+ if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) {
+ stl->storage->is_main_overlay = true;
+ }
+ if (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) {
+ stl->storage->is_main_onion = true;
+ }
+ }
+ /* If found, don't need loop more. */
+ if ((stl->storage->is_main_overlay) && (stl->storage->is_main_onion)) {
+ return;
+ }
+ }
+ }
+}
+
void GPENCIL_cache_init(void *vedata)
{
GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
@@ -320,6 +359,7 @@ void GPENCIL_cache_init(void *vedata)
ToolSettings *ts = scene->toolsettings;
View3D *v3d = draw_ctx->v3d;
Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
+ const View3DCursor *cursor = &scene->cursor;
/* Special handling for when active object is GP object (e.g. for draw mode) */
Object *obact = draw_ctx->obact;
@@ -395,10 +435,15 @@ void GPENCIL_cache_init(void *vedata)
stl->storage->reset_cache = true;
}
stl->storage->is_playing = playing;
+
+ /* Found if main overlay and onion switches are enabled in any screen. */
+ gpencil_check_screen_switches(draw_ctx, stl);
}
else {
stl->storage->is_playing = false;
stl->storage->reset_cache = false;
+ stl->storage->is_main_overlay = false;
+ stl->storage->is_main_onion = false;
}
/* save render state */
stl->storage->is_render = DRW_state_is_image_render();
@@ -546,11 +591,42 @@ void GPENCIL_cache_init(void *vedata)
}
/* grid pass */
- if (v3d) {
+ if ((v3d) && (obact) && (obact->type == OB_GPENCIL)) {
psl->grid_pass = DRW_pass_create("GPencil Grid Pass",
DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
stl->g_data->shgrps_grid = DRW_shgroup_create(e_data.gpencil_line_sh, psl->grid_pass);
+
+ /* define grid orientation */
+ switch (ts->gp_sculpt.lock_axis) {
+ case GP_LOCKAXIS_VIEW: {
+ /* align always to view */
+ invert_m4_m4(stl->storage->grid_matrix, draw_ctx->rv3d->viewmat);
+ /* copy ob location */
+ copy_v3_v3(stl->storage->grid_matrix[3], obact->obmat[3]);
+ break;
+ }
+ case GP_LOCKAXIS_CURSOR: {
+ float scale[3] = {1.0f, 1.0f, 1.0f};
+ loc_eul_size_to_mat4(
+ stl->storage->grid_matrix, cursor->location, cursor->rotation_euler, scale);
+ break;
+ }
+ default: {
+ copy_m4_m4(stl->storage->grid_matrix, obact->obmat);
+ break;
+ }
+ }
+
+ /* Move the origin to Object or Cursor */
+ if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
+ copy_v3_v3(stl->storage->grid_matrix[3], cursor->location);
+ }
+ else {
+ copy_v3_v3(stl->storage->grid_matrix[3], obact->obmat[3]);
+ }
+ DRW_shgroup_uniform_mat4(
+ stl->g_data->shgrps_grid, "gpModelMatrix", stl->storage->grid_matrix);
}
/* blend layers pass */
@@ -633,8 +709,6 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
Scene *scene = draw_ctx->scene;
ToolSettings *ts = scene->toolsettings;
View3D *v3d = draw_ctx->v3d;
- const View3DCursor *cursor = &scene->cursor;
- float grid_matrix[4][4];
if (ob->type == OB_GPENCIL && ob->data) {
bGPdata *gpd = (bGPdata *)ob->data;
@@ -695,36 +769,7 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) == 0)) {
stl->g_data->batch_grid = gpencil_get_grid(ob);
-
- /* define grid orientation */
- switch (ts->gp_sculpt.lock_axis) {
- case GP_LOCKAXIS_VIEW: {
- /* align always to view */
- invert_m4_m4(grid_matrix, draw_ctx->rv3d->viewmat);
- /* copy ob location */
- copy_v3_v3(grid_matrix[3], ob->obmat[3]);
- break;
- }
- case GP_LOCKAXIS_CURSOR: {
- float scale[3] = {1.0f, 1.0f, 1.0f};
- loc_eul_size_to_mat4(grid_matrix, cursor->location, cursor->rotation_euler, scale);
- break;
- }
- default: {
- copy_m4_m4(grid_matrix, ob->obmat);
- break;
- }
- }
-
- /* Move the origin to Object or Cursor */
- if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
- copy_v3_v3(grid_matrix[3], cursor->location);
- }
- else {
- copy_v3_v3(grid_matrix[3], ob->obmat[3]);
- }
-
- DRW_shgroup_call_obmat(stl->g_data->shgrps_grid, stl->g_data->batch_grid, grid_matrix);
+ DRW_shgroup_call(stl->g_data->shgrps_grid, stl->g_data->batch_grid, NULL);
}
}
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index c475c343d22..5638639cbf2 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -145,6 +145,8 @@ typedef struct GPENCIL_Storage {
bool is_playing;
bool is_render;
bool is_mat_preview;
+ bool is_main_overlay;
+ bool is_main_onion;
bool background_ready;
int is_xray;
bool is_ontop;
@@ -155,6 +157,7 @@ typedef struct GPENCIL_Storage {
int do_select_outline;
float select_color[4];
short multisamples;
+ float grid_matrix[4][4];
short framebuffer_flag; /* flag what framebuffer need to create */
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index 15522ba0dfb..2e8b952f234 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -78,7 +78,6 @@ static struct {
struct GPUTexture *object_id_tx; /* ref only, not alloced */
struct GPUTexture *color_buffer_tx; /* ref only, not alloced */
struct GPUTexture *cavity_buffer_tx; /* ref only, not alloced */
- struct GPUTexture *metallic_buffer_tx; /* ref only, not alloced */
struct GPUTexture *normal_buffer_tx; /* ref only, not alloced */
struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */
diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c
index ac27ff0b736..941a6741998 100644
--- a/source/blender/draw/engines/workbench/workbench_studiolight.c
+++ b/source/blender/draw/engines/workbench/workbench_studiolight.c
@@ -131,7 +131,7 @@ void studiolight_update_world(WORKBENCH_PrivateData *wpd,
static void compute_parallel_lines_nor_and_dist(const float v1[2],
const float v2[2],
const float v3[2],
- float r_line[2])
+ float r_line[4])
{
sub_v2_v2v2(r_line, v2, v1);
/* Find orthogonal vector. */
diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c
index e017661b6cd..23f0898c138 100644
--- a/source/blender/draw/engines/workbench/workbench_volume.c
+++ b/source/blender/draw/engines/workbench/workbench_volume.c
@@ -46,8 +46,6 @@ enum {
static struct {
struct GPUShader *volume_sh[VOLUME_SH_MAX];
struct GPUShader *volume_coba_sh;
- struct GPUShader *volume_slice_sh;
- struct GPUShader *volume_slice_coba_sh;
struct GPUTexture *dummy_tex;
struct GPUTexture *dummy_coba_tex;
} e_data = {{NULL}};
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index 865cfea14e3..5cd6a4a1286 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -60,7 +60,6 @@ static struct {
Object *ob;
/* Reset when changing current_armature */
DRWCallBuffer *bone_octahedral_solid;
- DRWCallBuffer *bone_octahedral_wire;
DRWCallBuffer *bone_octahedral_outline;
DRWCallBuffer *bone_box_solid;
DRWCallBuffer *bone_box_wire;
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 019098e5b90..b085d402e81 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -53,7 +53,6 @@ static struct DRWShapeCache {
GPUBatch *drw_cursor;
GPUBatch *drw_cursor_only_circle;
GPUBatch *drw_fullscreen_quad;
- GPUBatch *drw_fullscreen_quad_texcoord;
GPUBatch *drw_quad;
GPUBatch *drw_quad_wires;
GPUBatch *drw_grid;
@@ -72,8 +71,6 @@ static struct DRWShapeCache {
GPUBatch *drw_empty_capsule_body;
GPUBatch *drw_empty_capsule_cap;
GPUBatch *drw_empty_cone;
- GPUBatch *drw_arrows;
- GPUBatch *drw_axis_names;
GPUBatch *drw_image_plane;
GPUBatch *drw_image_plane_wire;
GPUBatch *drw_field_wind;
@@ -99,7 +96,6 @@ static struct DRWShapeCache {
GPUBatch *drw_bone_octahedral_wire;
GPUBatch *drw_bone_box;
GPUBatch *drw_bone_box_wire;
- GPUBatch *drw_bone_wire_wire;
GPUBatch *drw_bone_envelope;
GPUBatch *drw_bone_envelope_outline;
GPUBatch *drw_bone_point;
@@ -111,7 +107,6 @@ static struct DRWShapeCache {
GPUBatch *drw_camera;
GPUBatch *drw_camera_frame;
GPUBatch *drw_camera_tria;
- GPUBatch *drw_camera_focus;
GPUBatch *drw_particle_cross;
GPUBatch *drw_particle_circle;
GPUBatch *drw_particle_axis;
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h
index 75b8d820884..46193e255b5 100644
--- a/source/blender/draw/intern/draw_cache_extract.h
+++ b/source/blender/draw/intern/draw_cache_extract.h
@@ -48,6 +48,9 @@ typedef struct DRW_MeshCDMask {
uint32_t vcol : 8;
uint32_t orco : 1;
uint32_t tan_orco : 1;
+ /** Edit uv layer is from the base edit mesh as
+ * modifiers could remove it. (see T68857) */
+ uint32_t edit_uv : 1;
} DRW_MeshCDMask;
typedef enum eMRIterType {
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c
index 40a36acc3d9..2ac97196b99 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.c
@@ -1601,6 +1601,14 @@ static void *extract_uv_init(const MeshRenderData *mr, void *buf)
CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
uint32_t uv_layers = mr->cache->cd_used.uv;
+ /* HACK to fix T68857 */
+ if (mr->extract_type == MR_EXTRACT_BMESH && mr->cache->cd_used.edit_uv == 1) {
+ int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ if (layer != -1) {
+ uv_layers |= (1 << layer);
+ }
+ }
+
for (int i = 0; i < MAX_MTFACE; i++) {
if (uv_layers & (1 << i)) {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME];
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 4a69aa3e008..b8b657354b2 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -90,9 +90,15 @@ BLI_INLINE void mesh_cd_layers_type_clear(DRW_MeshCDMask *a)
*((uint32_t *)a) = 0;
}
+static void mesh_cd_calc_edit_uv_layer(const Mesh *UNUSED(me), DRW_MeshCDMask *cd_used)
+{
+ cd_used->edit_uv = 1;
+}
+
static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
- const CustomData *cd_ldata = (me->edit_mesh) ? &me->edit_mesh->bm->ldata : &me->ldata;
+ const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
+ const CustomData *cd_ldata = &me_final->ldata;
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
if (layer != -1) {
@@ -102,7 +108,8 @@ static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used
static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
- const CustomData *cd_ldata = (me->edit_mesh) ? &me->edit_mesh->bm->ldata : &me->ldata;
+ const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
+ const CustomData *cd_ldata = &me_final->ldata;
int layer = CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV);
if (layer != -1) {
@@ -112,7 +119,8 @@ static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd
static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
- const CustomData *cd_ldata = (me->edit_mesh) ? &me->edit_mesh->bm->ldata : &me->ldata;
+ const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
+ const CustomData *cd_ldata = &me_final->ldata;
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
if (layer != -1) {
@@ -124,7 +132,8 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
struct GPUMaterial **gpumat_array,
int gpumat_array_len)
{
- const CustomData *cd_ldata = (me->edit_mesh) ? &me->edit_mesh->bm->ldata : &me->ldata;
+ const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
+ const CustomData *cd_ldata = &me_final->ldata;
/* See: DM_vertex_attributes_from_gpu for similar logic */
DRW_MeshCDMask cd_used;
@@ -227,7 +236,8 @@ static void mesh_cd_extract_auto_layers_names_and_srgb(Mesh *me,
int **r_auto_layers_srgb,
int *r_auto_layers_len)
{
- const CustomData *cd_ldata = (me->edit_mesh) ? &me->edit_mesh->bm->ldata : &me->ldata;
+ const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
+ const CustomData *cd_ldata = &me_final->ldata;
int uv_len_used = count_bits_i(cd_used.uv);
int vcol_len_used = count_bits_i(cd_used.vcol);
@@ -458,6 +468,16 @@ static void mesh_batch_cache_check_vertex_group(MeshBatchCache *cache,
}
}
+static void mesh_batch_cache_discard_shaded_batches(MeshBatchCache *cache)
+{
+ if (cache->surface_per_mat) {
+ for (int i = 0; i < cache->mat_len; i++) {
+ GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]);
+ }
+ }
+ cache->batch_ready &= ~MBC_SURF_PER_MAT;
+}
+
static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache)
{
FOREACH_MESH_BUFFER_CACHE(cache, mbufcache)
@@ -468,21 +488,13 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache)
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.vcol);
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.orco);
}
+ mesh_batch_cache_discard_shaded_batches(cache);
+ mesh_cd_layers_type_clear(&cache->cd_used);
- if (cache->surface_per_mat) {
- for (int i = 0; i < cache->mat_len; i++) {
- GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]);
- }
- }
MEM_SAFE_FREE(cache->surface_per_mat);
-
- cache->batch_ready &= ~MBC_SURF_PER_MAT;
-
MEM_SAFE_FREE(cache->auto_layer_names);
MEM_SAFE_FREE(cache->auto_layer_is_srgb);
- mesh_cd_layers_type_clear(&cache->cd_used);
-
cache->mat_len = 0;
}
@@ -513,6 +525,37 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
cache->tot_uv_area = 0.0f;
cache->batch_ready &= ~MBC_EDITUV;
+
+ /* We discarded the vbo.uv so we need to reset the cd_used flag. */
+ cache->cd_used.uv = 0;
+ cache->cd_used.edit_uv = 0;
+
+ /* Discard other batches that uses vbo.uv */
+ mesh_batch_cache_discard_shaded_batches(cache);
+
+ GPU_BATCH_DISCARD_SAFE(cache->batch.surface);
+ cache->batch_ready &= ~MBC_SURFACE;
+}
+
+static void mesh_batch_cache_discard_uvedit_select(MeshBatchCache *cache)
+{
+ FOREACH_MESH_BUFFER_CACHE(cache, mbufcache)
+ {
+ GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_data);
+ GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_edituv_data);
+ GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_tris);
+ GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_lines);
+ GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_points);
+ GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_fdots);
+ }
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_area);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_angle);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_edges);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_verts);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_fdots);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops_uvs);
+ cache->batch_ready &= ~MBC_EDITUV;
}
void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
@@ -541,8 +584,8 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
MBC_EDIT_FACEDOTS | MBC_EDIT_SELECTION_FACEDOTS |
MBC_EDIT_SELECTION_FACES | MBC_EDIT_SELECTION_EDGES |
MBC_EDIT_SELECTION_VERTS | MBC_EDIT_MESH_ANALYSIS);
- /* Because visible UVs depends on edit mode selection, discard everything. */
- mesh_batch_cache_discard_uvedit(cache);
+ /* Because visible UVs depends on edit mode selection, discard topology. */
+ mesh_batch_cache_discard_uvedit_select(cache);
break;
case BKE_MESH_BATCH_DIRTY_SELECT_PAINT:
/* Paint mode selection flag is packed inside the nor attrib.
@@ -876,6 +919,19 @@ GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me)
/** \name UV Image editor API
* \{ */
+static void edituv_request_active_uv(MeshBatchCache *cache, Mesh *me)
+{
+ DRW_MeshCDMask cd_needed;
+ mesh_cd_layers_type_clear(&cd_needed);
+ mesh_cd_calc_edit_uv_layer(me, &cd_needed);
+
+ BLI_assert(cd_needed.edit_uv != 0 &&
+ "No uv layer available in edituv, but batches requested anyway!");
+
+ mesh_cd_calc_active_mask_uv_layer(me, &cd_needed);
+ mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed);
+}
+
/* Creates the GPUBatch for drawing the UV Stretching Area Overlay.
* Optional retrieves the total area or total uv area of the mesh.
*
@@ -886,7 +942,7 @@ GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_area(Mesh *me,
float **tot_uv_area)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- texpaint_request_active_uv(cache, me);
+ edituv_request_active_uv(cache, me);
mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRETCH_AREA);
if (tot_area != NULL) {
@@ -901,7 +957,7 @@ GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_area(Mesh *me,
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- texpaint_request_active_uv(cache, me);
+ edituv_request_active_uv(cache, me);
mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRETCH_ANGLE);
return DRW_batch_request(&cache->batch.edituv_faces_stretch_angle);
}
@@ -909,7 +965,7 @@ GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(Mesh *me)
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- texpaint_request_active_uv(cache, me);
+ edituv_request_active_uv(cache, me);
mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES);
return DRW_batch_request(&cache->batch.edituv_faces);
}
@@ -917,7 +973,7 @@ GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(Mesh *me)
GPUBatch *DRW_mesh_batch_cache_get_edituv_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- texpaint_request_active_uv(cache, me);
+ edituv_request_active_uv(cache, me);
mesh_batch_cache_add_request(cache, MBC_EDITUV_EDGES);
return DRW_batch_request(&cache->batch.edituv_edges);
}
@@ -925,7 +981,7 @@ GPUBatch *DRW_mesh_batch_cache_get_edituv_edges(Mesh *me)
GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- texpaint_request_active_uv(cache, me);
+ edituv_request_active_uv(cache, me);
mesh_batch_cache_add_request(cache, MBC_EDITUV_VERTS);
return DRW_batch_request(&cache->batch.edituv_verts);
}
@@ -933,7 +989,7 @@ GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(Mesh *me)
GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- texpaint_request_active_uv(cache, me);
+ edituv_request_active_uv(cache, me);
mesh_batch_cache_add_request(cache, MBC_EDITUV_FACEDOTS);
return DRW_batch_request(&cache->batch.edituv_fdots);
}
@@ -941,7 +997,7 @@ GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(Mesh *me)
GPUBatch *DRW_mesh_batch_cache_get_uv_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- texpaint_request_active_uv(cache, me);
+ edituv_request_active_uv(cache, me);
mesh_batch_cache_add_request(cache, MBC_WIRE_LOOPS_UVS);
return DRW_batch_request(&cache->batch.wire_loops_uvs);
}
@@ -1108,9 +1164,6 @@ void DRW_mesh_batch_cache_create_requested(
FOREACH_MESH_BUFFER_CACHE(cache, mbuffercache)
{
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.edituv_data);
- GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.stretch_angle);
- GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.stretch_area);
- GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.uv);
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.fdots_uv);
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_tris);
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_lines);
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index 7f679dd5581..988859c64a5 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -277,7 +277,6 @@ static struct {
struct GPUVertFormat *instance_scaled;
struct GPUVertFormat *instance_sized;
struct GPUVertFormat *instance_outline;
- struct GPUVertFormat *instance;
struct GPUVertFormat *instance_camera;
struct GPUVertFormat *instance_distance_lines;
struct GPUVertFormat *instance_spot;
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 6387cecc01f..9e28627ba3d 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -164,7 +164,7 @@ struct DRWTextStore *DRW_text_cache_ensure(void)
bool DRW_object_is_renderable(const Object *ob)
{
- BLI_assert((ob->base_flag & BASE_VISIBLE) != 0);
+ BLI_assert((ob->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0);
if (ob->type == OB_MESH) {
if ((ob == DST.draw_ctx.object_edit) || BKE_object_is_in_editmode(ob)) {
@@ -1171,7 +1171,7 @@ static void drw_engines_cache_finish(void)
MEM_freeN(DST.vedata_array);
}
-static void drw_engines_draw_background(void)
+static bool drw_engines_draw_background(void)
{
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
@@ -1185,10 +1185,20 @@ static void drw_engines_draw_background(void)
DRW_stats_group_end();
PROFILE_END_UPDATE(data->background_time, stime);
- return;
+ return true;
}
}
+ /* No draw engines draw the background. We clear the background.
+ * We draw the background after drawing of the scene so the camera background
+ * images can be drawn using ALPHA Under. Otherwise the background always
+ * interfered with the alpha blending. */
+ DRW_clear_background();
+ return false;
+}
+
+static void drw_draw_background_alpha_under(void)
+{
/* No draw_background found, doing default background */
const bool do_alpha_checker = !DRW_state_draw_background();
DRW_draw_background(do_alpha_checker);
@@ -1565,20 +1575,6 @@ void DRW_draw_view(const bContext *C)
DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C);
}
-static bool is_object_visible_in_viewport(View3D *v3d, Object *ob)
-{
- if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
- return false;
- }
-
- if ((v3d->flag & V3D_LOCAL_COLLECTIONS) &&
- ((v3d->local_collections_uuid & ob->runtime.local_collections_bits) == 0)) {
- return false;
- }
-
- return true;
-}
-
/**
* Used for both regular and off-screen drawing.
* Need to reset DST before calling this function
@@ -1654,7 +1650,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
continue;
}
- if (!is_object_visible_in_viewport(v3d, ob)) {
+ if (!BKE_object_is_visible_in_viewport(v3d, ob)) {
continue;
}
DST.dupli_parent = data_.dupli_parent;
@@ -1685,7 +1681,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
DRW_hair_update();
- drw_engines_draw_background();
+ const bool background_drawn = drw_engines_draw_background();
GPU_framebuffer_bind(DST.default_framebuffer);
@@ -1696,6 +1692,10 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
drw_engines_draw_scene();
+ if (!background_drawn) {
+ drw_draw_background_alpha_under();
+ }
+
/* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */
GPU_flush();
@@ -2350,7 +2350,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
v3d->object_type_exclude_select);
bool filter_exclude = false;
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
- if (!is_object_visible_in_viewport(v3d, ob)) {
+ if (!BKE_object_is_visible_in_viewport(v3d, ob)) {
continue;
}
if ((ob->base_flag & BASE_SELECTABLE) &&
@@ -2500,7 +2500,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph,
if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
continue;
}
- if (!is_object_visible_in_viewport(v3d, ob)) {
+ if (!BKE_object_is_visible_in_viewport(v3d, ob)) {
continue;
}
DST.dupli_parent = data_.dupli_parent;
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index dcf526679bf..330f72eda18 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -1846,11 +1846,6 @@ void DRW_pass_foreach_shgroup(DRWPass *pass,
}
}
-typedef struct ZSortData {
- const float *axis;
- const float *origin;
-} ZSortData;
-
static int pass_shgroup_dist_sort(const void *a, const void *b)
{
const DRWShadingGroup *shgrp_a = (const DRWShadingGroup *)a;
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 3de9ce74dbc..fa7c44c1b1f 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -29,6 +29,7 @@
#include "BKE_global.h"
#include "GPU_extensions.h"
+#include "GPU_platform.h"
#include "intern/gpu_shader_private.h"
#include "intern/gpu_primitive_private.h"
diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c
index 7aa2e007f79..58643eb12a8 100644
--- a/source/blender/draw/intern/draw_view.c
+++ b/source/blender/draw/intern/draw_view.c
@@ -41,11 +41,9 @@
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "DRW_render.h"
-
#include "view3d_intern.h"
-#include "draw_view.h"
+#include "draw_manager.h"
/* ******************** region info ***************** */
@@ -60,18 +58,17 @@ void DRW_draw_region_info(void)
}
/* ************************* Background ************************** */
+void DRW_clear_background()
+{
+ GPU_clear_color(0.0, 0.0, 0.0, 0.0);
+ GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT);
+}
void DRW_draw_background(bool do_alpha_checker)
{
- /* Just to make sure */
- glDepthMask(GL_TRUE);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilMask(0xFF);
-
+ drw_state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_UNDER_PREMUL);
if (do_alpha_checker) {
/* Transparent render, do alpha checker. */
- GPU_depth_test(false);
-
GPU_matrix_push();
GPU_matrix_identity_set();
GPU_matrix_identity_projection_set();
@@ -79,18 +76,11 @@ void DRW_draw_background(bool do_alpha_checker)
imm_draw_box_checker_2d(-1.0f, -1.0f, 1.0f, 1.0f);
GPU_matrix_pop();
-
- GPU_clear(GPU_DEPTH_BIT | GPU_STENCIL_BIT);
-
- GPU_depth_test(true);
}
- else if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+ else {
float m[4][4];
unit_m4(m);
- /* Gradient background Color */
- GPU_depth_test(false);
-
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
uint color = GPU_vertformat_attr_add(
@@ -103,8 +93,8 @@ void DRW_draw_background(bool do_alpha_checker)
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR_DITHER);
- UI_GetThemeColor3ubv(TH_BACK_GRAD, col_lo);
UI_GetThemeColor3ubv(TH_BACK, col_hi);
+ UI_GetThemeColor3ubv(UI_GetThemeValue(TH_SHOW_BACK_GRAD) ? TH_BACK_GRAD : TH_BACK, col_lo);
immBegin(GPU_PRIM_TRI_FAN, 4);
immAttr3ubv(color, col_lo);
@@ -119,16 +109,6 @@ void DRW_draw_background(bool do_alpha_checker)
immUnbindProgram();
GPU_matrix_pop();
-
- GPU_clear(GPU_DEPTH_BIT | GPU_STENCIL_BIT);
-
- GPU_depth_test(true);
- }
- else {
- /* Solid background Color */
- UI_ThemeClearColorAlpha(TH_BACK, 1.0f);
-
- GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT);
}
}
diff --git a/source/blender/draw/intern/draw_view.h b/source/blender/draw/intern/draw_view.h
index 715c3c0d40c..7be186f1c72 100644
--- a/source/blender/draw/intern/draw_view.h
+++ b/source/blender/draw/intern/draw_view.h
@@ -24,6 +24,7 @@
#define __DRAW_VIEW_H__
void DRW_draw_region_info(void);
+void DRW_clear_background(void);
void DRW_draw_background(bool do_alpha_checker);
void DRW_draw_cursor(void);
void DRW_draw_gizmo_3d(void);
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index 05a915185df..21e1dff7128 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -122,8 +122,9 @@ typedef struct OBJECT_PassList {
struct DRWPass *bone_axes[2];
struct DRWPass *particle;
struct DRWPass *lightprobes;
- struct DRWPass *camera_images_back;
- struct DRWPass *camera_images_front;
+ struct DRWPass *camera_images_back_alpha_under;
+ struct DRWPass *camera_images_back_alpha_over;
+ struct DRWPass *camera_images_front_alpha_over;
} OBJECT_PassList;
typedef struct OBJECT_FramebufferList {
@@ -991,13 +992,19 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data,
}
}
-/* Draw Camera Background Images */
+/* -------------------------------------------------------------------- */
+/** \name Camera Background Images
+ * \{ */
typedef struct CameraEngineData {
DrawData dd;
ListBase bg_data;
} CameraEngineData;
+
typedef struct CameraEngineBGData {
+ CameraBGImage *camera_image;
+ GPUTexture *texture;
float transform_mat[4][4];
+ bool premultiplied;
} CameraEngineBGData;
static void camera_engine_data_free(DrawData *dd)
@@ -1032,6 +1039,26 @@ static void camera_background_images_stereo_setup(Scene *scene,
iuser->flag &= ~IMA_SHOW_STEREO;
}
}
+static void camera_background_images_add_shgroup(DRWPass *pass,
+ CameraEngineBGData *bg_data,
+ GPUShader *shader,
+ GPUBatch *batch)
+{
+ CameraBGImage *camera_image = bg_data->camera_image;
+ DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
+
+ DRW_shgroup_uniform_float_copy(
+ grp, "depth", camera_image->flag & CAM_BGIMG_FLAG_FOREGROUND ? 0.000001f : 0.999999f);
+ DRW_shgroup_uniform_float_copy(grp, "alpha", camera_image->alpha);
+ DRW_shgroup_uniform_texture(grp, "image", bg_data->texture);
+ DRW_shgroup_uniform_bool_copy(grp, "imagePremultiplied", bg_data->premultiplied);
+ DRW_shgroup_uniform_float_copy(
+ grp, "flipX", (camera_image->flag & CAM_BGIMG_FLAG_FLIP_X) ? -1.0 : 1.0);
+ DRW_shgroup_uniform_float_copy(
+ grp, "flipY", (camera_image->flag & CAM_BGIMG_FLAG_FLIP_Y) ? -1.0 : 1.0);
+ DRW_shgroup_uniform_mat4(grp, "TransformMat", bg_data->transform_mat);
+ DRW_shgroup_call(grp, batch, NULL);
+}
static void DRW_shgroup_camera_background_images(OBJECT_Shaders *sh_data,
OBJECT_PassList *psl,
@@ -1255,25 +1282,46 @@ static void DRW_shgroup_camera_background_images(OBJECT_Shaders *sh_data,
scale_m4,
uv2img_space);
- DRWPass *pass = (bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) ? psl->camera_images_front :
- psl->camera_images_back;
- GPUShader *shader = DRW_state_do_color_management() ? sh_data->object_camera_image_cm :
- sh_data->object_camera_image;
- DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
+ /* Keep the references so we can reverse the loop */
+ bg_data->camera_image = bgpic;
+ bg_data->texture = tex;
+ bg_data->premultiplied = premultiplied;
+ }
- DRW_shgroup_uniform_float_copy(
- grp, "depth", (bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) ? 0.000001 : 0.999999);
- DRW_shgroup_uniform_float_copy(grp, "alpha", bgpic->alpha);
- DRW_shgroup_uniform_texture(grp, "image", tex);
- DRW_shgroup_uniform_bool_copy(grp, "imagePremultiplied", premultiplied);
+ /* Mark the rest bg_data's to be reused in the next drawing call */
+ LinkData *last_node = list_node ? list_node->prev : camera_engine_data->bg_data.last;
+ while (list_node != NULL) {
+ CameraEngineBGData *bg_data = (CameraEngineBGData *)list_node->data;
+ bg_data->texture = NULL;
+ bg_data->camera_image = NULL;
+ list_node = list_node->next;
+ }
- DRW_shgroup_uniform_float_copy(
- grp, "flipX", (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) ? -1.0 : 1.0);
- DRW_shgroup_uniform_float_copy(
- grp, "flipY", (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) ? -1.0 : 1.0);
- DRW_shgroup_uniform_mat4(grp, "TransformMat", bg_data->transform_mat);
+ GPUShader *shader = DRW_state_do_color_management() ? sh_data->object_camera_image_cm :
+ sh_data->object_camera_image;
+ /* loop 1: camera images alpha under */
+ for (list_node = last_node; list_node; list_node = list_node->prev) {
+ CameraEngineBGData *bg_data = (CameraEngineBGData *)list_node->data;
+ CameraBGImage *camera_image = bg_data->camera_image;
+ if ((camera_image->flag & CAM_BGIMG_FLAG_FOREGROUND) == 0) {
+ camera_background_images_add_shgroup(
+ psl->camera_images_back_alpha_under, bg_data, shader, batch);
+ }
+ }
- DRW_shgroup_call(grp, batch, NULL);
+ /* loop 2: camera images alpha over */
+ for (list_node = camera_engine_data->bg_data.first; list_node; list_node = list_node->next) {
+ CameraEngineBGData *bg_data = (CameraEngineBGData *)list_node->data;
+ CameraBGImage *camera_image = bg_data->camera_image;
+ if (camera_image == NULL) {
+ break;
+ }
+ camera_background_images_add_shgroup((camera_image->flag & CAM_BGIMG_FLAG_FOREGROUND) ?
+ psl->camera_images_front_alpha_over :
+ psl->camera_images_back_alpha_over,
+ bg_data,
+ shader,
+ batch);
}
}
}
@@ -1286,6 +1334,7 @@ static void camera_background_images_free_textures(void)
}
BLI_freelistN(&e_data.movie_clips);
}
+/* \} */
static void OBJECT_cache_init(void *vedata)
{
@@ -1427,9 +1476,15 @@ static void OBJECT_cache_init(void *vedata)
/* Camera background images */
{
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA;
- psl->camera_images_back = DRW_pass_create("Camera Images Back", state);
- psl->camera_images_front = DRW_pass_create("Camera Images Front", state);
+ psl->camera_images_back_alpha_over = DRW_pass_create(
+ "Camera Images Back Over",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA_PREMUL);
+ psl->camera_images_back_alpha_under = DRW_pass_create(
+ "Camera Images Back Under",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER | DRW_STATE_BLEND_ALPHA_UNDER_PREMUL);
+ psl->camera_images_front_alpha_over = DRW_pass_create(
+ "Camera Images Front Over",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA_PREMUL);
}
for (int i = 0; i < 2; i++) {
@@ -3486,6 +3541,10 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
if (hide_object_extra) {
break;
}
+ if ((ob->base_flag & BASE_FROM_DUPLI) && (ob->transflag & OB_DUPLICOLLECTION) &&
+ ob->instance_collection) {
+ break;
+ }
DRW_shgroup_empty(sh_data, sgl, ob, view_layer, rv3d, draw_ctx->sh_cfg);
break;
case OB_SPEAKER:
@@ -3666,7 +3725,8 @@ static void OBJECT_draw_scene(void *vedata)
float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- DRW_draw_pass(psl->camera_images_back);
+ DRW_draw_pass(psl->camera_images_back_alpha_under);
+ DRW_draw_pass(psl->camera_images_back_alpha_over);
/* Don't draw Transparent passes in MSAA buffer. */
// DRW_draw_pass(psl->bone_envelope); /* Never drawn in Object mode currently. */
@@ -3774,7 +3834,7 @@ static void OBJECT_draw_scene(void *vedata)
batch_camera_path_free(&stl->g_data->sgl_ghost.camera_path);
- DRW_draw_pass(psl->camera_images_front);
+ DRW_draw_pass(psl->camera_images_front_alpha_over);
camera_background_images_free_textures();
DRW_draw_pass(psl->ob_center);
diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c
index 1b196cd8bb7..9749619cffe 100644
--- a/source/blender/draw/modes/sculpt_mode.c
+++ b/source/blender/draw/modes/sculpt_mode.c
@@ -156,7 +156,8 @@ static void SCULPT_cache_populate(void *vedata, Object *ob)
const DRWContextState *draw_ctx = DRW_context_state_get();
if ((ob == draw_ctx->obact) &&
- (BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) || !ob->sculpt->modifiers_active)) {
+ (BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) ||
+ ob->sculpt->deform_modifiers_active || ob->sculpt->shapekey_active)) {
PBVH *pbvh = ob->sculpt->pbvh;
if (pbvh && pbvh_has_mask(pbvh)) {
DRW_shgroup_call_sculpt(stl->g_data->mask_overlay_grp, ob, false, true, false);
diff --git a/source/blender/draw/modes/shaders/object_camera_image_frag.glsl b/source/blender/draw/modes/shaders/object_camera_image_frag.glsl
index 5d8ad3c79ea..7804ebdb8c9 100644
--- a/source/blender/draw/modes/shaders/object_camera_image_frag.glsl
+++ b/source/blender/draw/modes/shaders/object_camera_image_frag.glsl
@@ -19,5 +19,7 @@ void main()
#endif
color.a *= alpha;
+ color.rgb *= color.a;
+
fragColor = color;
}
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index d80b96f0d74..8951677b32f 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -3411,7 +3411,7 @@ static void acf_nlatrack_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, flo
}
/* set color for nla track */
- UI_GetThemeColorShade3fv(TH_HEADER, ((nonSolo == false) ? 20 : -20), r_color);
+ UI_GetThemeColorShade3fv(TH_NLA_TRACK, ((nonSolo == false) ? 20 : -20), r_color);
}
/* name for nla track entries */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 48493c9e961..f73c8a5b71a 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -1818,7 +1818,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac,
!(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
/* Layer visibility - we check both object and base,
* since these may not be in sync yet. */
- if ((base->flag & BASE_VISIBLE) == 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
continue;
}
@@ -3017,7 +3017,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m
*/
if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
/* layer visibility - we check both object and base, since these may not be in sync yet */
- if ((base->flag & BASE_VISIBLE) == 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
return false;
}
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 2a35acdefcb..36583ecf060 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -1148,33 +1148,48 @@ static void deselect_markers(ListBase *markers)
}
/* select/deselect TimeMarker at current frame */
-static void select_timeline_marker_frame(ListBase *markers, int frame, bool extend)
+static int select_timeline_marker_frame(ListBase *markers,
+ int frame,
+ bool extend,
+ bool wait_to_deselect_others)
{
- TimeMarker *marker, *marker_first = NULL;
+ TimeMarker *marker, *marker_selected = NULL;
+ int ret_val = OPERATOR_FINISHED;
+
+ if (extend) {
+ wait_to_deselect_others = false;
+ }
/* support for selection cycling */
for (marker = markers->first; marker; marker = marker->next) {
if (marker->frame == frame) {
if (marker->flag & SELECT) {
- marker_first = marker->next;
+ marker_selected = marker->next;
break;
}
}
}
- /* if extend is not set, then deselect markers */
- if (extend == false) {
- deselect_markers(markers);
+ if (wait_to_deselect_others && marker_selected) {
+ ret_val = OPERATOR_RUNNING_MODAL;
}
+ /* if extend is not set, then deselect markers */
+ else {
+ if (extend == false) {
+ deselect_markers(markers);
+ }
- LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_first) {
- /* this way a not-extend select will always give 1 selected marker */
- if (marker->frame == frame) {
- marker->flag ^= SELECT;
- break;
+ LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_selected) {
+ /* this way a not-extend select will always give 1 selected marker */
+ if (marker->frame == frame) {
+ marker->flag ^= SELECT;
+ break;
+ }
}
+ LISTBASE_CIRCULAR_FORWARD_END(markers, marker, marker_selected);
}
- LISTBASE_CIRCULAR_FORWARD_END(markers, marker, marker_first);
+
+ return ret_val;
}
static void select_marker_camera_switch(
@@ -1221,17 +1236,17 @@ static void select_marker_camera_switch(
#endif
}
-static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool camera)
+static int ed_marker_select(
+ bContext *C, const int mval[2], bool extend, bool camera, bool wait_to_deselect_others)
{
ListBase *markers = ED_context_get_markers(C);
- ARegion *ar = CTX_wm_region(C);
View2D *v2d = UI_view2d_fromcontext(C);
+ int ret_val = OPERATOR_FINISHED;
- float mouse_region_x = event->x - ar->winrct.xmin;
- if (region_position_is_over_marker(v2d, markers, mouse_region_x)) {
- float frame_at_mouse_position = UI_view2d_region_to_view_x(v2d, mouse_region_x);
+ if (region_position_is_over_marker(v2d, markers, mval[0])) {
+ float frame_at_mouse_position = UI_view2d_region_to_view_x(v2d, mval[0]);
int cfra = ED_markers_find_nearest_marker_time(markers, frame_at_mouse_position);
- select_timeline_marker_frame(markers, cfra, extend);
+ ret_val = select_timeline_marker_frame(markers, cfra, extend, wait_to_deselect_others);
select_marker_camera_switch(C, camera, extend, markers, cfra);
}
@@ -1243,17 +1258,22 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool
WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
/* allowing tweaks, but needs OPERATOR_FINISHED, otherwise renaming fails... [#25987] */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ return ret_val | OPERATOR_PASS_THROUGH;
}
-static int ed_marker_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int ed_marker_select_exec(bContext *C, wmOperator *op)
{
const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
bool camera = false;
#ifdef DURIAN_CAMERA_SWITCH
camera = RNA_boolean_get(op->ptr, "camera");
#endif
- return ed_marker_select(C, event, extend, camera);
+ int mval[2];
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
+
+ return ed_marker_select(C, mval, extend, camera, wait_to_deselect_others);
}
static void MARKER_OT_select(wmOperatorType *ot)
@@ -1266,12 +1286,15 @@ static void MARKER_OT_select(wmOperatorType *ot)
ot->idname = "MARKER_OT_select";
/* api callbacks */
- ot->invoke = ed_marker_select_invoke;
ot->poll = ed_markers_poll_markers_exist;
+ ot->exec = ed_marker_select_exec;
+ ot->invoke = WM_generic_select_invoke;
+ ot->modal = WM_generic_select_modal;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ WM_operator_properties_generic_select(ot);
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
#ifdef DURIAN_CAMERA_SWITCH
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 61c8da08954..64f7fe034dc 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -111,7 +111,7 @@ struct FCurve *alloc_driver_fcurve(const char rna_path[],
FCurve *fcu = MEM_callocN(sizeof(FCurve), "FCurve");
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
- fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+ fcu->auto_smoothing = U.auto_smoothing_new;
/* store path - make copy, and store that */
if (rna_path) {
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index c174ce83bea..479e7192b0e 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -545,8 +545,7 @@ int actkeyblock_get_valid_hold(ActKeyColumn *ac)
return 0;
}
- const int hold_mask = (ACTKEYBLOCK_FLAG_ANY_HOLD | ACTKEYBLOCK_FLAG_STATIC_HOLD |
- ACTKEYBLOCK_FLAG_ANY_HOLD);
+ const int hold_mask = (ACTKEYBLOCK_FLAG_ANY_HOLD | ACTKEYBLOCK_FLAG_STATIC_HOLD);
return (ac->block.flag & ~ac->block.conflict) & hold_mask;
}
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 0f8b8742659..8203a9131fa 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -202,7 +202,7 @@ FCurve *verify_fcurve(Main *bmain,
fcu = MEM_callocN(sizeof(FCurve), "FCurve");
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
- fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+ fcu->auto_smoothing = U.auto_smoothing_new;
if (BLI_listbase_is_empty(&act->curves)) {
fcu->flag |= FCURVE_ACTIVE; /* first one added active */
}
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 616daf94e57..7ed41b5b4d0 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -368,30 +368,14 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, flo
switch (pso->mode) {
case POSESLIDE_PUSH: /* make the current pose more pronounced */
{
- /* perform a weighted average here, favoring the middle pose
- * - numerator should be larger than denominator to 'expand' the result
- * - perform this weighting a number of times given by the percentage...
- */
- /* TODO: maybe a sensitivity ctrl on top of this is needed */
- int iters = (int)ceil(10.0f * pso->percentage);
-
- while (iters-- > 0) {
- (*val) = (-((sVal * w2) + (eVal * w1)) + ((*val) * 6.0f)) / 5.0f;
- }
+ /* Slide the pose away from the breakdown pose in the timeline */
+ (*val) -= ((sVal * w2) + (eVal * w1) - (*val)) * pso->percentage;
break;
}
case POSESLIDE_RELAX: /* make the current pose more like its surrounding ones */
{
- /* perform a weighted average here, favoring the middle pose
- * - numerator should be smaller than denominator to 'relax' the result
- * - perform this weighting a number of times given by the percentage...
- */
- /* TODO: maybe a sensitivity ctrl on top of this is needed */
- int iters = (int)ceil(10.0f * pso->percentage);
-
- while (iters-- > 0) {
- (*val) = (((sVal * w2) + (eVal * w1)) + ((*val) * 5.0f)) / 6.0f;
- }
+ /* Slide the pose towards the breakdown pose in the timeline */
+ (*val) += ((sVal * w2) + (eVal * w1) - (*val)) * pso->percentage;
break;
}
case POSESLIDE_BREAKDOWN: /* make the current pose slide around between the endpoints */
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index 3f6db956643..8d2d7d790d2 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -32,6 +32,7 @@
#include "DNA_scene_types.h"
#include "BKE_action.h"
+#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
@@ -223,6 +224,11 @@ void poseAnim_mapping_refresh(bContext *C, Scene *UNUSED(scene), Object *ob)
{
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ AnimData *adt = BKE_animdata_from_id(&ob->id);
+ if (adt && adt->action) {
+ DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
+ }
}
/* reset changes made to current pose */
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 603b0967ace..e11807d818f 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -1876,6 +1876,7 @@ void ED_curve_editfont_make(Object *obedit)
memcpy(ef->textbufinfo, cu->strinfo, ef->len * sizeof(CharInfo));
+ ef->pos = cu->pos;
if (ef->pos > ef->len) {
ef->pos = ef->len;
}
@@ -1883,7 +1884,6 @@ void ED_curve_editfont_make(Object *obedit)
cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
/* Other vars */
- ef->pos = cu->pos;
ef->selstart = cu->selstart;
ef->selend = cu->selend;
diff --git a/source/blender/editors/gpencil/gpencil_ops_versioning.c b/source/blender/editors/gpencil/gpencil_ops_versioning.c
index af49587f9ad..3d56cb0fcb1 100644
--- a/source/blender/editors/gpencil/gpencil_ops_versioning.c
+++ b/source/blender/editors/gpencil/gpencil_ops_versioning.c
@@ -54,6 +54,9 @@
#include "ED_object.h"
#include "ED_gpencil.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "gpencil_intern.h"
/* Free all of a gp-colors */
@@ -111,6 +114,7 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op)
ob = BKE_object_add_for_data(
bmain, view_layer, OB_GPENCIL, "GP_Scene", &scene->gpd->id, false);
zero_v3(ob->loc);
+ DEG_relations_tag_update(bmain); /* added object */
/* convert grease pencil palettes (version >= 2.78) to materials and weights */
for (const bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 7c3aac6c688..c3e61f5f2b2 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -246,7 +246,8 @@ ScrArea *ED_screen_temp_space_open(struct bContext *C,
int sizex,
int sizey,
eSpace_Type space_type,
- int display_type);
+ int display_type,
+ bool dialog);
void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
void ED_screens_footer_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
void ED_screens_navigation_bar_tools_menu_create(struct bContext *C,
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 76ab4a53eb8..89579b88d24 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -283,6 +283,7 @@ typedef enum ThemeColorID {
TH_NLA_TWEAK, /* 'tweaking' track in NLA */
TH_NLA_TWEAK_DUPLI, /* error/warning flag for other strips referencing dupli strip */
+ TH_NLA_TRACK,
TH_NLA_TRANSITION,
TH_NLA_TRANSITION_SEL,
TH_NLA_META,
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index bc8d25e8d9e..d33023c69a1 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -50,6 +50,7 @@ set(SRC
interface_eyedropper_datablock.c
interface_eyedropper_depth.c
interface_eyedropper_driver.c
+ interface_eyedropper_gpencil_color.c
interface_handlers.c
interface_icons.c
interface_icons_event.c
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index f05100e9065..54fd91e5361 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -786,6 +786,8 @@ static bool ui_but_update_from_old_block(const bContext *C,
oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy);
oldbut->drawflag = (oldbut->drawflag & ~drawflag_copy) | (but->drawflag & drawflag_copy);
+ SWAP(ListBase, but->extra_op_icons, oldbut->extra_op_icons);
+
/* copy hardmin for list rows to prevent 'sticking' highlight to mouse position
* when scrolling without moving mouse (see [#28432]) */
if (ELEM(oldbut->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) {
@@ -3389,7 +3391,7 @@ static void ui_but_build_drawstr_float(uiBut *but, double value)
if (value == (double)FLT_MAX) {
STR_CONCAT(but->drawstr, slen, "inf");
}
- else if (value == (double)-FLT_MIN) {
+ else if (value == (double)-FLT_MAX) {
STR_CONCAT(but->drawstr, slen, "-inf");
}
else if (subtype == PROP_PERCENTAGE) {
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 3c26c37b610..988dea270f5 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -69,6 +69,7 @@ wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_id");
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_depth");
WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_driver");
+ WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_gpencil_color");
return keymap;
}
diff --git a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
new file mode 100644
index 00000000000..02d4596e93c
--- /dev/null
+++ b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
@@ -0,0 +1,324 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edinterface
+ *
+ * Eyedropper (RGB Color)
+ *
+ * Defines:
+ * - #UI_OT_eyedropper_gpencil_color
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_string.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_report.h"
+
+#include "UI_interface.h"
+
+#include "IMB_colormanagement.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_undo.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+#include "interface_intern.h"
+#include "interface_eyedropper_intern.h"
+
+typedef struct EyedropperGPencil {
+ struct ColorManagedDisplay *display;
+ /** color under cursor RGB */
+ float color[3];
+} EyedropperGPencil;
+
+/* Helper: Draw status message while the user is running the operator */
+static void eyedropper_gpencil_status_indicators(bContext *C)
+{
+ char msg_str[UI_MAX_DRAW_STR];
+ BLI_strncpy(
+ msg_str, TIP_("LMB: Stroke - Shift: Fill - Shift+Ctrl: Stroke + Fill"), UI_MAX_DRAW_STR);
+
+ ED_workspace_status_text(C, msg_str);
+}
+
+/* Initialize. */
+static bool eyedropper_gpencil_init(bContext *C, wmOperator *op)
+{
+ EyedropperGPencil *eye = MEM_callocN(sizeof(EyedropperGPencil), __func__);
+
+ op->customdata = eye;
+ Scene *scene = CTX_data_scene(C);
+
+ const char *display_device;
+ display_device = scene->display_settings.display_device;
+ eye->display = IMB_colormanagement_display_get_named(display_device);
+
+ return true;
+}
+
+/* Exit and free memory. */
+static void eyedropper_gpencil_exit(bContext *C, wmOperator *op)
+{
+ /* Clear status message area. */
+ ED_workspace_status_text(C, NULL);
+
+ MEM_SAFE_FREE(op->customdata);
+}
+
+/* Set the material. */
+static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, EyedropperGPencil *eye)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ Material *ma = NULL;
+
+ const bool only_stroke = ((!event->ctrl) && (!event->shift));
+ const bool only_fill = ((!event->ctrl) && (event->shift));
+ const bool both = ((event->ctrl) && (event->shift));
+
+ float col_conv[4];
+ bool found = false;
+
+ /* Convert from linear rgb space to display space because grease pencil colors are in display
+ * space, and this conversion is needed to undo the conversion to linear performed by
+ * eyedropper_color_sample_fl. */
+ if (eye->display) {
+ copy_v3_v3(col_conv, eye->color);
+ IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display);
+ }
+ else {
+ copy_v3_v3(col_conv, eye->color);
+ }
+
+ /* Look for a similar material in grease pencil slots. */
+ short *totcol = give_totcolp(ob);
+ for (short i = 0; i < *totcol; i++) {
+ ma = give_current_material(ob, i + 1);
+ if (ma == NULL) {
+ continue;
+ }
+
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ if (gp_style != NULL) {
+ /* Check stroke color. */
+ bool found_stroke = compare_v3v3(gp_style->stroke_rgba, col_conv, 0.01f) &&
+ (gp_style->flag & GP_STYLE_STROKE_SHOW);
+ /* Check fill color. */
+ bool found_fill = compare_v3v3(gp_style->fill_rgba, col_conv, 0.01f) &&
+ (gp_style->flag & GP_STYLE_FILL_SHOW);
+
+ if ((only_stroke) && (found_stroke) && ((gp_style->flag & GP_STYLE_FILL_SHOW) == 0)) {
+ found = true;
+ }
+ else if ((only_fill) && (found_fill) && ((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0)) {
+ found = true;
+ }
+ else if ((both) && (found_stroke) && (found_fill)) {
+ found = true;
+ }
+
+ /* Found existing material. */
+ if (found) {
+ ob->actcol = i + 1;
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ return;
+ }
+ }
+ }
+
+ /* If material was not found add a new material with stroke and/or fill color
+ * depending of the secondary key (LMB: Stroke, Shift: Fill, Shift+Ctrl: Stroke/Fill)
+ */
+ int idx;
+ Material *ma_new = BKE_gpencil_object_material_new(bmain, ob, "Material", &idx);
+ WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, &ob->id);
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ DEG_relations_tag_update(bmain);
+
+ BLI_assert(ma_new != NULL);
+
+ MaterialGPencilStyle *gp_style_new = ma_new->gp_style;
+ BLI_assert(gp_style_new != NULL);
+
+ /* Only create Stroke (default option). */
+ if (only_stroke) {
+ /* Stroke color. */
+ gp_style_new->flag |= GP_STYLE_STROKE_SHOW;
+ gp_style_new->flag &= ~GP_STYLE_FILL_SHOW;
+ copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
+ zero_v4(gp_style_new->fill_rgba);
+ }
+ /* Fill Only. */
+ else if (only_fill) {
+ /* Fill color. */
+ gp_style_new->flag &= ~GP_STYLE_STROKE_SHOW;
+ gp_style_new->flag |= GP_STYLE_FILL_SHOW;
+ zero_v4(gp_style_new->stroke_rgba);
+ copy_v3_v3(gp_style_new->fill_rgba, col_conv);
+ }
+ /* Stroke and Fill. */
+ else if (both) {
+ gp_style_new->flag |= GP_STYLE_STROKE_SHOW | GP_STYLE_FILL_SHOW;
+ copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
+ copy_v3_v3(gp_style_new->fill_rgba, col_conv);
+ }
+ /* Push undo for new created material. */
+ ED_undo_push(C, "Add Grease Pencil Material");
+}
+
+/* Sample the color below cursor. */
+static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, int mx, int my)
+{
+ eyedropper_color_sample_fl(C, mx, my, eye->color);
+}
+
+/* Cancel operator. */
+static void eyedropper_gpencil_cancel(bContext *C, wmOperator *op)
+{
+ eyedropper_gpencil_exit(C, op);
+}
+
+/* Main modal status check. */
+static int eyedropper_gpencil_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ EyedropperGPencil *eye = (EyedropperGPencil *)op->customdata;
+ /* Handle modal keymap */
+ switch (event->type) {
+ case EVT_MODAL_MAP: {
+ switch (event->val) {
+ case EYE_MODAL_SAMPLE_BEGIN: {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ case EYE_MODAL_CANCEL: {
+ eyedropper_gpencil_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ case EYE_MODAL_SAMPLE_CONFIRM: {
+ eyedropper_gpencil_color_sample(C, eye, event->x, event->y);
+
+ /* Create material. */
+ eyedropper_gpencil_color_set(C, event, eye);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ eyedropper_gpencil_exit(C, op);
+ return OPERATOR_FINISHED;
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ break;
+ }
+ case MOUSEMOVE:
+ case INBETWEEN_MOUSEMOVE: {
+ eyedropper_gpencil_color_sample(C, eye, event->x, event->y);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Modal Operator init */
+static int eyedropper_gpencil_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ /* Init. */
+ if (eyedropper_gpencil_init(C, op)) {
+ /* Add modal temp handler. */
+ WM_event_add_modal_handler(C, op);
+ /* Status message. */
+ eyedropper_gpencil_status_indicators(C);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
+}
+
+/* Repeat operator */
+static int eyedropper_gpencil_exec(bContext *C, wmOperator *op)
+{
+ /* init */
+ if (eyedropper_gpencil_init(C, op)) {
+
+ /* cleanup */
+ eyedropper_gpencil_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
+}
+
+static bool eyedropper_gpencil_poll(bContext *C)
+{
+ /* Only valid if the current active object is grease pencil. */
+ Object *obact = CTX_data_active_object(C);
+ if ((obact == NULL) || (obact->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ /* Test we have a window below. */
+ return (CTX_wm_window(C) != NULL);
+}
+
+void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Grease Pencil Eyedropper";
+ ot->idname = "UI_OT_eyedropper_gpencil_color";
+ ot->description = "Sample a color from the Blender Window and create Grease Pencil material";
+
+ /* api callbacks */
+ ot->invoke = eyedropper_gpencil_invoke;
+ ot->modal = eyedropper_gpencil_modal;
+ ot->cancel = eyedropper_gpencil_cancel;
+ ot->exec = eyedropper_gpencil_exec;
+ ot->poll = eyedropper_gpencil_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index e0442ebcca2..83820c919c8 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -108,6 +108,7 @@ static int ui_do_but_EXIT(bContext *C,
const wmEvent *event);
static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b);
static void ui_textedit_string_set(uiBut *but, struct uiHandleButtonData *data, const char *str);
+static void button_tooltip_timer_reset(bContext *C, uiBut *but);
#ifdef USE_KEYNAV_LIMIT
static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event);
@@ -3967,8 +3968,11 @@ static bool ui_do_but_extra_operator_icon(bContext *C,
uiButExtraOpIcon *op_icon = ui_but_extra_operator_icon_mouse_over_get(but, data, event);
if (op_icon) {
+ ED_region_tag_redraw(data->region);
+ button_tooltip_timer_reset(C, but);
+
ui_but_extra_operator_icon_apply(C, but, op_icon);
- button_activate_exit(C, but, data, false, false);
+ /* Note: 'but', 'data' may now be freed, don't access. */
return true;
}
@@ -7493,6 +7497,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
data = MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData");
data->wm = CTX_wm_manager(C);
data->window = CTX_wm_window(C);
+ BLI_assert(ar != NULL);
data->region = ar;
#ifdef USE_CONT_MOUSE_CORRECT
@@ -8005,6 +8010,7 @@ void ui_but_execute_begin(struct bContext *UNUSED(C),
*active_back = but->active;
data = MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData_Fake");
but->active = data;
+ BLI_assert(ar != NULL);
data->region = ar;
}
@@ -9816,9 +9822,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
if (but && (U.pie_menu_confirm > 0) &&
(dist >= U.dpi_fac * (U.pie_menu_threshold + U.pie_menu_confirm))) {
- if (but) {
- return ui_but_pie_menu_apply(C, menu, but, true);
- }
+ return ui_but_pie_menu_apply(C, menu, but, true);
}
retval = ui_but_pie_menu_apply(C, menu, but, true);
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index b844e237366..1495fb7e716 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1583,7 +1583,6 @@ static struct {
IconTextureDrawCall normal;
IconTextureDrawCall border;
bool enabled;
- float mat[4][4];
} g_icon_draw_cache = {{{{{0}}}}};
void UI_icon_draw_cache_begin(void)
diff --git a/source/blender/editors/interface/interface_icons_event.c b/source/blender/editors/interface/interface_icons_event.c
index e1ce77b8b61..b7fd953ed63 100644
--- a/source/blender/editors/interface/interface_icons_event.c
+++ b/source/blender/editors/interface/interface_icons_event.c
@@ -171,12 +171,13 @@ void icon_draw_rect_input(float x,
const bool simple_text = false;
- if ((event_type >= AKEY) || (ZKEY <= event_type)) {
+ if ((event_type >= AKEY) && (event_type <= ZKEY)) {
char str[2] = {'A' + (event_type - AKEY), '\0'};
icon_draw_rect_input_default_text(&rect, color, margin, str);
}
- if ((event_type >= F1KEY) || (F12KEY <= event_type)) {
- char str[3] = {'F', '1' + (event_type - F1KEY), '\0'};
+ else if ((event_type >= F1KEY) && (event_type <= F12KEY)) {
+ char str[4];
+ SNPRINTF(str, "F%d", 1 + (event_type - F1KEY));
icon_draw_rect_input_default_text(&rect, color, margin, str);
}
else if (event_type == LEFTSHIFTKEY) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 4351b75eb86..81979b1fc8f 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -971,6 +971,9 @@ void UI_OT_eyedropper_depth(struct wmOperatorType *ot);
/* interface_eyedropper_driver.c */
void UI_OT_eyedropper_driver(struct wmOperatorType *ot);
+/* interface_eyedropper_gpencil_color.c */
+void UI_OT_eyedropper_gpencil_color(struct wmOperatorType *ot);
+
/* interface_util.c */
/**
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 4e56a02997b..7ce4242c697 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1751,6 +1751,7 @@ void ED_operatortypes_ui(void)
WM_operatortype_append(UI_OT_eyedropper_id);
WM_operatortype_append(UI_OT_eyedropper_depth);
WM_operatortype_append(UI_OT_eyedropper_driver);
+ WM_operatortype_append(UI_OT_eyedropper_gpencil_color);
}
/**
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index 028d99ac052..cd0421dde09 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -334,7 +334,8 @@ int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, Rep
}
if (block) {
- UI_block_active_only_flagged_buttons(C, CTX_wm_region(C), block);
+ uiPopupBlockHandle *handle = block->handle;
+ UI_block_active_only_flagged_buttons(C, handle->region, block);
}
return OPERATOR_INTERFACE;
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 9f1b11d1354..b3e039292e1 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -4638,9 +4638,6 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case UI_BTYPE_SEARCH_MENU:
wt = widget_type(UI_WTYPE_NAME);
- if (but->block->theme_style == UI_BLOCK_THEME_STYLE_POPUP) {
- wt->wcol_theme = &btheme->tui.wcol_menu_back;
- }
break;
case UI_BTYPE_TAB:
@@ -4914,9 +4911,10 @@ static void ui_draw_popover_back_impl(const uiWidgetColors *wcol,
{
/* tsk, this isn't nice. */
const float unit_half = unit_size / 2;
- const float cent_x = mval_origin ?
- CLAMPIS(mval_origin[0], rect->xmin + unit_size, rect->xmax - unit_size) :
- BLI_rcti_cent_x(rect);
+ const float cent_x = mval_origin ? CLAMPIS(mval_origin[0],
+ rect->xmin + unit_size,
+ rect->xmax - unit_size) :
+ BLI_rcti_cent_x(rect);
rect->ymax -= unit_half;
rect->ymin += unit_half;
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 8a570933a33..99594cf0803 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -371,7 +371,6 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_OBCENTER_DIA:
cp = &ts->obcenter_dia;
break;
- break;
case TH_EDGE:
cp = ts->edge;
break;
@@ -841,6 +840,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp = ts->nla_tweakdupli;
break;
+ case TH_NLA_TRACK:
+ cp = ts->nla_track;
+ break;
case TH_NLA_TRANSITION:
cp = ts->nla_transition;
break;
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
index 7155348fed5..993898bddd5 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
@@ -522,7 +522,6 @@ typedef struct GizmoGroupData_SpinRedo {
PropertyRNA *prop_axis_no;
PropertyRNA *prop_angle;
- float rotate_axis[3];
#ifdef USE_ANGLE_Z_ORIENT
/* Apply 'orient_mat' for the final value. */
float orient_axis_relative[3];
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 3be94cf99c1..3c3e91e8afe 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -386,7 +386,6 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
bool ok = true;
if (is_interactive == false) {
if (exec_data.base_index >= bases_len) {
- return OPERATOR_CANCELLED;
ok = false;
}
else {
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index d066e9ecddc..8d98a3bf231 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -101,16 +101,21 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
BMIter face_iter;
/* Delete all unmasked faces */
+ const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
+ BLI_assert(cd_vert_mask_offset != -1);
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
float mask_threshold = RNA_float_get(op->ptr, "mask_threshold");
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- bool delete_face = false;
+ bool keep_face = true;
BM_ITER_ELEM (v, &face_iter, f, BM_VERTS_OF_FACE) {
- float mask = BM_elem_float_data_get(&bm->vdata, v, CD_PAINT_MASK);
- delete_face = mask < mask_threshold;
+ const float mask = BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
+ if (mask < mask_threshold) {
+ keep_face = false;
+ break;
+ }
}
- BM_elem_flag_set(f, BM_ELEM_TAG, delete_face);
+ BM_elem_flag_set(f, BM_ELEM_TAG, !keep_face);
}
BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES);
@@ -173,7 +178,6 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
}
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- BKE_editmesh_free_derivedmesh(em);
BKE_mesh_free(new_mesh);
new_mesh = BKE_mesh_from_bmesh_nomain(bm,
@@ -182,7 +186,8 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
}),
mesh);
- BM_mesh_free(bm);
+ BKE_editmesh_free(em);
+ MEM_freeN(em);
if (new_mesh->totvert == 0) {
BKE_mesh_free(new_mesh);
@@ -196,8 +201,6 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
Object *new_ob = ED_object_add_type(C, OB_MESH, NULL, ob->loc, ob->rot, false, local_view_bits);
BKE_mesh_nomain_to_mesh(new_mesh, new_ob->data, new_ob, &CD_MASK_EVERYTHING, true);
- BKE_mesh_free(new_mesh);
-
if (RNA_boolean_get(op->ptr, "apply_shrinkwrap")) {
BKE_shrinkwrap_mesh_nearest_surface_deform(C, new_ob, ob);
}
@@ -212,6 +215,8 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
}
}
+ BKE_mesh_calc_normals(new_ob->data);
+
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, new_ob);
BKE_mesh_batch_cache_dirty_tag(new_ob->data, BKE_MESH_BATCH_DIRTY_ALL);
DEG_relations_tag_update(bmain);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 4636d1ee71e..cf3170b5446 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -2044,11 +2044,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
}
if (tot_failed_all != 0) {
- BKE_reportf(op->reports,
- RPT_WARNING,
- tot_failed_all == 1 ? "Unable to rotate %d edge" :
- "Unable to rotate %d edges",
- tot_failed_all);
+ BKE_reportf(op->reports, RPT_WARNING, "Unable to rotate %d edge(s)", tot_failed_all);
}
return OPERATOR_FINISHED;
@@ -3165,11 +3161,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
}
MEM_freeN(objects);
- BKE_reportf(op->reports,
- RPT_INFO,
- count_multi == 1 ? "Removed %d vertex" :
- "Removed %d vertices",
- count_multi);
+ BKE_reportf(op->reports, RPT_INFO, "Removed %d vertice(s)", count_multi);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 569994bead1..a0d424e083c 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -880,14 +880,14 @@ void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot)
void ED_mesh_update(Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_loose)
{
- if (calc_edges_loose && mesh->totedge) {
- BKE_mesh_calc_edges_loose(mesh);
- }
-
if (calc_edges || ((mesh->totpoly || mesh->totface) && mesh->totedge == 0)) {
BKE_mesh_calc_edges(mesh, calc_edges, true);
}
+ if (calc_edges_loose && mesh->totedge) {
+ BKE_mesh_calc_edges_loose(mesh);
+ }
+
/* Default state is not to have tessface's so make sure this is the case. */
BKE_mesh_tessface_clear(mesh);
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index d6816ddbe73..bdb23c5ce6f 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1030,7 +1030,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
return OPERATOR_CANCELLED;
}
/* handled below */
- id_us_min((ID *)ima);
+ id_us_min(&ima->id);
Object *ob = NULL;
Object *ob_cursor = ED_view3d_give_object_under_cursor(C, event->mval);
@@ -1581,11 +1581,7 @@ static int object_delete_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- BKE_reportf(op->reports,
- RPT_INFO,
- changed_count == 1 ? "Deleted %u object" :
- "Deleted %u objects",
- changed_count);
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %u object(s)", changed_count);
if (changed_count == 0) {
return OPERATOR_CANCELLED;
@@ -2149,6 +2145,7 @@ static int convert_exec(bContext *C, wmOperator *op)
const short target = RNA_enum_get(op->ptr, "target");
bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
int a, mballConverted = 0;
+ bool gpencilConverted = false;
/* don't forget multiple users! */
@@ -2389,20 +2386,20 @@ static int convert_exec(bContext *C, wmOperator *op)
}
else if (target == OB_GPENCIL) {
if (ob->type != OB_CURVE) {
+ ob->flag &= ~OB_DONE;
BKE_report(
op->reports, RPT_ERROR, "Convert Surfaces to Grease Pencil is not supported.");
}
else {
- /* Create a new grease pencil object only if it was not created before.
- * All curves selected are converted as strokes of the same grease pencil object.
+ /* Create a new grease pencil object and copy transformations.
* Nurbs Surface are not supported.
*/
- if (gpencil_ob == NULL) {
- const float *cur = scene->cursor.location;
- ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
- gpencil_ob = ED_gpencil_add_object(C, scene, cur, local_view_bits);
- }
+ ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
+ gpencil_ob = ED_gpencil_add_object(C, scene, ob->loc, local_view_bits);
+ copy_v3_v3(gpencil_ob->rot, ob->rot);
+ copy_v3_v3(gpencil_ob->scale, ob->scale);
BKE_gpencil_convert_curve(bmain, scene, gpencil_ob, ob, false, false, true);
+ gpencilConverted = true;
}
}
}
@@ -2502,6 +2499,17 @@ static int convert_exec(bContext *C, wmOperator *op)
}
FOREACH_SCENE_OBJECT_END;
}
+ /* Remove curves converted to Grease Pencil object. */
+ if (gpencilConverted) {
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_curve) {
+ if (ob_curve->type == OB_CURVE) {
+ if (ob_curve->flag & OB_DONE) {
+ ED_object_base_free_and_unlink(bmain, scene, ob_curve);
+ }
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+ }
}
// XXX ED_object_editmode_enter(C, 0);
@@ -2580,7 +2588,7 @@ static Base *object_add_duplicate_internal(
DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
base = BKE_view_layer_base_find(view_layer, ob);
- if ((base != NULL) && (base->flag & BASE_VISIBLE)) {
+ if ((base != NULL) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) {
BKE_collection_object_add_from(bmain, scene, ob, obn);
}
else {
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index d9baec7c3ca..9e9cfe1beed 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -879,7 +879,7 @@ static int bake(Render *re,
else {
ob_cage_eval = DEG_get_evaluated_object(depsgraph, ob_cage);
ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+ ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER);
}
}
}
@@ -976,7 +976,7 @@ static int bake(Render *re,
highpoly[i].ob = ob_iter;
highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
- highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER);
+ highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER);
highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false);
/* lowpoly to highpoly transformation matrix */
@@ -992,10 +992,10 @@ static int bake(Render *re,
if (ob_cage != NULL) {
ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+ ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER);
}
ob_low_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_low_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+ ob_low_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER);
/* populate the pixel arrays with the corresponding face data for each high poly object */
if (!RE_bake_pixels_populate_from_objects(me_low,
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 4759a3cb0db..70d024c7902 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -218,7 +218,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op)
/* Hide selected or unselected objects. */
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (!(base->flag & BASE_VISIBLE)) {
+ if (!(base->flag & BASE_VISIBLE_DEPSGRAPH)) {
continue;
}
@@ -292,7 +292,7 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
if (v3d->flag & V3D_LOCAL_COLLECTIONS) {
- if ((lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0) {
+ if (lc->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) {
return OPERATOR_CANCELLED;
}
if (toggle) {
@@ -300,11 +300,11 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op)
BKE_layer_collection_local_sync(view_layer, v3d);
}
else {
- BKE_layer_collection_local_isolate(view_layer, v3d, lc, extend);
+ BKE_layer_collection_isolate_local(view_layer, v3d, lc, extend);
}
}
else {
- BKE_layer_collection_isolate(scene, view_layer, lc, extend);
+ BKE_layer_collection_isolate_global(scene, view_layer, lc, extend);
}
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -1547,7 +1547,7 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
}
int collection_index = RNA_property_int_get(op->ptr, prop);
- collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
+ collection = BKE_collection_from_index(scene, collection_index);
if (collection == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index d56791e5da0..c030c551374 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2051,7 +2051,7 @@ void ED_object_single_users(Main *bmain,
single_object_action_users(bmain, scene, NULL, NULL, 0);
single_mat_users_expand(bmain);
/* Duplicating obdata and other IDs may require another update of the collections and objects
- * pointers, especially reguarding drivers and custom props, see T66641.
+ * pointers, especially regarding drivers and custom props, see T66641.
* Note that this whole scene duplication code and 'make single user' functions have te be
* rewritten at some point to make use of proper modern ID management code,
* but that is no small task.
diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c
index 2c05ae14f2e..35762c5861e 100644
--- a/source/blender/editors/object/object_remesh.c
+++ b/source/blender/editors/object/object_remesh.c
@@ -92,6 +92,12 @@ static bool object_remesh_poll(bContext *C)
return false;
}
+ if (modifiers_usesMultires(ob)) {
+ CTX_wm_operator_poll_msg_set(
+ C, "The remesher cannot run with a Multires modifier in the modifier stack.");
+ return false;
+ }
+
return ED_operator_object_active_editable_mesh(C);
}
@@ -111,8 +117,13 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
ED_sculpt_undo_geometry_begin(ob);
}
+ float isovalue = 0.0f;
+ if (mesh->flag & ME_REMESH_REPROJECT_VOLUME) {
+ isovalue = mesh->remesh_voxel_size * 0.3f;
+ }
+
new_mesh = BKE_mesh_remesh_voxel_to_mesh_nomain(
- mesh, mesh->remesh_voxel_size, mesh->remesh_voxel_adaptivity);
+ mesh, mesh->remesh_voxel_size, mesh->remesh_voxel_adaptivity, isovalue);
if (!new_mesh) {
return OPERATOR_CANCELLED;
@@ -204,6 +215,57 @@ typedef struct QuadriFlowJob {
int success;
} QuadriFlowJob;
+static bool mesh_is_manifold_consistent(Mesh *mesh)
+{
+ /* In this check we count boundary edges as manifold. Additionally, we also
+ * check that the direction of the faces are consistent and doesn't suddenly
+ * flip
+ */
+
+ bool is_manifold_consistent = true;
+ const MLoop *mloop = mesh->mloop;
+ char *edge_faces = (char *)MEM_callocN(mesh->totedge * sizeof(char), "remesh_manifold_check");
+ int *edge_vert = (int *)MEM_malloc_arrayN(
+ mesh->totedge, sizeof(unsigned int), "remesh_consistent_check");
+
+ for (unsigned int i = 0; i < mesh->totedge; i++) {
+ edge_vert[i] = -1;
+ }
+
+ for (unsigned int loop_idx = 0; loop_idx < mesh->totloop; loop_idx++) {
+ const MLoop *loop = &mloop[loop_idx];
+ edge_faces[loop->e] += 1;
+ if (edge_faces[loop->e] > 2) {
+ is_manifold_consistent = false;
+ break;
+ }
+
+ if (edge_vert[loop->e] == -1) {
+ edge_vert[loop->e] = loop->v;
+ }
+ else if (edge_vert[loop->e] == loop->v) {
+ /* Mesh has flips in the surface so it is non consistent */
+ is_manifold_consistent = false;
+ break;
+ }
+ }
+
+ if (is_manifold_consistent) {
+ /* check for wire edges */
+ for (unsigned int i = 0; i < mesh->totedge; i++) {
+ if (edge_faces[i] == 0) {
+ is_manifold_consistent = false;
+ break;
+ }
+ }
+ }
+
+ MEM_freeN(edge_faces);
+ MEM_freeN(edge_vert);
+
+ return is_manifold_consistent;
+}
+
static void quadriflow_free_job(void *customdata)
{
QuadriFlowJob *qj = customdata;
@@ -320,6 +382,12 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update
Mesh *new_mesh;
Mesh *bisect_mesh;
+ /* Check if the mesh is manifold. Quadriflow requires manifold meshes */
+ if (!mesh_is_manifold_consistent(mesh)) {
+ qj->success = -2;
+ return;
+ }
+
/* Run Quadriflow bisect operations on a copy of the mesh to keep the code readable without
* freeing the original ID */
bisect_mesh = BKE_mesh_copy(qj->bmain, mesh);
@@ -390,17 +458,22 @@ static void quadriflow_end_job(void *customdata)
WM_set_locked_interface(G_MAIN->wm.first, false);
- if (qj->success > 0) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_reportf(RPT_INFO, "QuadriFlow: Completed remeshing!");
- }
- else {
- if (qj->success == 0) {
+ switch (qj->success) {
+ case 1:
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_reportf(RPT_INFO, "QuadriFlow: Completed remeshing!");
+ break;
+ case 0:
WM_reportf(RPT_ERROR, "QuadriFlow: remeshing failed!");
- }
- else {
+ break;
+ case -1:
WM_report(RPT_WARNING, "QuadriFlow: remeshing canceled!");
- }
+ break;
+ case -2:
+ WM_report(RPT_WARNING,
+ "QuadriFlow: The mesh needs to be manifold and have face normals that point in a "
+ "consistent direction.");
+ break;
}
}
@@ -602,7 +675,7 @@ void OBJECT_OT_quadriflow_remesh(wmOperatorType *ot)
RNA_def_enum(ot->srna,
"mode",
mode_type_items,
- 0,
+ QUADRIFLOW_REMESH_FACES,
"Mode",
"How to specify the amount of detail for the new mesh");
@@ -628,7 +701,7 @@ void OBJECT_OT_quadriflow_remesh(wmOperatorType *ot)
prop = RNA_def_int(ot->srna,
"target_faces",
- 1,
+ 4000,
1,
INT_MAX,
"Number of Faces",
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 28242b986f1..40fa11994f4 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -214,7 +214,7 @@ bool ED_object_base_deselect_all(ViewLayer *view_layer, View3D *v3d, int action)
static int get_base_select_priority(Base *base)
{
- if (base->flag & BASE_VISIBLE) {
+ if (base->flag & BASE_VISIBLE_DEPSGRAPH) {
if (base->flag & BASE_SELECTABLE) {
return 3;
}
@@ -288,7 +288,7 @@ bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_
if (!(base->flag & BASE_SELECTED)) {
ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
- if (base->flag & BASE_VISIBLE) {
+ if (BASE_VISIBLE(v3d, base)) {
ED_object_base_select(base, BA_SELECT);
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 2ea0e9dc018..3978f7ba3b5 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -3076,11 +3076,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_reportf(op->reports,
- RPT_INFO,
- totremoved == 1 ? "Removed %d double particle" :
- "Removed %d double particles",
- totremoved);
+ BKE_reportf(op->reports, RPT_INFO, "Removed %d double particle(s)", totremoved);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 4b1d51ee6c2..303a0714388 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -115,13 +115,7 @@ bool ED_rigidbody_constraint_add(
void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
{
- RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
-
- BKE_rigidbody_remove_constraint(scene, ob);
- if (rbw) {
- BKE_collection_object_remove(bmain, rbw->constraints, ob, false);
- DEG_id_tag_update(&rbw->constraints->id, ID_RECALC_COPY_ON_WRITE);
- }
+ BKE_rigidbody_remove_constraint(bmain, scene, ob, false);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index bc8a1799fa0..43ca421b9d0 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -105,7 +105,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
{
- BKE_rigidbody_remove_object(bmain, scene, ob);
+ BKE_rigidbody_remove_object(bmain, scene, ob, false);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 053ca3d8f9f..7106af25a82 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -859,7 +859,7 @@ static void screen_render_cancel(bContext *C, wmOperator *op)
static void clean_viewport_memory_base(Base *base)
{
- if ((base->flag & BASE_VISIBLE) == 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
return;
}
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 3e001ef25b5..6dc3a1ec1ac 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -115,7 +115,7 @@ ImBuf *get_brush_icon(Brush *brush)
// first use the path directly to try and load the file
BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath));
- BLI_path_abs(path, BKE_main_blendfile_path_from_global());
+ BLI_path_abs(path, ID_BLEND_PATH_FROM_GLOBAL(&brush->id));
/* use default colorspaces for brushes */
brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
@@ -474,7 +474,7 @@ static Scene *preview_prepare_scene(
}
}
else if (base->object->type == OB_LAMP) {
- base->flag |= BASE_VISIBLE;
+ base->flag |= BASE_VISIBLE_DEPSGRAPH;
}
}
}
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 9f13431f25a..7970d491877 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -103,15 +103,17 @@ static Object **object_array_for_shading(bContext *C, uint *r_objects_len)
ScrArea *sa = CTX_wm_area(C);
SpaceProperties *sbuts = NULL;
View3D *v3d = NULL;
- if (sa->spacetype == SPACE_PROPERTIES) {
- sbuts = sa->spacedata.first;
- }
- else if (sa->spacetype == SPACE_VIEW3D) {
- v3d = sa->spacedata.first;
+ if (sa != NULL) {
+ if (sa->spacetype == SPACE_PROPERTIES) {
+ sbuts = sa->spacedata.first;
+ }
+ else if (sa->spacetype == SPACE_VIEW3D) {
+ v3d = sa->spacedata.first;
+ }
}
Object **objects;
- if (sbuts && sbuts->pinid && GS(sbuts->pinid->name) == ID_OB) {
+ if (sbuts != NULL && sbuts->pinid && GS(sbuts->pinid->name) == ID_OB) {
objects = MEM_mallocN(sizeof(*objects), __func__);
objects[0] = (Object *)sbuts->pinid;
*r_objects_len = 1;
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index 6873495e962..a54701f8725 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -156,8 +156,8 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
}
/* changes context! */
- if (WM_window_open_temp(C, IFACE_("Blender Render"), mx, my, sizex, sizey, SPACE_IMAGE) ==
- NULL) {
+ if (WM_window_open_temp(
+ C, IFACE_("Blender Render"), mx, my, sizex, sizey, SPACE_IMAGE, false) == NULL) {
BKE_report(reports, RPT_ERROR, "Failed to open window!");
return NULL;
}
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index c068fbdf7cb..9957fe0515c 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -2869,7 +2869,7 @@ void ED_region_info_draw(ARegion *ar,
float fill_color[4],
const bool full_redraw)
{
- ED_region_info_draw_multiline(ar, (const char * [2]){text, NULL}, fill_color, full_redraw);
+ ED_region_info_draw_multiline(ar, (const char *[2]){text, NULL}, fill_color, full_redraw);
}
#define MAX_METADATA_STR 1024
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
index 316604156de..a6b8bba73e3 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -21,7 +21,7 @@
#include "ED_screen.h"
#include "GPU_batch_presets.h"
-#include "GPU_extensions.h"
+#include "GPU_platform.h"
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index c8008fe3cc7..bbdddfadc30 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1375,13 +1375,14 @@ ScrArea *ED_screen_temp_space_open(bContext *C,
int sizex,
int sizey,
eSpace_Type space_type,
- int display_type)
+ int display_type,
+ bool dialog)
{
ScrArea *sa = NULL;
switch (display_type) {
case USER_TEMP_SPACE_DISPLAY_WINDOW:
- if (WM_window_open_temp(C, title, x, y, sizex, sizey, (int)space_type)) {
+ if (WM_window_open_temp(C, title, x, y, sizex, sizey, (int)space_type, dialog)) {
sa = CTX_wm_area(C);
}
break;
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 0b374617cce..cc1f53eabde 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -3946,7 +3946,7 @@ static int region_toggle_exec(bContext *C, wmOperator *op)
region = CTX_wm_region(C);
}
- if (region) {
+ if (region && (region->alignment != RGN_ALIGN_NONE)) {
ED_region_toggle_hidden(C, region);
}
ED_region_tag_redraw(region);
@@ -4828,9 +4828,14 @@ static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *even
int sizey = 520 * UI_DPI_FAC;
/* changes context! */
- if (WM_window_open_temp(
- C, IFACE_("Blender Preferences"), event->x, event->y, sizex, sizey, SPACE_USERPREF) !=
- NULL) {
+ if (WM_window_open_temp(C,
+ IFACE_("Blender Preferences"),
+ event->x,
+ event->y,
+ sizex,
+ sizey,
+ SPACE_USERPREF,
+ false) != NULL) {
/* The header only contains the editor switcher and looks empty.
* So hiding in the temp window makes sense. */
ScrArea *area = CTX_wm_area(C);
@@ -4879,9 +4884,14 @@ static int drivers_editor_show_invoke(bContext *C, wmOperator *op, const wmEvent
but = UI_context_active_but_prop_get(C, &ptr, &prop, &index);
/* changes context! */
- if (WM_window_open_temp(
- C, IFACE_("Blender Drivers Editor"), event->x, event->y, sizex, sizey, SPACE_GRAPH) !=
- NULL) {
+ if (WM_window_open_temp(C,
+ IFACE_("Blender Drivers Editor"),
+ event->x,
+ event->y,
+ sizex,
+ sizey,
+ SPACE_GRAPH,
+ false) != NULL) {
ED_drivers_editor_init(C, CTX_wm_area(C));
/* activate driver F-Curve for the property under the cursor */
@@ -4939,9 +4949,14 @@ static int info_log_show_invoke(bContext *C, wmOperator *op, const wmEvent *even
int shift_y = 480;
/* changes context! */
- if (WM_window_open_temp(
- C, IFACE_("Blender Info Log"), event->x, event->y + shift_y, sizex, sizey, SPACE_INFO) !=
- NULL) {
+ if (WM_window_open_temp(C,
+ IFACE_("Blender Info Log"),
+ event->x,
+ event->y + shift_y,
+ sizex,
+ sizey,
+ SPACE_INFO,
+ false) != NULL) {
return OPERATOR_FINISHED;
}
else {
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 774d4ef09b1..c59ab6279cd 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -410,7 +410,7 @@ static void load_tex_cursor_task_cb(void *__restrict userdata,
if (len <= 1.0f) {
float avg = BKE_brush_curve_strength_clamped(br, len, 1.0f); /* Falloff curve */
- buffer[index] = 255 - (GLubyte)(255 * avg);
+ buffer[index] = (GLubyte)(255 * avg);
}
else {
buffer[index] = 0;
@@ -1359,13 +1359,14 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
if ((mode == PAINT_MODE_SCULPT) && ss && !ups->stroke_active) {
prev_active_vertex_index = ss->active_vertex_index;
is_cursor_over_mesh = sculpt_cursor_geometry_info_update(
- C, &gi, mouse, !(brush->falloff_shape & BRUSH_AIRBRUSH));
+ C, &gi, mouse, (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE));
}
/* Use special paint crosshair cursor in all paint modes*/
wmWindow *win = CTX_wm_window(C);
WM_cursor_set(win, WM_CURSOR_PAINT);
- if ((mode == PAINT_MODE_SCULPT) && ss && !(brush->falloff_shape & BRUSH_AIRBRUSH)) {
+ if ((mode == PAINT_MODE_SCULPT) && ss &&
+ (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE)) {
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
if (!ups->stroke_active) {
@@ -1393,7 +1394,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
}
/* Draw pose brush origin */
- if (brush->sculpt_tool == SCULPT_TOOL_POSE && !is_multires) {
+ if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
if (update_previews) {
BKE_sculpt_update_object_for_edit(depsgraph, vc.obact, true, false);
@@ -1439,14 +1440,14 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
GPU_matrix_mul(vc.obact->obmat);
if (brush->sculpt_tool == SCULPT_TOOL_GRAB && (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) &&
!is_multires) {
- if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->modifiers_active) {
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->deform_modifiers_active) {
sculpt_geometry_preview_lines_update(C, ss, rds);
sculpt_geometry_preview_lines_draw(pos, ss);
}
}
/* Draw pose brush line preview */
- if (brush->sculpt_tool == SCULPT_TOOL_POSE && !is_multires) {
+ if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
GPU_line_width(2.0f);
immBegin(GPU_PRIM_LINES, 2);
@@ -1492,7 +1493,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* Draw cached dynamic mesh preview lines */
if (brush->sculpt_tool == SCULPT_TOOL_GRAB && (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) &&
!is_multires) {
- if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->modifiers_active) {
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->deform_modifiers_active) {
GPU_matrix_push_projection();
ED_view3d_draw_setup_view(CTX_wm_window(C),
CTX_data_depsgraph_pointer(C),
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 24c2dfb6c6b..b4388f6c324 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -540,7 +540,7 @@ static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, Po
RNA_float_get_array(itemptr, "mouse", mouse);
pressure = RNA_float_get(itemptr, "pressure");
eraser = RNA_boolean_get(itemptr, "pen_flip");
- size = max_ff(1.0f, RNA_float_get(itemptr, "size"));
+ size = RNA_float_get(itemptr, "size");
/* stroking with fill tool only acts on stroke end */
if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 4f1ae10aa62..9c95a3cee4d 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -374,25 +374,65 @@ static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter,
/* create a mask with the falloff strength */
static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter,
int diameter,
- float radius)
+ float radius,
+ const float pos[2])
{
Brush *brush = painter->brush;
- int xoff = -radius;
- int yoff = -radius;
+ int offset = (int)floorf(diameter / 2.0f);
unsigned short *mask, *m;
- int x, y;
mask = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
m = mask;
- for (y = 0; y < diameter; y++) {
- for (x = 0; x < diameter; x++, m++) {
- float xy[2] = {x + xoff, y + yoff};
- float len = len_v2(xy);
+ int aa_samples = 1.0f / (radius * 0.20f);
+ aa_samples = clamp_i(aa_samples, 3, 16);
- *m = (unsigned short)(65535.0f * BKE_brush_curve_strength_clamped(brush, len, radius));
+ /* Temporal until we have the brush properties */
+ const float hardness = 1.0f;
+ const float rotation = 0.0f;
+
+ float aa_offset = 1.0f / (2.0f * (float)aa_samples);
+ float aa_step = 1.0f / (float)aa_samples;
+
+ float bpos[2];
+ bpos[0] = pos[0] - floorf(pos[0]) + offset + aa_offset;
+ bpos[1] = pos[1] - floorf(pos[1]) + offset + aa_offset;
+
+ const float co = cosf(DEG2RADF(rotation));
+ const float si = sinf(DEG2RADF(rotation));
+
+ float norm_factor = 65535.0f / (float)(aa_samples * aa_samples);
+
+ for (int y = 0; y < diameter; y++) {
+ for (int x = 0; x < diameter; x++, m++) {
+ float total_samples = 0;
+ for (int i = 0; i < aa_samples; i++) {
+ for (int j = 0; j < aa_samples; j++) {
+ float pixel_xy[2] = {x + (aa_step * i), y + (aa_step * j)};
+ float xy_rot[2];
+ sub_v2_v2(pixel_xy, bpos);
+
+ xy_rot[0] = co * pixel_xy[0] - si * pixel_xy[1];
+ xy_rot[1] = si * pixel_xy[0] + co * pixel_xy[1];
+
+ float len = len_v2(xy_rot);
+ float p = len / radius;
+ if (hardness < 1.0f) {
+ p = (p - hardness) / (1 - hardness);
+ p = 1.0f - p;
+ CLAMP(p, 0, 1);
+ }
+ else {
+ p = 1.0;
+ }
+ float hardness_factor = 3.0f * p * p - 2.0f * p * p * p;
+ float curve = BKE_brush_curve_strength_clamped(brush, len, radius);
+ total_samples += curve * hardness_factor;
+ }
+ }
+ *m = (unsigned short)(total_samples * norm_factor);
}
}
@@ -721,7 +761,8 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s,
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
Brush *brush = painter->brush;
BrushPainterCache *cache = &painter->cache;
- const int diameter = 2 * size;
+ /* Adding 4 pixels of padding for brush antialiasing */
+ const int diameter = MAX2(1, size * 2) + 4;
bool do_random = false;
bool do_partial_update = false;
@@ -802,15 +843,13 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s,
}
/* curve mask can only change if the size changes */
- if (diameter != cache->lastdiameter) {
- if (cache->curve_mask) {
- MEM_freeN(cache->curve_mask);
- cache->curve_mask = NULL;
- }
-
- cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size);
+ if (cache->curve_mask) {
+ MEM_freeN(cache->curve_mask);
+ cache->curve_mask = NULL;
}
+ cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size, pos);
+
/* detect if we need to recreate image brush buffer */
if ((diameter != cache->lastdiameter) || (tex_rotation != cache->last_tex_rotation) ||
do_random || update_color) {
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 69eed84fe2b..19380fb9022 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -29,7 +29,6 @@ struct Brush;
struct ColorManagedDisplay;
struct ColorSpace;
struct ImagePool;
-struct ListBase;
struct MTex;
struct Object;
struct Paint;
@@ -37,7 +36,6 @@ struct PaintStroke;
struct PointerRNA;
struct RegionView3D;
struct Scene;
-struct UndoStep;
struct VPaint;
struct ViewContext;
struct bContext;
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index a93e55685d2..d160fba4013 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -166,9 +166,9 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
.value = value,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings);
if (multires) {
multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
@@ -343,9 +343,9 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *
.clip_planes_final = clip_planes_final,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings);
if (nodes) {
MEM_freeN(nodes);
@@ -532,9 +532,9 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
data.task_data.mode = mode;
data.task_data.value = value;
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings);
if (nodes) {
MEM_freeN(nodes);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index d8be345cc84..36418045551 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -256,6 +256,7 @@ static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode m
SCULPT_TOOL_GRAB,
SCULPT_TOOL_ROTATE,
SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_SNAKE_HOOK,
SCULPT_TOOL_ELASTIC_DEFORM,
SCULPT_TOOL_POSE)) {
return false;
@@ -668,7 +669,7 @@ static float paint_space_stroke_spacing(bContext *C,
return max_ff(0.001f, size_clamp * spacing / 50.f);
}
else {
- return max_ff(1.0, size_clamp * spacing / 50.0f);
+ return max_ff(stroke->zoom_2d, size_clamp * spacing / 50.0f);
}
}
@@ -909,16 +910,21 @@ PaintStroke *paint_stroke_new(bContext *C,
void paint_stroke_free(bContext *C, wmOperator *op)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (rv3d) {
+ rv3d->rflag &= ~RV3D_PAINTING;
+ }
+
+ BKE_paint_set_overlay_override(0);
+
PaintStroke *stroke = op->customdata;
- UnifiedPaintSettings *ups = stroke->ups;
+ if (stroke == NULL) {
+ return;
+ }
+ UnifiedPaintSettings *ups = stroke->ups;
ups->draw_anchored = false;
ups->stroke_active = false;
- if (rv3d) {
- rv3d->rflag &= ~RV3D_PAINTING;
- }
-
if (stroke->timer) {
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), stroke->timer);
}
@@ -933,7 +939,6 @@ void paint_stroke_free(bContext *C, wmOperator *op)
BLI_freelistN(&stroke->line);
- BKE_paint_set_overlay_override(0);
MEM_SAFE_FREE(op->customdata);
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 3554a6cc546..77c95c6acb3 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -2072,9 +2072,9 @@ static void calculate_average_weight(SculptThreadedTaskData *data,
struct WPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
data->custom_data = accum;
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (data->sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings);
uint accum_len = 0;
double accum_weight = 0.0;
@@ -2120,22 +2120,22 @@ static void wpaint_paint_leaves(bContext *C,
data.strength = BKE_brush_weight_get(scene, brush);
/* NOTE: current mirroring code cannot be run in parallel */
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, !(me->editflag & ME_EDIT_MIRROR_X), totnode);
switch ((eBrushWeightPaintTool)brush->weightpaint_tool) {
case WPAINT_TOOL_AVERAGE:
calculate_average_weight(&data, nodes, totnode);
- BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
break;
case WPAINT_TOOL_SMEAR:
- BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings);
break;
case WPAINT_TOOL_BLUR:
- BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings);
break;
case WPAINT_TOOL_DRAW:
- BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
break;
}
}
@@ -2587,11 +2587,6 @@ void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
* - revise whether op->customdata should be added in object, in set_vpaint
*/
-typedef struct PolyFaceMap {
- struct PolyFaceMap *next, *prev;
- int facenr;
-} PolyFaceMap;
-
struct VPaintData {
ViewContext vc;
struct NormalAnglePrecalc normal_angle_precalc;
@@ -3131,9 +3126,9 @@ static void calculate_average_color(SculptThreadedTaskData *data,
struct VPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
data->custom_data = accum;
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
- BLI_task_parallel_range(0, totnode, data, do_vpaint_brush_calc_average_color_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, data, do_vpaint_brush_calc_average_color_cb_ex, &settings);
uint accum_len = 0;
uint accum_value[3] = {0};
@@ -3177,21 +3172,21 @@ static void vpaint_paint_leaves(bContext *C,
.lcol = (uint *)me->mloopcol,
.me = me,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
switch ((eBrushVertexPaintTool)brush->vertexpaint_tool) {
case VPAINT_TOOL_AVERAGE:
calculate_average_color(&data, nodes, totnode);
- BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
break;
case VPAINT_TOOL_BLUR:
- BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_blur_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_blur_task_cb_ex, &settings);
break;
case VPAINT_TOOL_SMEAR:
- BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_smear_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_smear_task_cb_ex, &settings);
break;
case VPAINT_TOOL_DRAW:
- BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings);
break;
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index b9d621fc1fb..d2d424745da 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -64,6 +64,7 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_subdiv_ccg.h"
#include "BKE_subsurf.h"
#include "DEG_depsgraph.h"
@@ -185,7 +186,6 @@ static float sculpt_vertex_mask_get(SculptSession *ss, int index)
static int sculpt_active_vertex_get(SculptSession *ss)
{
- BLI_assert(BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
return ss->active_vertex_index;
@@ -211,14 +211,19 @@ static void sculpt_active_vertex_normal_get(SculptSession *ss, float normal[3])
#define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
typedef struct SculptVertexNeighborIter {
+ /* Storage */
int *neighbors;
int size;
int capacity;
-
int neighbors_fixed[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY];
- int index;
+ /* Internal iterator. */
+ int num_duplicates;
int i;
+
+ /* Public */
+ int index;
+ bool is_duplicate;
} SculptVertexNeighborIter;
static void sculpt_vertex_neighbor_add(SculptVertexNeighborIter *iter, int neighbor_index)
@@ -254,6 +259,7 @@ static void sculpt_vertex_neighbors_get_bmesh(SculptSession *ss,
BMIter liter;
BMLoop *l;
iter->size = 0;
+ iter->num_duplicates = 0;
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
@@ -276,6 +282,7 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
int i;
MeshElemMap *vert_map = &ss->pmap[(int)index];
iter->size = 0;
+ iter->num_duplicates = 0;
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
@@ -293,20 +300,44 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
}
}
-static void sculpt_vertex_neighbors_get_grids(SculptSession *UNUSED(ss),
- int UNUSED(index),
+static void sculpt_vertex_neighbors_get_grids(SculptSession *ss,
+ const int index,
+ const bool include_duplicates,
SculptVertexNeighborIter *iter)
{
- /* TODO: implement this for multires. It might also be worth changing this
- * iterator to provide a coordinate and mask pointer directly for effiency,
- * rather than converting back and forth between CCGElem and global index. */
+ /* TODO: optimize this. We could fill SculptVertexNeighborIter directly,
+ * maybe provide coordinate and mask pointers directly rather than converting
+ * back and forth between CCGElem and global index. */
+ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
+ const int grid_index = index / key->grid_area;
+ const int vertex_index = index - grid_index * key->grid_area;
+
+ SubdivCCGCoord coord = {.grid_index = grid_index,
+ .x = vertex_index % key->grid_size,
+ .y = vertex_index / key->grid_size};
+
+ SubdivCCGNeighbors neighbors;
+ BKE_subdiv_ccg_neighbor_coords_get(ss->subdiv_ccg, &coord, include_duplicates, &neighbors);
+
iter->size = 0;
+ iter->num_duplicates = neighbors.num_duplicates;
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
+
+ for (int i = 0; i < neighbors.size; i++) {
+ sculpt_vertex_neighbor_add(iter,
+ neighbors.coords[i].grid_index * key->grid_area +
+ neighbors.coords[i].y * key->grid_size + neighbors.coords[i].x);
+ }
+
+ if (neighbors.coords != neighbors.coords_fixed) {
+ MEM_freeN(neighbors.coords);
+ }
}
static void sculpt_vertex_neighbors_get(SculptSession *ss,
- int index,
+ const int index,
+ const bool include_duplicates,
SculptVertexNeighborIter *iter)
{
switch (BKE_pbvh_type(ss->pbvh)) {
@@ -317,17 +348,28 @@ static void sculpt_vertex_neighbors_get(SculptSession *ss,
sculpt_vertex_neighbors_get_bmesh(ss, index, iter);
return;
case PBVH_GRIDS:
- sculpt_vertex_neighbors_get_grids(ss, index, iter);
+ sculpt_vertex_neighbors_get_grids(ss, index, include_duplicates, iter);
return;
}
}
+/* Iterator over neighboring vertices. */
#define sculpt_vertex_neighbors_iter_begin(ss, v_index, neighbor_iterator) \
- sculpt_vertex_neighbors_get(ss, v_index, &neighbor_iterator); \
+ sculpt_vertex_neighbors_get(ss, v_index, false, &neighbor_iterator); \
for (neighbor_iterator.i = 0; neighbor_iterator.i < neighbor_iterator.size; \
neighbor_iterator.i++) { \
neighbor_iterator.index = ni.neighbors[ni.i];
+/* Iterate over neighboring and duplicate vertices (for PBVH_GRIDS). Duplicates come
+ * first since they are nearest for floodfill. */
+#define sculpt_vertex_duplicates_and_neighbors_iter_begin(ss, v_index, neighbor_iterator) \
+ sculpt_vertex_neighbors_get(ss, v_index, true, &neighbor_iterator); \
+ for (neighbor_iterator.i = neighbor_iterator.size - 1; neighbor_iterator.i >= 0; \
+ neighbor_iterator.i--) { \
+ neighbor_iterator.index = ni.neighbors[ni.i]; \
+ neighbor_iterator.is_duplicate = (ni.i >= \
+ neighbor_iterator.size - neighbor_iterator.num_duplicates);
+
#define sculpt_vertex_neighbors_iter_end(neighbor_iterator) \
} \
if (neighbor_iterator.neighbors != neighbor_iterator.neighbors_fixed) { \
@@ -381,16 +423,19 @@ static void do_nearest_vertex_get_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void nearest_vertex_get_finalize(void *__restrict userdata, void *__restrict tls)
+static void nearest_vertex_get_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- SculptThreadedTaskData *data = userdata;
- NearestVertexTLSData *nvtd = tls;
- if (data->nearest_vertex_index == -1) {
- data->nearest_vertex_index = nvtd->nearest_vertex_index;
+ NearestVertexTLSData *join = chunk_join;
+ NearestVertexTLSData *nvtd = chunk;
+ if (join->nearest_vertex_index == -1) {
+ join->nearest_vertex_index = nvtd->nearest_vertex_index;
+ join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
}
- else if (nvtd->nearest_vertex_distance_squared < data->nearest_vertex_distance_squared) {
- data->nearest_vertex_index = nvtd->nearest_vertex_index;
- data->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
+ else if (nvtd->nearest_vertex_distance_squared < join->nearest_vertex_distance_squared) {
+ join->nearest_vertex_index = nvtd->nearest_vertex_index;
+ join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
}
}
@@ -417,25 +462,23 @@ static int sculpt_nearest_vertex_get(
.ob = ob,
.nodes = nodes,
.max_distance_squared = max_distance * max_distance,
- .nearest_vertex_index = -1,
};
copy_v3_v3(task_data.nearest_vertex_search_co, co);
- task_data.nearest_vertex_distance_squared = FLT_MAX;
NearestVertexTLSData nvtd;
nvtd.nearest_vertex_index = -1;
nvtd.nearest_vertex_distance_squared = FLT_MAX;
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- settings.func_finalize = nearest_vertex_get_finalize;
+ settings.func_reduce = nearest_vertex_get_reduce;
settings.userdata_chunk = &nvtd;
settings.userdata_chunk_size = sizeof(NearestVertexTLSData);
- BLI_task_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings);
MEM_SAFE_FREE(nodes);
- return task_data.nearest_vertex_index;
+ return nvtd.nearest_vertex_index;
}
static bool is_symmetry_iteration_valid(char i, char symm)
@@ -470,28 +513,18 @@ typedef struct SculptFloodFill {
char *visited_vertices;
} SculptFloodFill;
-typedef struct SculptFloodFillIterator {
- int v;
- int it;
- float edge_factor;
-} SculptFloodFillIterator;
-
static void sculpt_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
{
int vertex_count = sculpt_vertex_count_get(ss);
sculpt_vertex_random_access_init(ss);
- flood->queue = BLI_gsqueue_new(sizeof(SculptFloodFillIterator));
+ flood->queue = BLI_gsqueue_new(sizeof(int));
flood->visited_vertices = MEM_callocN(vertex_count * sizeof(char), "visited vertices");
}
static void sculpt_floodfill_add_initial(SculptFloodFill *flood, int index)
{
- SculptFloodFillIterator mevit;
- mevit.v = index;
- mevit.it = 0;
- mevit.edge_factor = 1.0f;
- BLI_gsqueue_push(flood->queue, &mevit);
+ BLI_gsqueue_push(flood->queue, &index);
}
static void sculpt_floodfill_add_active(
@@ -518,32 +551,24 @@ static void sculpt_floodfill_add_active(
}
}
-static void sculpt_floodfill_execute(SculptSession *ss,
- SculptFloodFill *flood,
- bool (*func)(SculptSession *ss,
- const SculptFloodFillIterator *from,
- SculptFloodFillIterator *to,
- void *userdata),
- void *userdata)
+static void sculpt_floodfill_execute(
+ SculptSession *ss,
+ SculptFloodFill *flood,
+ bool (*func)(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata),
+ void *userdata)
{
- /* TODO: multires support, taking into account duplicate vertices and
- * correctly handling them in the pose, automask and mask expand callbacks. */
while (!BLI_gsqueue_is_empty(flood->queue)) {
- SculptFloodFillIterator from;
- BLI_gsqueue_pop(flood->queue, &from);
+ int from_v;
+ BLI_gsqueue_pop(flood->queue, &from_v);
SculptVertexNeighborIter ni;
- sculpt_vertex_neighbors_iter_begin(ss, from.v, ni)
+ sculpt_vertex_duplicates_and_neighbors_iter_begin(ss, from_v, ni)
{
- if (flood->visited_vertices[ni.index] == 0) {
- flood->visited_vertices[ni.index] = 1;
+ const int to_v = ni.index;
+ if (flood->visited_vertices[to_v] == 0) {
+ flood->visited_vertices[to_v] = 1;
- SculptFloodFillIterator to;
- to.v = ni.index;
- to.it = from.it + 1;
- to.edge_factor = 0.0f;
-
- if (func(ss, &from, &to, userdata)) {
- BLI_gsqueue_push(flood->queue, &to);
+ if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) {
+ BLI_gsqueue_push(flood->queue, &to_v);
}
}
}
@@ -912,9 +937,9 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP) && !ss->bm, totnode);
- BLI_task_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings);
MEM_SAFE_FREE(nodes);
}
@@ -1097,9 +1122,8 @@ bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float loca
local_co[1] = fabsf(local_co[1]);
local_co[2] = fabsf(local_co[2]);
+ const float p = 8.0f;
if (local_co[0] <= side && local_co[1] <= side && local_co[2] <= side) {
- float p = 4.0f;
-
test->dist = ((powf(local_co[0], p) + powf(local_co[1], p) + powf(local_co[2], p)) /
powf(side, p));
@@ -1194,11 +1218,6 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test,
static bool sculpt_automasking_enabled(SculptSession *ss, const Brush *br)
{
- // REMOVE WITH PBVH_GRIDS
- if (ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return false;
- }
-
if (sculpt_stroke_is_dynamic_topology(ss, br)) {
return false;
}
@@ -1229,7 +1248,7 @@ static void sculpt_automasking_end(Object *ob)
static bool sculpt_automasking_is_constrained_by_radius(Brush *br)
{
/* 2D falloff is not constrained by radius */
- if (br->falloff_shape & BRUSH_AIRBRUSH) {
+ if (br->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
return false;
}
@@ -1247,17 +1266,15 @@ typedef struct AutomaskFloodFillData {
char symm;
} AutomaskFloodFillData;
-static bool automask_floodfill_cb(SculptSession *ss,
- const SculptFloodFillIterator *UNUSED(from),
- SculptFloodFillIterator *to,
- void *userdata)
+static bool automask_floodfill_cb(
+ SculptSession *ss, int UNUSED(from_v), int to_v, bool UNUSED(is_duplicate), void *userdata)
{
AutomaskFloodFillData *data = userdata;
- data->automask_factor[to->v] = 1.0f;
+ data->automask_factor[to_v] = 1.0f;
return (!data->use_radius ||
sculpt_is_vertex_inside_brush_radius_symm(
- sculpt_vertex_co_get(ss, to->v), data->location, data->radius, data->symm));
+ sculpt_vertex_co_get(ss, to_v), data->location, data->radius, data->symm));
}
static float *sculpt_topology_automasking_init(Sculpt *sd, Object *ob, float *automask_factor)
@@ -1396,9 +1413,10 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
* \{ */
typedef struct AreaNormalCenterTLSData {
- float private_co[2][3];
- float private_no[2][3];
- int private_count[2];
+ /* 0=towards view, 1=flipped */
+ float area_cos[2][3];
+ float area_nos[2][3];
+ int area_count[2];
} AreaNormalCenterTLSData;
static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
@@ -1408,8 +1426,8 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
AreaNormalCenterTLSData *anctd = tls->userdata_chunk;
- float(*area_nos)[3] = data->area_nos;
- float(*area_cos)[3] = data->area_cos;
+ const bool use_area_nos = data->use_area_nos;
+ const bool use_area_cos = data->use_area_cos;
PBVHVertexIter vd;
SculptUndoNode *unode = NULL;
@@ -1428,7 +1446,10 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
/* Update the test radius to sample the normal using the normal radius of the brush */
if (data->brush->ob_mode == OB_MODE_SCULPT) {
float test_radius = sqrtf(test.radius_squared);
- test_radius *= data->brush->normal_radius_factor;
+ /* Layer brush produces artifacts with normal radius */
+ if (!(ss->cache && data->brush->sculpt_tool == SCULPT_TOOL_LAYER)) {
+ test_radius *= data->brush->normal_radius_factor;
+ }
test.radius_squared = test_radius * test_radius;
}
@@ -1459,13 +1480,13 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
normal_tri_v3(no, UNPACK3(co_tri));
flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
- if (area_cos) {
- add_v3_v3(anctd->private_co[flip_index], co);
+ if (use_area_cos) {
+ add_v3_v3(anctd->area_cos[flip_index], co);
}
- if (area_nos) {
- add_v3_v3(anctd->private_no[flip_index], no);
+ if (use_area_nos) {
+ add_v3_v3(anctd->area_nos[flip_index], no);
}
- anctd->private_count[flip_index] += 1;
+ anctd->area_count[flip_index] += 1;
}
}
}
@@ -1511,40 +1532,37 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <=
0.0f);
- if (area_cos) {
- add_v3_v3(anctd->private_co[flip_index], co);
+ if (use_area_cos) {
+ add_v3_v3(anctd->area_cos[flip_index], co);
}
- if (area_nos) {
- add_v3_v3(anctd->private_no[flip_index], no);
+ if (use_area_nos) {
+ add_v3_v3(anctd->area_nos[flip_index], no);
}
- anctd->private_count[flip_index] += 1;
+ anctd->area_count[flip_index] += 1;
}
}
BKE_pbvh_vertex_iter_end;
}
}
-static void calc_area_normal_and_center_finalize(void *__restrict userdata, void *__restrict tls)
+static void calc_area_normal_and_center_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- SculptThreadedTaskData *data = userdata;
- AreaNormalCenterTLSData *anctd = tls;
- float(*area_nos)[3] = data->area_nos;
- float(*area_cos)[3] = data->area_cos;
+ AreaNormalCenterTLSData *join = chunk_join;
+ AreaNormalCenterTLSData *anctd = chunk;
+
/* for flatten center */
- if (area_cos) {
- add_v3_v3(area_cos[0], anctd->private_co[0]);
- add_v3_v3(area_cos[1], anctd->private_co[1]);
- }
+ add_v3_v3(join->area_cos[0], anctd->area_cos[0]);
+ add_v3_v3(join->area_cos[1], anctd->area_cos[1]);
/* for area normal */
- if (area_nos) {
- add_v3_v3(area_nos[0], anctd->private_no[0]);
- add_v3_v3(area_nos[1], anctd->private_no[1]);
- }
+ add_v3_v3(join->area_nos[0], anctd->area_nos[0]);
+ add_v3_v3(join->area_nos[1], anctd->area_nos[1]);
/* weights */
- data->count[0] += anctd->private_count[0];
- data->count[1] += anctd->private_count[1];
+ join->area_count[0] += anctd->area_count[0];
+ join->area_count[1] += anctd->area_count[1];
}
static void calc_area_center(
@@ -1555,11 +1573,6 @@ static void calc_area_center(
const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
int n;
- /* 0=towards view, 1=flipped */
- float area_cos[2][3] = {{0.0f}};
-
- int count[2] = {0};
-
/* Intentionally set 'sd' to NULL since we share logic with vertex paint. */
SculptThreadedTaskData data = {
.sd = NULL,
@@ -1568,24 +1581,22 @@ static void calc_area_center(
.nodes = nodes,
.totnode = totnode,
.has_bm_orco = has_bm_orco,
- .area_cos = area_cos,
- .area_nos = NULL,
- .count = count,
+ .use_area_cos = true,
};
AreaNormalCenterTLSData anctd = {{{0}}};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- settings.func_finalize = calc_area_normal_and_center_finalize;
+ settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
- BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
/* for flatten center */
- for (n = 0; n < ARRAY_SIZE(area_cos); n++) {
- if (count[n] != 0) {
- mul_v3_v3fl(r_area_co, area_cos[n], 1.0f / count[n]);
+ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) {
+ if (anctd.area_count[n] != 0) {
+ mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.area_count[n]);
break;
}
}
@@ -1613,11 +1624,6 @@ bool sculpt_pbvh_calc_area_normal(const Brush *brush,
SculptSession *ss = ob->sculpt;
const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
- /* 0=towards view, 1=flipped */
- float area_nos[2][3] = {{0.0f}};
-
- int count[2] = {0};
-
/* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
SculptThreadedTaskData data = {
.sd = NULL,
@@ -1626,24 +1632,22 @@ bool sculpt_pbvh_calc_area_normal(const Brush *brush,
.nodes = nodes,
.totnode = totnode,
.has_bm_orco = has_bm_orco,
- .area_cos = NULL,
- .area_nos = area_nos,
- .count = count,
+ .use_area_nos = true,
.any_vertex_sampled = false,
};
AreaNormalCenterTLSData anctd = {{{0}}};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, use_threading, totnode);
- settings.func_finalize = calc_area_normal_and_center_finalize;
+ settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
- BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
/* for area normal */
- for (int i = 0; i < ARRAY_SIZE(area_nos); i++) {
- if (normalize_v3_v3(r_area_no, area_nos[i]) != 0.0f) {
+ for (int i = 0; i < ARRAY_SIZE(anctd.area_nos); i++) {
+ if (normalize_v3_v3(r_area_no, anctd.area_nos[i]) != 0.0f) {
break;
}
}
@@ -1661,12 +1665,6 @@ static void calc_area_normal_and_center(
const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush);
int n;
- /* 0=towards view, 1=flipped */
- float area_cos[2][3] = {{0.0f}};
- float area_nos[2][3] = {{0.0f}};
-
- int count[2] = {0};
-
/* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
SculptThreadedTaskData data = {
.sd = NULL,
@@ -1675,24 +1673,23 @@ static void calc_area_normal_and_center(
.nodes = nodes,
.totnode = totnode,
.has_bm_orco = has_bm_orco,
- .area_cos = area_cos,
- .area_nos = area_nos,
- .count = count,
+ .use_area_cos = true,
+ .use_area_nos = true,
};
AreaNormalCenterTLSData anctd = {{{0}}};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- settings.func_finalize = calc_area_normal_and_center_finalize;
+ settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
- BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
/* for flatten center */
- for (n = 0; n < ARRAY_SIZE(area_cos); n++) {
- if (count[n] != 0) {
- mul_v3_v3fl(r_area_co, area_cos[n], 1.0f / count[n]);
+ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) {
+ if (anctd.area_count[n] != 0) {
+ mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.area_count[n]);
break;
}
}
@@ -1701,8 +1698,8 @@ static void calc_area_normal_and_center(
}
/* for area normal */
- for (n = 0; n < ARRAY_SIZE(area_nos); n++) {
- if (normalize_v3_v3(r_area_no, area_nos[n]) != 0.0f) {
+ for (n = 0; n < ARRAY_SIZE(anctd.area_nos); n++) {
+ if (normalize_v3_v3(r_area_no, anctd.area_nos[n]) != 0.0f) {
break;
}
}
@@ -1736,11 +1733,13 @@ static float brush_strength(const Sculpt *sd,
switch (brush->sculpt_tool) {
case SCULPT_TOOL_CLAY:
- case SCULPT_TOOL_CLAY_STRIPS:
case SCULPT_TOOL_DRAW:
case SCULPT_TOOL_DRAW_SHARP:
case SCULPT_TOOL_LAYER:
return alpha * flip * pressure * overlap * feather;
+ case SCULPT_TOOL_CLAY_STRIPS:
+ /* Clay Strips needs extra strength to compensate for its default normal radius */
+ return alpha * flip * pressure * overlap * feather * 1.3f;
case SCULPT_TOOL_MASK:
overlap = (1 + overlap) / 2;
@@ -2083,9 +2082,15 @@ static void update_sculpt_normal(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
{
const Brush *brush = BKE_paint_brush(&sd->paint);
StrokeCache *cache = ob->sculpt->cache;
+ /* Grab brush does not update the sculpt normal during a stroke */
+ const bool update_normal = !(brush->flag & BRUSH_ORIGINAL_NORMAL) &&
+ !(brush->sculpt_tool == SCULPT_TOOL_GRAB) &&
+ !(brush->sculpt_tool == SCULPT_TOOL_ELASTIC_DEFORM) &&
+ !(brush->sculpt_tool == SCULPT_TOOL_SNAKE_HOOK &&
+ cache->normal_weight > 0.0f);
if (cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0 &&
- (cache->first_time || !(brush->flag & BRUSH_ORIGINAL_NORMAL))) {
+ (cache->first_time || update_normal)) {
calc_sculpt_normal(sd, ob, nodes, totnode, cache->sculpt_normal);
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
project_plane_v3_v3v3(cache->sculpt_normal, cache->sculpt_normal, cache->view_normal);
@@ -2796,7 +2801,7 @@ static void smooth(Sculpt *sd,
.strength = strength,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
switch (type) {
@@ -2814,16 +2819,16 @@ static void smooth(Sculpt *sd,
settings.userdata_chunk = data_chunk;
settings.userdata_chunk_size = size;
- BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings);
MEM_freeN(data_chunk);
break;
}
case PBVH_FACES:
- BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings);
break;
case PBVH_BMESH:
- BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings);
break;
}
@@ -2855,10 +2860,10 @@ static void bmesh_topology_rake(
.nodes = nodes,
.strength = factor,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings);
}
}
@@ -2912,9 +2917,9 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings);
}
static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
@@ -2999,9 +3004,9 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.offset = offset,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings);
}
static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
@@ -3075,9 +3080,9 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
.offset = offset,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings);
}
/**
@@ -3191,9 +3196,9 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
.flippedbstrength = flippedbstrength,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings);
}
static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
@@ -3253,9 +3258,9 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings);
}
static void do_grab_brush_task_cb_ex(void *__restrict userdata,
@@ -3325,9 +3330,9 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.grab_delta = grab_delta,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings);
}
/* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity
@@ -3566,6 +3571,10 @@ static void do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
+ if (ss->cache->normal_weight > 0.0f) {
+ sculpt_project_v3_normal_align(ss, ss->cache->normal_weight, grab_delta);
+ }
+
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
@@ -3574,9 +3583,9 @@ static void do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
.grab_delta = grab_delta,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings);
}
static void do_pose_brush_task_cb_ex(void *__restrict userdata,
@@ -3628,10 +3637,6 @@ static void do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
float pose_initial_co[3];
float transform_rot[4][4], transform_trans[4][4], transform_trans_inv[4][4];
- if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return;
- }
-
copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
copy_v3_v3(pose_origin, ss->cache->pose_origin);
@@ -3667,14 +3672,14 @@ static void do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.transform_trans_inv = transform_trans_inv,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings);
}
typedef struct PoseGrowFactorTLSData {
float pos_avg[3];
- int tot_pos_avg;
+ int pos_count;
} PoseGrowFactorTLSData;
static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata,
@@ -3703,7 +3708,7 @@ static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata,
data->pose_factor[vd.index] = max;
if (check_vertex_pivot_symmetry(vd.co, active_co, symm)) {
add_v3_v3(gftd->pos_avg, vd.co);
- gftd->tot_pos_avg++;
+ gftd->pos_count++;
}
}
}
@@ -3711,12 +3716,14 @@ static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void pose_brush_grow_factor_finalize(void *__restrict userdata, void *__restrict tls)
+static void pose_brush_grow_factor_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- SculptThreadedTaskData *data = userdata;
- PoseGrowFactorTLSData *gftd = tls;
- add_v3_v3(data->tot_pos_avg, gftd->pos_avg);
- data->tot_pos_count += gftd->tot_pos_avg;
+ PoseGrowFactorTLSData *join = chunk_join;
+ PoseGrowFactorTLSData *gftd = chunk;
+ add_v3_v3(join->pos_avg, gftd->pos_avg);
+ join->pos_count += gftd->pos_count;
}
/* Grow the factor until its boundary is near to the offset pose origin */
@@ -3735,12 +3742,12 @@ static void sculpt_pose_grow_pose_factor(
.totnode = totnode,
.pose_factor = pose_factor,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
PoseGrowFactorTLSData gftd;
- gftd.tot_pos_avg = 0;
+ gftd.pos_count = 0;
zero_v3(gftd.pos_avg);
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- settings.func_finalize = pose_brush_grow_factor_finalize;
+ settings.func_reduce = pose_brush_grow_factor_reduce;
settings.userdata_chunk = &gftd;
settings.userdata_chunk_size = sizeof(PoseGrowFactorTLSData);
@@ -3748,15 +3755,13 @@ static void sculpt_pose_grow_pose_factor(
float prev_len = FLT_MAX;
data.prev_mask = MEM_mallocN(sculpt_vertex_count_get(ss) * sizeof(float), "prev mask");
while (grow_next_iteration) {
- zero_v3(data.tot_pos_avg);
- data.tot_pos_count = 0;
zero_v3(gftd.pos_avg);
- gftd.tot_pos_avg = 0;
+ gftd.pos_count = 0;
memcpy(data.prev_mask, pose_factor, sculpt_vertex_count_get(ss) * sizeof(float));
- BLI_task_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings);
- if (data.tot_pos_count != 0) {
- mul_v3_fl(data.tot_pos_avg, 1.0f / (float)data.tot_pos_count);
- float len = len_v3v3(data.tot_pos_avg, pose_origin);
+ BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings);
+ if (gftd.pos_count != 0) {
+ mul_v3_fl(gftd.pos_avg, 1.0f / (float)gftd.pos_count);
+ float len = len_v3v3(gftd.pos_avg, pose_origin);
if (len < prev_len) {
prev_len = len;
grow_next_iteration = true;
@@ -3806,25 +3811,25 @@ typedef struct PoseFloodFillData {
int tot_co;
} PoseFloodFillData;
-static bool pose_floodfill_cb(SculptSession *ss,
- const SculptFloodFillIterator *UNUSED(from),
- SculptFloodFillIterator *to,
- void *userdata)
+static bool pose_floodfill_cb(
+ SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata)
{
PoseFloodFillData *data = userdata;
if (data->pose_factor) {
- data->pose_factor[to->v] = 1.0f;
+ data->pose_factor[to_v] = 1.0f;
}
- const float *co = sculpt_vertex_co_get(ss, to->v);
+ const float *co = sculpt_vertex_co_get(ss, to_v);
if (sculpt_pose_brush_is_vertex_inside_brush_radius(
co, data->pose_initial_co, data->radius, data->symm)) {
return true;
}
else if (check_vertex_pivot_symmetry(co, data->pose_initial_co, data->symm)) {
- add_v3_v3(data->pose_origin, co);
- data->tot_co++;
+ if (!is_duplicate) {
+ add_v3_v3(data->pose_origin, co);
+ data->tot_co++;
+ }
}
return false;
@@ -3925,9 +3930,9 @@ static void sculpt_pose_brush_init(
/* Smooth the pose brush factor for cleaner deformation */
for (int i = 0; i < 4; i++) {
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings);
}
MEM_SAFE_FREE(nodes);
@@ -3995,9 +4000,9 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
.cono = cono,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings);
}
static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
@@ -4116,9 +4121,9 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
.grab_delta = grab_delta,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings);
}
static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
@@ -4188,9 +4193,9 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
.cono = cono,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings);
}
static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
@@ -4261,9 +4266,9 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
.angle = angle,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings);
}
static void do_layer_brush_task_cb_ex(void *__restrict userdata,
@@ -4358,9 +4363,9 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
};
BLI_mutex_init(&data.mutex);
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings);
BLI_mutex_end(&data.mutex);
}
@@ -4426,9 +4431,9 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings);
}
static void calc_sculpt_plane(
@@ -4635,9 +4640,9 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
.area_co = area_co,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings);
}
static void do_clay_brush_task_cb_ex(void *__restrict userdata,
@@ -4733,9 +4738,9 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.area_co = area_co,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings);
}
static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
@@ -4863,9 +4868,9 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
.mat = mat,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings);
}
static void do_fill_brush_task_cb_ex(void *__restrict userdata,
@@ -4956,9 +4961,9 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.area_co = area_co,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings);
}
static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
@@ -5048,9 +5053,9 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
.area_co = area_co,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings);
}
static void do_gravity_task_cb_ex(void *__restrict userdata,
@@ -5117,9 +5122,9 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl
.offset = offset,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings);
}
void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
@@ -5271,7 +5276,12 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
else {
const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true :
ss->cache->original;
- const float radius_scale = 1.0f;
+ float radius_scale = 1.0f;
+ /* With these options enabled not all required nodes are inside the original brush radius, so
+ * the brush can produce artifacts in some situations */
+ if (brush->sculpt_tool == SCULPT_TOOL_DRAW && brush->flag & BRUSH_ORIGINAL_NORMAL) {
+ radius_scale = 2.0f;
+ }
nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode);
}
@@ -5286,9 +5296,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
if (sculpt_brush_needs_normal(ss, brush)) {
update_sculpt_normal(sd, ob, nodes, totnode);
@@ -5306,9 +5316,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
if (brush->sculpt_tool == SCULPT_TOOL_POSE && ss->cache->first_time &&
ss->cache->mirror_symmetry_pass == 0) {
- if (BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS) {
- sculpt_pose_brush_init(sd, ob, ss, brush, ss->cache->location, ss->cache->radius);
- }
+ sculpt_pose_brush_init(sd, ob, ss, brush, ss->cache->location, ss->cache->radius);
}
/* Apply one type of brush action */
@@ -5425,7 +5433,7 @@ static void sculpt_flush_pbvhvert_deform(Object *ob, PBVHVertexIter *vd)
copy_v3_v3(ss->deform_cos[index], vd->co);
copy_v3_v3(ss->orig_cos[index], newco);
- if (!ss->kb) {
+ if (!ss->shapekey_active) {
copy_v3_v3(me->mvert[index].co, newco);
}
}
@@ -5481,7 +5489,7 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
sculpt_clip(sd, ss, vd.co, val);
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
sculpt_flush_pbvhvert_deform(ob, &vd);
}
}
@@ -5508,9 +5516,9 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
.nodes = nodes,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings);
}
MEM_SAFE_FREE(nodes);
@@ -5532,7 +5540,7 @@ static void sculpt_update_keyblock(Object *ob)
}
if (vertCos) {
- sculpt_vertcos_to_key(ob, ss->kb, vertCos);
+ sculpt_vertcos_to_key(ob, ss->shapekey_active, vertCos);
if (vertCos != ss->orig_cos) {
MEM_freeN(vertCos);
@@ -5578,7 +5586,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_use
PBVHNode **nodes;
float(*vertCos)[3] = NULL;
- if (ss->kb) {
+ if (ss->shapekey_active) {
vertCos = MEM_mallocN(sizeof(*vertCos) * me->totvert, "flushStrokeDeofrm keyVerts");
/* mesh could have isolated verts which wouldn't be in BVH,
@@ -5598,12 +5606,12 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_use
.vertCos = vertCos,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, sculpt_flush_stroke_deform_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, sculpt_flush_stroke_deform_task_cb, &settings);
if (vertCos) {
- sculpt_vertcos_to_key(ob, ss->kb, vertCos);
+ sculpt_vertcos_to_key(ob, ss->shapekey_active, vertCos);
MEM_freeN(vertCos);
}
@@ -5614,7 +5622,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_use
* after applying coords from keyblock on base mesh */
BKE_mesh_calc_normals(me);
}
- else if (ss->kb) {
+ else if (ss->shapekey_active) {
sculpt_update_keyblock(ob);
}
}
@@ -6378,7 +6386,8 @@ static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob, const B
View3D *v3d = CTX_wm_view3d(C);
bool need_pmap = sculpt_needs_conectivity_info(brush, ss, 0);
- if (ss->kb || ss->modifiers_active || (!BKE_sculptsession_use_pbvh_draw(ob, v3d) && need_pmap)) {
+ if (ss->shapekey_active || ss->deform_modifiers_active ||
+ (!BKE_sculptsession_use_pbvh_draw(ob, v3d) && need_pmap)) {
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
BKE_sculpt_update_object_for_edit(depsgraph, ob, need_pmap, false);
}
@@ -6559,13 +6568,7 @@ bool sculpt_cursor_geometry_info_update(bContext *C,
/* Update the active vertex of the SculptSession */
ss->active_vertex_index = srd.active_vertex_index;
-
- if (!ss->multires) {
- copy_v3_v3(out->active_vertex_co, sculpt_active_vertex_co_get(ss));
- }
- else {
- zero_v3(out->active_vertex_co);
- }
+ copy_v3_v3(out->active_vertex_co, sculpt_active_vertex_co_get(ss));
copy_v3_v3(out->location, ray_normal);
mul_v3_fl(out->location, srd.depth);
@@ -6877,7 +6880,7 @@ static void sculpt_flush_update_done(const bContext *C, Object *ob, SculptUpdate
/* optimization: if there is locked key and active modifiers present in */
/* the stack, keyblock is updating at each step. otherwise we could update */
/* keyblock only when stroke is finished */
- if (ss->kb && !ss->modifiers_active) {
+ if (ss->shapekey_active && !ss->deform_modifiers_active) {
sculpt_update_keyblock(ob);
}
@@ -6970,10 +6973,10 @@ static void sculpt_stroke_update_step(bContext *C,
* Same applies to the DEG_id_tag_update() invoked from
* sculpt_flush_update_step().
*/
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
sculpt_flush_stroke_deform(sd, ob, sculpt_tool_is_proxy_used(brush->sculpt_tool));
}
- else if (ss->kb) {
+ else if (ss->shapekey_active) {
sculpt_update_keyblock(ob);
}
@@ -8146,43 +8149,36 @@ static void filter_cache_init_task_cb(void *__restrict userdata,
const TaskParallelTLS *__restrict UNUSED(tls))
{
SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
PBVHNode *node = data->nodes[i];
- PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
- {
- if (!vd.mask || (vd.mask && *vd.mask < 1.0f)) {
- data->node_mask[i] = 1;
- }
- }
- BKE_pbvh_vertex_iter_end;
-
- if (data->node_mask[i] == 1) {
- sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
- }
+ sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
}
static void sculpt_filter_cache_init(Object *ob, Sculpt *sd)
{
SculptSession *ss = ob->sculpt;
PBVH *pbvh = ob->sculpt->pbvh;
- PBVHNode **nodes;
- int totnode;
ss->filter_cache = MEM_callocN(sizeof(FilterCache), "filter cache");
ss->filter_cache->random_seed = rand();
+ float center[3] = {0.0f};
SculptSearchSphereData search_data = {
.original = true,
- };
- BKE_pbvh_search_gather(pbvh, NULL, &search_data, &nodes, &totnode);
+ .center = center,
+ .radius_squared = FLT_MAX,
+ .ignore_fully_masked = true,
- int *node_mask = MEM_callocN((unsigned int)totnode * sizeof(int), "node mask");
+ };
+ BKE_pbvh_search_gather(pbvh,
+ sculpt_search_sphere_cb,
+ &search_data,
+ &ss->filter_cache->nodes,
+ &ss->filter_cache->totnode);
- for (int i = 0; i < totnode; i++) {
- BKE_pbvh_node_mark_normals_update(nodes[i]);
+ for (int i = 0; i < ss->filter_cache->totnode; i++) {
+ BKE_pbvh_node_mark_normals_update(ss->filter_cache->nodes[i]);
}
/* mesh->runtime.subdiv_ccg is not available. Updating of the normals is done during drawing.
@@ -8194,40 +8190,14 @@ static void sculpt_filter_cache_init(Object *ob, Sculpt *sd)
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
- .nodes = nodes,
- .node_mask = node_mask,
+ .nodes = ss->filter_cache->nodes,
};
- TaskParallelSettings settings;
- BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, filter_cache_init_task_cb, &settings);
-
- int tot_active_nodes = 0;
- int active_node_index = 0;
- PBVHNode **active_nodes;
-
- /* Count number of PBVH nodes that are not fully masked */
- for (int i = 0; i < totnode; i++) {
- if (node_mask[i] == 1) {
- tot_active_nodes++;
- }
- }
-
- /* Create the final list of nodes that is going to be processed in the filter */
- active_nodes = MEM_callocN(tot_active_nodes * sizeof(PBVHNode *), "active nodes");
-
- for (int i = 0; i < totnode; i++) {
- if (node_mask[i] == 1) {
- active_nodes[active_node_index] = nodes[i];
- active_node_index++;
- }
- }
-
- ss->filter_cache->nodes = active_nodes;
- ss->filter_cache->totnode = tot_active_nodes;
-
- MEM_SAFE_FREE(nodes);
- MEM_SAFE_FREE(node_mask);
+ PBVHParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(
+ &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
+ BKE_pbvh_parallel_range(
+ 0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings);
}
static void sculpt_filter_cache_free(SculptSession *ss)
@@ -8299,6 +8269,11 @@ static void mesh_filter_task_cb(void *__restrict userdata,
float fade = vd.mask ? *vd.mask : 0.0f;
fade = 1 - fade;
fade *= data->filter_strength;
+
+ if (fade == 0.0f) {
+ continue;
+ }
+
copy_v3_v3(orig_co, orig_data.co);
switch (filter_type) {
case MESH_FILTER_SMOOTH:
@@ -8417,12 +8392,12 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
.filter_strength = filter_strength,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(
&settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings);
- if (ss->modifiers_active || ss->kb) {
+ if (ss->deform_modifiers_active || ss->shapekey_active) {
sculpt_flush_stroke_deform(sd, ob, true);
}
@@ -8440,10 +8415,6 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SculptSession *ss = ob->sculpt;
PBVH *pbvh = ob->sculpt->pbvh;
- if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return OPERATOR_CANCELLED;
- }
-
int deform_axis = RNA_enum_get(op->ptr, "deform_axis");
if (deform_axis == 0) {
return OPERATOR_CANCELLED;
@@ -8654,10 +8625,6 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
int totnode;
int filter_type = RNA_enum_get(op->ptr, "filter_type");
- if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return OPERATOR_CANCELLED;
- }
-
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
sculpt_vertex_random_access_init(ss);
@@ -8702,9 +8669,9 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
.prev_mask = prev_mask,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings);
if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) {
MEM_freeN(prev_mask);
@@ -8813,13 +8780,14 @@ static void dirty_mask_compute_range_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void dirty_mask_compute_range_finalize(void *__restrict userdata, void *__restrict tls)
+static void dirty_mask_compute_range_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- SculptThreadedTaskData *data = userdata;
- DirtyMaskRangeData *range = tls;
-
- data->dirty_mask_min = min_ff(range->min, data->dirty_mask_min);
- data->dirty_mask_max = max_ff(range->max, data->dirty_mask_max);
+ DirtyMaskRangeData *join = chunk_join;
+ DirtyMaskRangeData *range = chunk;
+ join->min = min_ff(range->min, join->min);
+ join->max = max_ff(range->max, join->max);
}
static void dirty_mask_apply_task_cb(void *__restrict userdata,
@@ -8871,10 +8839,6 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
int totnode;
- if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return OPERATOR_CANCELLED;
- }
-
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
sculpt_vertex_random_access_init(ss);
@@ -8894,8 +8858,6 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
.sd = sd,
.ob = ob,
.nodes = nodes,
- .dirty_mask_min = FLT_MAX,
- .dirty_mask_max = -FLT_MAX,
.dirty_mask_dirty_only = RNA_boolean_get(op->ptr, "dirty_only"),
};
DirtyMaskRangeData range = {
@@ -8903,15 +8865,17 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
.max = -FLT_MAX,
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- settings.func_finalize = dirty_mask_compute_range_finalize;
+ settings.func_reduce = dirty_mask_compute_range_reduce;
settings.userdata_chunk = &range;
settings.userdata_chunk_size = sizeof(DirtyMaskRangeData);
- BLI_task_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings);
- BLI_task_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings);
+ data.dirty_mask_min = range.min;
+ data.dirty_mask_max = range.max;
+ BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings);
MEM_SAFE_FREE(nodes);
@@ -9070,10 +9034,10 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *
int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations");
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false);
for (int i = 0; i < smooth_iterations; i++) {
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(
&settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mask_filter_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, mask_filter_task_cb, &settings);
}
/* Pivot position */
@@ -9139,10 +9103,10 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *
.mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"),
.mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"),
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(
&settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
ss->filter_cache->mask_update_current_it = mask_expand_update_it;
}
@@ -9157,26 +9121,37 @@ typedef struct MaskExpandFloodFillData {
bool use_normals;
} MaskExpandFloodFillData;
-static bool mask_expand_floodfill_cb(SculptSession *ss,
- const SculptFloodFillIterator *from,
- SculptFloodFillIterator *to,
- void *userdata)
+static bool mask_expand_floodfill_cb(
+ SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
{
MaskExpandFloodFillData *data = userdata;
- ss->filter_cache->mask_update_it[to->v] = to->it;
- if (to->it > ss->filter_cache->mask_update_last_it) {
- ss->filter_cache->mask_update_last_it = to->it;
- }
+ if (!is_duplicate) {
+ int to_it = ss->filter_cache->mask_update_it[from_v] + 1;
+ ss->filter_cache->mask_update_it[to_v] = to_it;
+ if (to_it > ss->filter_cache->mask_update_last_it) {
+ ss->filter_cache->mask_update_last_it = to_it;
+ }
- if (data->use_normals) {
- float current_normal[3], prev_normal[3];
- sculpt_vertex_normal_get(ss, to->v, current_normal);
- sculpt_vertex_normal_get(ss, from->v, prev_normal);
- to->edge_factor = dot_v3v3(current_normal, prev_normal) * from->edge_factor;
- ss->filter_cache->normal_factor[to->v] = dot_v3v3(data->original_normal, current_normal) *
- powf(from->edge_factor, data->edge_sensitivity);
- CLAMP(ss->filter_cache->normal_factor[to->v], 0.0f, 1.0f);
+ if (data->use_normals) {
+ float current_normal[3], prev_normal[3];
+ sculpt_vertex_normal_get(ss, to_v, current_normal);
+ sculpt_vertex_normal_get(ss, from_v, prev_normal);
+ const float from_edge_factor = ss->filter_cache->edge_factor[from_v];
+ ss->filter_cache->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) *
+ from_edge_factor;
+ ss->filter_cache->normal_factor[to_v] = dot_v3v3(data->original_normal, current_normal) *
+ powf(from_edge_factor, data->edge_sensitivity);
+ CLAMP(ss->filter_cache->normal_factor[to_v], 0.0f, 1.0f);
+ }
+ }
+ else {
+ /* PBVH_GRIDS duplicate handling */
+ ss->filter_cache->mask_update_it[to_v] = ss->filter_cache->mask_update_it[from_v];
+ if (data->use_normals) {
+ ss->filter_cache->edge_factor[to_v] = ss->filter_cache->edge_factor[from_v];
+ ss->filter_cache->normal_factor[to_v] = ss->filter_cache->normal_factor[from_v];
+ }
}
return true;
@@ -9197,10 +9172,6 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
mouse[0] = event->mval[0];
mouse[1] = event->mval[1];
- if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
- return OPERATOR_CANCELLED;
- }
-
sculpt_vertex_random_access_init(ss);
op->customdata = MEM_mallocN(2 * sizeof(float), "initial mouse position");
@@ -9228,6 +9199,11 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
if (use_normals) {
ss->filter_cache->normal_factor = MEM_callocN(sizeof(float) * vertex_count,
"mask update normal factor");
+ ss->filter_cache->edge_factor = MEM_callocN(sizeof(float) * vertex_count,
+ "mask update normal factor");
+ for (int i = 0; i < vertex_count; i++) {
+ ss->filter_cache->edge_factor[i] = 1.0f;
+ }
}
ss->filter_cache->prev_mask = MEM_callocN(sizeof(float) * vertex_count, "prev mask");
@@ -9266,6 +9242,8 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
ss->filter_cache->normal_factor[i] = avg / ni.size;
}
}
+
+ MEM_SAFE_FREE(ss->filter_cache->edge_factor);
}
SculptThreadedTaskData data = {
@@ -9277,10 +9255,10 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
.mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"),
.mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"),
};
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(
&settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
+ BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
const char *status_str = TIP_(
"Move the mouse to expand the mask from the active vertex. LBM: confirm mask, ESC/RMB: "
@@ -9594,13 +9572,13 @@ void ED_sculpt_update_modal_transform(struct bContext *C)
mul_m4_m4m4(data.transform_mats[i], pivot_mat, data.transform_mats[i]);
}
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(
&settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
- BLI_task_parallel_range(
+ BKE_pbvh_parallel_range(
0, ss->filter_cache->totnode, &data, sculpt_transform_task_cb, &settings);
- if (ss->modifiers_active || ss->kb) {
+ if (ss->deform_modifiers_active || ss->shapekey_active) {
sculpt_flush_stroke_deform(sd, ob, true);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index e9af49a0b5a..93e4a777569 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -194,12 +194,9 @@ typedef struct SculptThreadedTaskData {
int filter_type;
float filter_strength;
- int *node_mask;
- /* 0=towards view, 1=flipped */
- float (*area_cos)[3];
- float (*area_nos)[3];
- int *count;
+ bool use_area_cos;
+ bool use_area_nos;
bool any_vertex_sampled;
float *prev_mask;
@@ -209,13 +206,8 @@ typedef struct SculptThreadedTaskData {
float *pose_factor;
float (*transform_rot)[4], (*transform_trans)[4], (*transform_trans_inv)[4];
- float tot_pos_avg[3];
- int tot_pos_count;
-
float max_distance_squared;
float nearest_vertex_search_co[3];
- int nearest_vertex_index;
- float nearest_vertex_distance_squared;
int mask_expand_update_it;
bool mask_expand_invert_mask;
@@ -418,6 +410,7 @@ typedef struct FilterCache {
int mask_update_last_it;
int *mask_update_it;
float *normal_factor;
+ float *edge_factor;
float *prev_mask;
float mask_expand_initial_co[3];
} FilterCache;
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 788d07f6e78..5d95cc80280 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -86,6 +86,7 @@ static void update_cb(PBVHNode *node, void *rebuild)
struct PartialUpdateData {
PBVH *pbvh;
bool rebuild;
+ char *modified_grids;
};
/**
@@ -94,8 +95,24 @@ struct PartialUpdateData {
static void update_cb_partial(PBVHNode *node, void *userdata)
{
struct PartialUpdateData *data = userdata;
- if (BKE_pbvh_node_vert_update_check_any(data->pbvh, node)) {
- update_cb(node, &(data->rebuild));
+ if (BKE_pbvh_type(data->pbvh) == PBVH_GRIDS) {
+ int *node_grid_indices;
+ int totgrid;
+ bool update = false;
+ BKE_pbvh_node_get_grids(data->pbvh, node, &node_grid_indices, &totgrid, NULL, NULL, NULL);
+ for (int i = 0; i < totgrid; i++) {
+ if (data->modified_grids[node_grid_indices[i]] == 1) {
+ update = true;
+ }
+ }
+ if (update) {
+ update_cb(node, &(data->rebuild));
+ }
+ }
+ else {
+ if (BKE_pbvh_node_vert_update_check_any(data->pbvh, node)) {
+ update_cb(node, &(data->rebuild));
+ }
}
}
@@ -135,7 +152,7 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
if (unode->maxvert) {
/* regular mesh restore */
- if (ss->kb && !STREQ(ss->kb->name, unode->shapeName)) {
+ if (ss->shapekey_active && !STREQ(ss->shapekey_active->name, unode->shapeName)) {
/* shape key has been changed before calling undo operator */
Key *key = BKE_key_from_object(ob);
@@ -157,12 +174,12 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
index = unode->index;
mvert = ss->mvert;
- if (ss->kb) {
+ if (ss->shapekey_active) {
float(*vertCos)[3];
- vertCos = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
+ vertCos = BKE_keyblock_convert_to_vertcos(ob, ss->shapekey_active);
if (unode->orig_co) {
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
for (int i = 0; i < unode->totvert; i++) {
sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]);
}
@@ -180,36 +197,33 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
}
/* propagate new coords to keyblock */
- sculpt_vertcos_to_key(ob, ss->kb, vertCos);
+ sculpt_vertcos_to_key(ob, ss->shapekey_active, vertCos);
/* pbvh uses it's own mvert array, so coords should be */
/* propagated to pbvh here */
- BKE_pbvh_vert_coords_apply(ss->pbvh, vertCos, ss->kb->totelem);
+ BKE_pbvh_vert_coords_apply(ss->pbvh, vertCos, ss->shapekey_active->totelem);
MEM_freeN(vertCos);
}
else {
if (unode->orig_co) {
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
for (int i = 0; i < unode->totvert; i++) {
- if (sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co)) {
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
- }
+ sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co);
+ mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
}
}
else {
for (int i = 0; i < unode->totvert; i++) {
- if (test_swap_v3_v3(mvert[index[i]].co, unode->orig_co[i])) {
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
- }
+ swap_v3_v3(mvert[index[i]].co, unode->orig_co[i]);
+ mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
}
}
}
else {
for (int i = 0; i < unode->totvert; i++) {
- if (test_swap_v3_v3(mvert[index[i]].co, unode->co[i])) {
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
- }
+ swap_v3_v3(mvert[index[i]].co, unode->co[i]);
+ mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
}
}
}
@@ -346,9 +360,9 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
- TaskParallelSettings settings;
+ PBVHParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
- BLI_task_parallel_range(
+ BKE_pbvh_parallel_range(
0, totnode, nodes, sculpt_undo_bmesh_restore_generic_task_cb, &settings);
if (nodes) {
@@ -485,7 +499,6 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
SculptUndoNode *unode;
bool update = false, rebuild = false;
bool need_mask = false;
- bool partial_update = true;
for (unode = lb->first; unode; unode = unode->next) {
/* restore pivot */
@@ -527,6 +540,9 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
return;
}
+ char *undo_modified_grids = NULL;
+ bool use_multires_undo = false;
+
for (unode = lb->first; unode; unode = unode->next) {
if (!STREQ(unode->idname, ob->id.name)) {
@@ -546,8 +562,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
continue;
}
- /* multi-res can't do partial updates since it doesn't flag edited vertices */
- partial_update = false;
+ use_multires_undo = true;
}
switch (unode->type) {
@@ -577,21 +592,29 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
}
}
+ if (use_multires_undo) {
+ int max_grid;
+ unode = lb->first;
+ max_grid = unode->maxgrid;
+ undo_modified_grids = MEM_callocN(sizeof(char) * max_grid, "undo_grids");
+ for (unode = lb->first; unode; unode = unode->next) {
+ for (int i = 0; i < unode->totgrid; i++) {
+ undo_modified_grids[unode->grids[i]] = 1;
+ }
+ }
+ }
+
if (update || rebuild) {
bool tag_update = false;
/* we update all nodes still, should be more clever, but also
* needs to work correct when exiting/entering sculpt mode and
* the nodes get recreated, though in that case it could do all */
- if (partial_update) {
- struct PartialUpdateData data = {
- .rebuild = rebuild,
- .pbvh = ss->pbvh,
- };
- BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb_partial, &data);
- }
- else {
- BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
- }
+ struct PartialUpdateData data = {
+ .rebuild = rebuild,
+ .pbvh = ss->pbvh,
+ .modified_grids = undo_modified_grids,
+ };
+ BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb_partial, &data);
BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw);
if (BKE_sculpt_multires_active(scene, ob)) {
@@ -605,7 +628,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
tag_update |= ((Mesh *)ob->data)->id.us > 1 || !BKE_sculptsession_use_pbvh_draw(ob, v3d);
- if (ss->kb || ss->modifiers_active) {
+ if (ss->shapekey_active || ss->deform_modifiers_active) {
Mesh *mesh = ob->data;
BKE_mesh_calc_normals(mesh);
@@ -620,6 +643,8 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
sculpt_update_object_bounding_box(ob);
}
}
+
+ MEM_SAFE_FREE(undo_modified_grids);
}
static void sculpt_undo_free_list(ListBase *lb)
@@ -806,7 +831,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
unode->index = MEM_mapallocN(sizeof(int) * allvert, "SculptUndoNode.index");
}
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
unode->orig_co = MEM_callocN(allvert * sizeof(*unode->orig_co), "undoSculpt orig_cos");
}
@@ -828,7 +853,7 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
normal_float_to_short_v3(unode->no[vd.i], vd.fno);
}
- if (ss->modifiers_active) {
+ if (ss->deform_modifiers_active) {
copy_v3_v3(unode->orig_co[vd.i], ss->orig_cos[unode->index[vd.i]]);
}
}
@@ -1057,8 +1082,8 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
copy_v3_v3(unode->pivot_rot, ss->pivot_rot);
/* store active shape key */
- if (ss->kb) {
- BLI_strncpy(unode->shapeName, ss->kb->name, sizeof(ss->kb->name));
+ if (ss->shapekey_active) {
+ BLI_strncpy(unode->shapeName, ss->shapekey_active->name, sizeof(ss->shapekey_active->name));
}
else {
unode->shapeName[0] = '\0';
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 4e710d31cbb..69745663c02 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -273,8 +273,11 @@ static void sound_update_animation_flags(Scene *scene)
static int sound_update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Scene *scene = CTX_data_scene(C);
+
BKE_main_id_tag_idcode(CTX_data_main(C), ID_SCE, LIB_TAG_DOIT, false);
sound_update_animation_flags(CTX_data_scene(C));
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 4a4ff5f5605..ca6efb5f69e 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -153,7 +153,8 @@ static void actkeys_find_key_in_list_element(bAnimContext *ac,
float region_x,
float *r_selx,
float *r_frame,
- bool *r_found)
+ bool *r_found,
+ bool *r_is_selected)
{
*r_found = false;
@@ -182,6 +183,7 @@ static void actkeys_find_key_in_list_element(bAnimContext *ac,
*r_selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
*r_frame = ak->cfra;
*r_found = true;
+ *r_is_selected = (ak->sel & SELECT) != 0;
break;
}
}
@@ -197,14 +199,16 @@ static void actkeys_find_key_at_position(bAnimContext *ac,
bAnimListElem **r_ale,
float *r_selx,
float *r_frame,
- bool *r_found)
+ bool *r_found,
+ bool *r_is_selected)
{
*r_found = false;
*r_ale = actkeys_find_list_element_at_position(ac, filter, region_x, region_y);
if (*r_ale != NULL) {
- actkeys_find_key_in_list_element(ac, *r_ale, region_x, r_selx, r_frame, r_found);
+ actkeys_find_key_in_list_element(
+ ac, *r_ale, region_x, r_selx, r_frame, r_found, r_is_selected);
}
}
@@ -213,9 +217,11 @@ static bool actkeys_is_key_at_position(bAnimContext *ac, float region_x, float r
bAnimListElem *ale;
float selx, frame;
bool found;
+ bool is_selected;
int filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS;
- actkeys_find_key_at_position(ac, filter, region_x, region_y, &ale, &selx, &frame, &found);
+ actkeys_find_key_at_position(
+ ac, filter, region_x, region_y, &ale, &selx, &frame, &found, &is_selected);
if (ale != NULL) {
MEM_freeN(ale);
@@ -1681,20 +1687,29 @@ static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, s
/* ------------------- */
-static void mouse_action_keys(bAnimContext *ac,
- const int mval[2],
- short select_mode,
- const bool deselect_all,
- const bool column,
- const bool same_channel)
+static int mouse_action_keys(bAnimContext *ac,
+ const int mval[2],
+ short select_mode,
+ const bool deselect_all,
+ const bool column,
+ const bool same_channel,
+ bool wait_to_deselect_others)
{
int filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS;
bAnimListElem *ale = NULL;
bool found = false;
+ bool is_selected = false;
float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
float selx = 0.0f; /* frame of keyframe under mouse */
- actkeys_find_key_at_position(ac, filter, mval[0], mval[1], &ale, &selx, &frame, &found);
+ int ret_value = OPERATOR_FINISHED;
+
+ actkeys_find_key_at_position(
+ ac, filter, mval[0], mval[1], &ale, &selx, &frame, &found, &is_selected);
+
+ if (select_mode != SELECT_REPLACE) {
+ wait_to_deselect_others = false;
+ }
/* For replacing selection, if we have something to select, we have to clear existing selection.
* The same goes if we found nothing to select, and deselect_all is true
@@ -1703,56 +1718,61 @@ static void mouse_action_keys(bAnimContext *ac,
/* reset selection mode for next steps */
select_mode = SELECT_ADD;
- /* deselect all keyframes */
- deselect_action_keys(ac, 0, SELECT_SUBTRACT);
-
- /* highlight channel clicked on */
- if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) {
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
-
- /* Highlight Action-Group or F-Curve? */
- if (ale != NULL && ale->data) {
- if (ale->type == ANIMTYPE_GROUP) {
- bActionGroup *agrp = ale->data;
-
- agrp->flag |= AGRP_SELECTED;
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
- }
- else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
- FCurve *fcu = ale->data;
-
- fcu->flag |= FCURVE_SELECTED;
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
+ if (wait_to_deselect_others && is_selected) {
+ ret_value = OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ /* deselect all keyframes */
+ deselect_action_keys(ac, 0, SELECT_SUBTRACT);
+
+ /* highlight channel clicked on */
+ if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) {
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+ /* Highlight Action-Group or F-Curve? */
+ if (ale != NULL && ale->data) {
+ if (ale->type == ANIMTYPE_GROUP) {
+ bActionGroup *agrp = ale->data;
+
+ agrp->flag |= AGRP_SELECTED;
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
+ }
+ else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
+ FCurve *fcu = ale->data;
+
+ fcu->flag |= FCURVE_SELECTED;
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
+ }
}
}
- }
- else if (ac->datatype == ANIMCONT_GPENCIL) {
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
-
- /* Highlight GPencil Layer */
- if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_GPLAYER) {
- bGPdata *gpd = (bGPdata *)ale->id;
- bGPDlayer *gpl = ale->data;
-
- gpl->flag |= GP_LAYER_SELECT;
- /* Update other layer status. */
- if (BKE_gpencil_layer_getactive(gpd) != gpl) {
- BKE_gpencil_layer_setactive(gpd, gpl);
- BKE_gpencil_layer_autolock_set(gpd, false);
- WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ else if (ac->datatype == ANIMCONT_GPENCIL) {
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+ /* Highlight GPencil Layer */
+ if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_GPLAYER) {
+ bGPdata *gpd = (bGPdata *)ale->id;
+ bGPDlayer *gpl = ale->data;
+
+ gpl->flag |= GP_LAYER_SELECT;
+ /* Update other layer status. */
+ if (BKE_gpencil_layer_getactive(gpd) != gpl) {
+ BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_autolock_set(gpd, false);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
}
}
- }
- else if (ac->datatype == ANIMCONT_MASK) {
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ else if (ac->datatype == ANIMCONT_MASK) {
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
- if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_MASKLAYER) {
- MaskLayer *masklay = ale->data;
+ if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_MASKLAYER) {
+ MaskLayer *masklay = ale->data;
- masklay->flag |= MASK_LAYERFLAG_SELECT;
+ masklay->flag |= MASK_LAYERFLAG_SELECT;
+ }
}
}
}
@@ -1787,12 +1807,15 @@ static void mouse_action_keys(bAnimContext *ac,
/* free this channel */
MEM_freeN(ale);
}
+
+ return ret_value;
}
/* handle clicking */
-static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int actkeys_clickselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+ int ret_value;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0) {
@@ -1805,20 +1828,26 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent
/* select mode is either replace (deselect all, then add) or add/extend */
const short selectmode = RNA_boolean_get(op->ptr, "extend") ? SELECT_INVERT : SELECT_REPLACE;
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+ const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
+ int mval[2];
/* column selection */
const bool column = RNA_boolean_get(op->ptr, "column");
const bool channel = RNA_boolean_get(op->ptr, "channel");
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
+
/* select keyframe(s) based upon mouse position*/
- mouse_action_keys(&ac, event->mval, selectmode, deselect_all, column, channel);
+ ret_value = mouse_action_keys(
+ &ac, mval, selectmode, deselect_all, column, channel, wait_to_deselect_others);
/* set notifier that keyframe selection (and channels too) have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
/* for tweak grab to work */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ return ret_value | OPERATOR_PASS_THROUGH;
}
void ACTION_OT_clickselect(wmOperatorType *ot)
@@ -1831,13 +1860,16 @@ void ACTION_OT_clickselect(wmOperatorType *ot)
ot->description = "Select keyframes by clicking on them";
/* callbacks */
- ot->invoke = actkeys_clickselect_invoke;
ot->poll = ED_operator_action_active;
+ ot->exec = actkeys_clickselect_exec;
+ ot->invoke = WM_generic_select_invoke;
+ ot->modal = WM_generic_select_modal;
/* flags */
ot->flag = OPTYPE_UNDO;
/* properties */
+ WM_operator_properties_generic_select(ot);
prop = RNA_def_boolean(
ot->srna,
"extend",
diff --git a/source/blender/editors/space_clip/tracking_ops_solve.c b/source/blender/editors/space_clip/tracking_ops_solve.c
index 1d2fc239a89..7e2671382b9 100644
--- a/source/blender/editors/space_clip/tracking_ops_solve.c
+++ b/source/blender/editors/space_clip/tracking_ops_solve.c
@@ -118,7 +118,11 @@ static void solve_camera_freejob(void *scv)
MovieClip *clip = scj->clip;
int solved;
- WM_set_locked_interface(scj->wm, false);
+ /* WindowManager is missing in the job when initialization is incomplete.
+ * In this case the interface is not locked either. */
+ if (scj->wm != NULL) {
+ WM_set_locked_interface(scj->wm, false);
+ }
if (!scj->context) {
/* job weren't fully initialized due to some error */
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index b4b51de302d..3cdcc07f081 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -2395,60 +2395,49 @@ void FILE_OT_filenum(struct wmOperatorType *ot)
RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100, 100);
}
-static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
+static void file_rename_state_activate(SpaceFile *sfile, int file_idx, bool require_selected)
{
- ScrArea *sa = CTX_wm_area(C);
- SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
+ const int numfiles = filelist_files_ensure(sfile->files);
- if (sfile->params) {
- int idx = sfile->params->highlight_file;
- int numfiles = filelist_files_ensure(sfile->files);
- if ((0 <= idx) && (idx < numfiles)) {
- FileDirEntry *file = filelist_file(sfile->files, idx);
+ if ((file_idx >= 0) && (file_idx < numfiles)) {
+ FileDirEntry *file = filelist_file(sfile->files, file_idx);
+
+ if ((require_selected == false) ||
+ (filelist_entry_select_get(sfile->files, file, CHECK_ALL) & FILE_SEL_SELECTED)) {
filelist_entry_select_index_set(
- sfile->files, idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
+ sfile->files, file_idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
BLI_strncpy(sfile->params->renamefile, file->relpath, FILE_MAXFILE);
/* We can skip the pending state,
* as we can directly set FILE_SEL_EDITING on the expected entry here. */
sfile->params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
}
+ }
+}
+
+static int file_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+{
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
+
+ if (sfile->params) {
+ file_rename_state_activate(sfile, sfile->params->active_file, true);
ED_area_tag_redraw(sa);
}
return OPERATOR_FINISHED;
}
-static bool file_rename_poll(bContext *C)
+static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
{
- bool poll = ED_operator_file_active(C);
- SpaceFile *sfile = CTX_wm_space_file(C);
-
- if (sfile && sfile->params) {
- int idx = sfile->params->highlight_file;
- int numfiles = filelist_files_ensure(sfile->files);
-
- if ((0 <= idx) && (idx < numfiles)) {
- FileDirEntry *file = filelist_file(sfile->files, idx);
- if (FILENAME_IS_CURRPAR(file->relpath)) {
- poll = false;
- }
- }
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
- if (sfile->params->highlight_file < 0) {
- poll = false;
- }
- else {
- char dir[FILE_MAX_LIBEXTRA];
- if (filelist_islibrary(sfile->files, dir, NULL)) {
- poll = false;
- }
- }
- }
- else {
- poll = false;
+ if (sfile->params) {
+ file_rename_state_activate(sfile, sfile->params->highlight_file, false);
+ ED_area_tag_redraw(sa);
}
- return poll;
+ return OPERATOR_FINISHED;
}
void FILE_OT_rename(struct wmOperatorType *ot)
@@ -2459,8 +2448,9 @@ void FILE_OT_rename(struct wmOperatorType *ot)
ot->idname = "FILE_OT_rename";
/* api callbacks */
+ ot->invoke = file_rename_invoke;
ot->exec = file_rename_exec;
- ot->poll = file_rename_poll;
+ ot->poll = ED_operator_file_active;
}
static bool file_delete_poll(bContext *C)
@@ -2504,23 +2494,29 @@ int file_delete_exec(bContext *C, wmOperator *op)
int numfiles = filelist_files_ensure(sfile->files);
int i;
+ const char *error_message = NULL;
bool report_error = false;
errno = 0;
for (i = 0; i < numfiles; i++) {
if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
file = filelist_file(sfile->files, i);
BLI_make_file_string(BKE_main_blendfile_path(bmain), str, sfile->params->dir, file->relpath);
- if (BLI_delete(str, false, false) != 0 || BLI_exists(str)) {
+ if (BLI_delete_soft(str, &error_message) != 0 || BLI_exists(str)) {
report_error = true;
}
}
}
if (report_error) {
- BKE_reportf(op->reports,
- RPT_ERROR,
- "Could not delete file: %s",
- errno ? strerror(errno) : "unknown error");
+ if (error_message != NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "Could not delete file or directory: %s", error_message);
+ }
+ else {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Could not delete file or directory: %s",
+ errno ? strerror(errno) : "unknown error");
+ }
}
ED_fileselect_clear(wm, sa, sfile);
@@ -2533,7 +2529,7 @@ void FILE_OT_delete(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete Selected Files";
- ot->description = "Delete selected files";
+ ot->description = "Move selected files to the trash or recycle bin";
ot->idname = "FILE_OT_delete";
/* api callbacks */
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 27cccf6bab1..d29233618de 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -831,7 +831,7 @@ void filelist_setfilter_options(FileList *filelist,
}
if ((filelist->filter_data.filter != filter) || (filelist->filter_data.filter_id != filter_id)) {
filelist->filter_data.filter = filter;
- filelist->filter_data.filter_id = filter_id;
+ filelist->filter_data.filter_id = (filter & FILE_TYPE_BLENDERLIB) ? filter_id : FILTER_ID_ALL;
update = true;
}
if (!STREQ(filelist->filter_data.filter_glob, filter_glob)) {
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index e2c9bb8d6e5..ba4ccb4fba9 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -247,13 +247,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
}
/* For now, always init filterid to 'all true' */
- params->filter_id = FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU |
- FILTER_ID_GD | FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS |
- FILTER_ID_LT | FILTER_ID_MA | FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME |
- FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | FILTER_ID_PA |
- FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK |
- FILTER_ID_SO | FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO |
- FILTER_ID_CF | FILTER_ID_WS | FILTER_ID_LP;
+ params->filter_id = FILTER_ID_ALL;
if (U.uiflag & USER_HIDE_DOT) {
params->flag |= FILE_HIDE_DOT;
@@ -362,10 +356,10 @@ void ED_fileselect_set_params_from_userdef(SpaceFile *sfile)
/**
* Update the user-preference data for the file space. In fact, this also contains some
- * non-FileSelectParams data, but it's neglectable.
+ * non-FileSelectParams data, but we can safely ignore this.
*
- * \param temp_win_size: If the browser was opened in a temporary window, pass its size here so we
- * can store that in the preferences. Otherwise NULL.
+ * \param temp_win_size: If the browser was opened in a temporary window,
+ * pass its size here so we can store that in the preferences. Otherwise NULL.
*/
void ED_fileselect_params_to_userdef(SpaceFile *sfile, int temp_win_size[2])
{
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 39f7bf001f3..a8dfad85232 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -2298,12 +2298,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op)
/* get a filename for menu */
BLI_split_dir_part(first_ibuf->name, di, sizeof(di));
- BKE_reportf(op->reports,
- RPT_INFO,
- tot == 1 ? "%d image will be saved in %s" :
- "%d images will be saved in %s",
- tot,
- di);
+ BKE_reportf(op->reports, RPT_INFO, "%d image(s) will be saved in %s", tot, di);
iter = IMB_moviecacheIter_new(image->cache);
while (!IMB_moviecacheIter_done(iter)) {
diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c
index c450d5122eb..577c4e24b11 100644
--- a/source/blender/editors/space_image/image_undo.c
+++ b/source/blender/editors/space_image/image_undo.c
@@ -70,7 +70,7 @@ static CLG_LogRef LOG = {"ed.image.undo"};
/** \name Thread Locking
* \{ */
-/* this is a static resource for non-globality,
+/* This is a non-global static resource,
* Maybe it should be exposed as part of the
* paint operation, but for now just give a public interface */
static SpinLock paint_tiles_lock;
@@ -457,6 +457,31 @@ static void ubuf_from_image_all_tiles(UndoImageBuf *ubuf, const ImBuf *ibuf)
IMB_freeImBuf(tmpibuf);
}
+/** Ensure we can copy the ubuf into the ibuf. */
+static void ubuf_ensure_compat_ibuf(const UndoImageBuf *ubuf, ImBuf *ibuf)
+{
+ /* We could have both float and rect buffers,
+ * in this case free the float buffer if it's unused. */
+ if ((ibuf->rect_float != NULL) && (ubuf->image_state.use_float == false)) {
+ imb_freerectfloatImBuf(ibuf);
+ }
+
+ if (ibuf->x == ubuf->image_dims[0] && ibuf->y == ubuf->image_dims[1] &&
+ (ubuf->image_state.use_float ? (void *)ibuf->rect_float : (void *)ibuf->rect)) {
+ return;
+ }
+
+ imb_freerectImbuf_all(ibuf);
+ IMB_rect_size_set(ibuf, ubuf->image_dims);
+
+ if (ubuf->image_state.use_float) {
+ imb_addrectfloatImBuf(ibuf);
+ }
+ else {
+ imb_addrectImBuf(ibuf);
+ }
+}
+
static void ubuf_free(UndoImageBuf *ubuf)
{
UndoImageBuf *ubuf_post = ubuf->post;
@@ -510,7 +535,8 @@ static void uhandle_restore_list(ListBase *undo_handles, bool use_init)
bool changed = false;
for (UndoImageBuf *ubuf_iter = uh->buffers.first; ubuf_iter; ubuf_iter = ubuf_iter->next) {
UndoImageBuf *ubuf = use_init ? ubuf_iter : ubuf_iter->post;
- IMB_rect_size_set(ibuf, ubuf->image_dims);
+ ubuf_ensure_compat_ibuf(ubuf, ibuf);
+
int i = 0;
for (uint y_tile = 0; y_tile < ubuf->tiles_dims[1]; y_tile += 1) {
uint y = y_tile << ED_IMAGE_UNDO_TILE_BITS;
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index 1abf1a64263..938e7f09881 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -597,13 +597,19 @@ void NLA_OT_select_leftright(wmOperatorType *ot)
/* ******************** Mouse-Click Select Operator *********************** */
/* select strip directly under mouse */
-static void mouse_nla_strips(
- bContext *C, bAnimContext *ac, const int mval[2], short select_mode, const bool deselect_all)
+static int mouse_nla_strips(bContext *C,
+ bAnimContext *ac,
+ const int mval[2],
+ short select_mode,
+ const bool deselect_all,
+ bool wait_to_deselect_others)
{
Scene *scene = ac->scene;
bAnimListElem *ale = NULL;
NlaStrip *strip = NULL;
+ int ret_value = OPERATOR_FINISHED;
+
nlaedit_strip_at_region_position(ac, mval[0], mval[1], &ale, &strip);
/* if currently in tweakmode, exit tweakmode before changing selection states
@@ -613,6 +619,10 @@ static void mouse_nla_strips(
WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
}
+ if (select_mode != SELECT_REPLACE) {
+ wait_to_deselect_others = false;
+ }
+
/* For replacing selection, if we have something to select, we have to clear existing selection.
* The same goes if we found nothing to select, and deselect_all is true
* (deselect on nothing behavior). */
@@ -620,11 +630,16 @@ static void mouse_nla_strips(
/* reset selection mode for next steps */
select_mode = SELECT_ADD;
- /* deselect all strips */
- deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
+ if (strip && wait_to_deselect_others && (strip->flag & DESELECT_STRIPS_CLEARACTIVE)) {
+ ret_value = OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ /* deselect all strips */
+ deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
- /* deselect all other channels first */
- ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ }
}
/* only select strip if we clicked on a valid channel and hit something */
@@ -658,14 +673,17 @@ static void mouse_nla_strips(
/* free this channel */
MEM_freeN(ale);
}
+
+ return ret_value;
}
/* ------------------- */
/* handle clicking */
-static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int nlaedit_clickselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+ int ret_value;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0) {
@@ -675,15 +693,19 @@ static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent
/* select mode is either replace (deselect all, then add) or add/extend */
const short selectmode = RNA_boolean_get(op->ptr, "extend") ? SELECT_INVERT : SELECT_REPLACE;
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+ const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
+ int mval[2];
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
/* select strips based upon mouse position */
- mouse_nla_strips(C, &ac, event->mval, selectmode, deselect_all);
+ ret_value = mouse_nla_strips(C, &ac, mval, selectmode, deselect_all, wait_to_deselect_others);
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
/* for tweak grab to work */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ return ret_value | OPERATOR_PASS_THROUGH;
}
void NLA_OT_click_select(wmOperatorType *ot)
@@ -695,14 +717,17 @@ void NLA_OT_click_select(wmOperatorType *ot)
ot->idname = "NLA_OT_click_select";
ot->description = "Handle clicks to select NLA Strips";
- /* api callbacks - absolutely no exec() this yet... */
- ot->invoke = nlaedit_clickselect_invoke;
+ /* callbacks */
ot->poll = ED_operator_nla_active;
+ ot->exec = nlaedit_clickselect_exec;
+ ot->invoke = WM_generic_select_invoke;
+ ot->modal = WM_generic_select_modal;
/* flags */
ot->flag = OPTYPE_UNDO;
/* properties */
+ WM_operator_properties_generic_select(ot);
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 3beb12fbb2a..a5b18ff7589 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -47,7 +47,7 @@
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
-#include "GPU_extensions.h"
+#include "GPU_platform.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
@@ -816,51 +816,8 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- PointerRNA imaptr = RNA_pointer_get(ptr, "image");
PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
- Image *ima = imaptr.data;
-
- uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
- uiTemplateID(layout,
- C,
- ptr,
- "image",
- "IMAGE_OT_new",
- "IMAGE_OT_open",
- NULL,
- UI_TEMPLATE_ID_FILTER_ALL,
- false);
-
- if (!ima) {
- return;
- }
-
- uiItemR(layout, &imaptr, "source", 0, IFACE_("Source"), ICON_NONE);
-
- if (!(ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER))) {
- uiLayout *row = uiLayoutRow(layout, true);
- const bool is_packed = BKE_image_has_packedfile(ima);
-
- if (is_packed) {
- uiItemO(row, "", ICON_PACKAGE, "image.unpack");
- }
- else {
- uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
- }
-
- row = uiLayoutRow(row, true);
- uiLayoutSetEnabled(row, !is_packed);
- uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
- uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
- }
-
- /* multilayer? */
- if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
- uiTemplateImageLayers(layout, C, ima, iuserptr.data);
- }
- else if (ima->source != IMA_SRC_GENERATED) {
- uiTemplateImageInfo(layout, C, ima, iuserptr.data);
- }
+ uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0);
uiItemR(layout, ptr, "interpolation", 0, IFACE_("Interpolation"), ICON_NONE);
uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE);
@@ -3890,9 +3847,7 @@ static void nodelink_batch_draw(SpaceNode *snode)
void nodelink_batch_start(SpaceNode *UNUSED(snode))
{
- /* TODO: partial workaround for NVIDIA driver bug on recent GTX/RTX cards,
- * that breaks instancing when using indirect draw-call (see T70011). */
- g_batch_link.enabled = !GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY);
+ g_batch_link.enabled = true;
}
void nodelink_batch_end(SpaceNode *snode)
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 08ac84cbb2f..5d020ff5ab4 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -241,6 +241,8 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
node->flag |= NODE_SELECT;
}
+ bNodeLink *glinks_first = ntree->links.last;
+
/* Add internal links to the ntree */
for (link = wgroup->links.first; link; link = linkn) {
linkn = link->next;
@@ -248,6 +250,8 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
BLI_addtail(&ntree->links, link);
}
+ bNodeLink *glinks_last = ntree->links.last;
+
/* and copy across the animation,
* note that the animation data's action can be NULL here */
if (wgroup->adt) {
@@ -280,70 +284,64 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
BKE_id_free(bmain, wgroup);
/* restore external links to and from the gnode */
- /* note: the nodes have been copied to intermediate wgroup first (so need to use new_node),
- * then transferred to ntree (new_node pointers remain valid).
- */
/* input links */
- for (link = ngroup->links.first; link; link = link->next) {
- if (link->fromnode->type == NODE_GROUP_INPUT) {
- const char *identifier = link->fromsock->identifier;
- int num_external_links = 0;
-
- /* find external links to this input */
- for (tlink = ntree->links.first; tlink; tlink = tlink->next) {
- if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
- nodeAddLink(ntree,
- tlink->fromnode,
- tlink->fromsock,
- link->tonode->new_node,
- link->tosock->new_sock);
- num_external_links++;
+ if (glinks_first != NULL) {
+ for (link = glinks_first->next; link != glinks_last->next; link = link->next) {
+ if (link->fromnode->type == NODE_GROUP_INPUT) {
+ const char *identifier = link->fromsock->identifier;
+ int num_external_links = 0;
+
+ /* find external links to this input */
+ for (tlink = ntree->links.first; tlink != glinks_first->next; tlink = tlink->next) {
+ if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
+ nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock);
+ num_external_links++;
+ }
}
- }
- /* if group output is not externally linked,
- * convert the constant input value to ensure somewhat consistent behavior */
- if (num_external_links == 0) {
- /* XXX TODO bNodeSocket *sock = node_group_find_input_socket(gnode, identifier);
- BLI_assert(sock);*/
+ /* if group output is not externally linked,
+ * convert the constant input value to ensure somewhat consistent behavior */
+ if (num_external_links == 0) {
+ /* XXX TODO bNodeSocket *sock = node_group_find_input_socket(gnode, identifier);
+ BLI_assert(sock);*/
- /* XXX TODO
- * nodeSocketCopy(ntree, link->tosock->new_sock, link->tonode->new_node,
- * ntree, sock, gnode);*/
+ /* XXX TODO
+ * nodeSocketCopy(ntree, link->tosock->new_sock, link->tonode->new_node,
+ * ntree, sock, gnode);*/
+ }
}
}
- }
- /* output links */
- for (link = ntree->links.first; link; link = link->next) {
- if (link->fromnode == gnode) {
- const char *identifier = link->fromsock->identifier;
- int num_internal_links = 0;
-
- /* find internal links to this output */
- for (tlink = ngroup->links.first; tlink; tlink = tlink->next) {
- /* only use active output node */
- if (tlink->tonode->type == NODE_GROUP_OUTPUT && (tlink->tonode->flag & NODE_DO_OUTPUT)) {
- if (STREQ(tlink->tosock->identifier, identifier)) {
- nodeAddLink(ntree,
- tlink->fromnode->new_node,
- tlink->fromsock->new_sock,
- link->tonode,
- link->tosock);
- num_internal_links++;
+ /* Also iterate over new links to cover passthrough links. */
+ glinks_last = ntree->links.last;
+
+ /* output links */
+ for (link = ntree->links.first; link != glinks_first->next; link = link->next) {
+ if (link->fromnode == gnode) {
+ const char *identifier = link->fromsock->identifier;
+ int num_internal_links = 0;
+
+ /* find internal links to this output */
+ for (tlink = glinks_first->next; tlink != glinks_last->next; tlink = tlink->next) {
+ /* only use active output node */
+ if (tlink->tonode->type == NODE_GROUP_OUTPUT && (tlink->tonode->flag & NODE_DO_OUTPUT)) {
+ if (STREQ(tlink->tosock->identifier, identifier)) {
+ nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock);
+ num_internal_links++;
+ }
}
}
- }
- /* if group output is not internally linked,
- * convert the constant output value to ensure somewhat consistent behavior */
- if (num_internal_links == 0) {
- /* XXX TODO bNodeSocket *sock = node_group_find_output_socket(gnode, identifier);
- BLI_assert(sock);*/
+ /* if group output is not internally linked,
+ * convert the constant output value to ensure somewhat consistent behavior */
+ if (num_internal_links == 0) {
+ /* XXX TODO bNodeSocket *sock = node_group_find_output_socket(gnode, identifier);
+ BLI_assert(sock);*/
- /* XXX TODO
- * nodeSocketCopy(ntree, link->tosock, link->tonode, ntree, sock, gnode); */
+ /* XXX TODO
+ * nodeSocketCopy(ntree, link->tosock, link->tonode, ntree, sock, gnode); */
+ }
}
}
}
@@ -893,7 +891,7 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree,
}
}
if (sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) {
- skip = true;
+ skip = true;
}
if (skip) {
continue;
@@ -917,7 +915,7 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree,
}
}
if (sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) {
- skip = true;
+ skip = true;
}
if (skip) {
continue;
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index b66cd0d3069..e22ef389516 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -557,100 +557,40 @@ static int node_mouse_select(bContext *C,
static int node_select_exec(bContext *C, wmOperator *op)
{
+ const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
+
/* get settings from RNA properties for operator */
int mval[2];
mval[0] = RNA_int_get(op->ptr, "mouse_x");
mval[1] = RNA_int_get(op->ptr, "mouse_y");
/* perform the select */
- const int ret_value = node_mouse_select(C, op, mval, false);
+ const int ret_value = node_mouse_select(C, op, mval, wait_to_deselect_others);
/* allow tweak event to work too */
return ret_value | OPERATOR_PASS_THROUGH;
}
-static int node_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- const short init_event_type = (short)POINTER_AS_INT(op->customdata);
-
- /* get settings from RNA properties for operator */
- int mval[2];
- mval[0] = RNA_int_get(op->ptr, "mouse_x");
- mval[1] = RNA_int_get(op->ptr, "mouse_y");
-
- if (init_event_type == 0) {
- if (event->val == KM_PRESS) {
- const int ret_value = node_mouse_select(C, op, mval, true);
-
- op->customdata = POINTER_FROM_INT((int)event->type);
- if (ret_value & OPERATOR_RUNNING_MODAL) {
- WM_event_add_modal_handler(C, op);
- }
- return ret_value | OPERATOR_PASS_THROUGH;
- }
- else {
- /* If we are in init phase, and cannot validate init of modal operations,
- * just fall back to basic exec.
- */
- const int ret_value = node_mouse_select(C, op, mval, false);
- return ret_value | OPERATOR_PASS_THROUGH;
- }
- }
- else if (event->type == init_event_type && event->val == KM_RELEASE) {
- const int ret_value = node_mouse_select(C, op, mval, false);
- return ret_value | OPERATOR_PASS_THROUGH;
- }
- else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
- const int drag_delta[2] = {
- mval[0] - event->mval[0],
- mval[1] - event->mval[1],
- };
- /* If user moves mouse more than defined threshold, we consider select operator as
- * finished. Otherwise, it is still running until we get an 'release' event. In any
- * case, we pass through event, but select op is not finished yet. */
- if (WM_event_drag_test_with_delta(event, drag_delta)) {
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
- }
- else {
- /* Important not to return anything other than PASS_THROUGH here,
- * otherwise it prevents underlying tweak detection code to work properly. */
- return OPERATOR_PASS_THROUGH;
- }
- }
-
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
-}
-
-static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
- RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
-
- op->customdata = POINTER_FROM_INT(0);
-
- return node_select_modal(C, op, event);
-}
-
void NODE_OT_select(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Select";
ot->idname = "NODE_OT_select";
ot->description = "Select the node under the cursor";
/* api callbacks */
- ot->invoke = node_select_invoke;
ot->exec = node_select_exec;
- ot->modal = node_select_modal;
+ ot->invoke = WM_generic_select_invoke;
+ ot->modal = WM_generic_select_modal;
ot->poll = ED_operator_node_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- PropertyRNA *prop;
- RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX);
+ WM_operator_properties_generic_select(ot);
RNA_def_boolean(ot->srna, "extend", false, "Extend", "");
RNA_def_boolean(ot->srna, "socket_select", false, "Socket Select", "");
prop = RNA_def_boolean(ot->srna,
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 309446db83b..03606282fcd 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -965,7 +965,7 @@ static int collection_isolate_exec(bContext *C, wmOperator *op)
LayerCollection *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
if (extend) {
- BKE_layer_collection_isolate(scene, view_layer, layer_collection, true);
+ BKE_layer_collection_isolate_global(scene, view_layer, layer_collection, true);
}
else {
PointerRNA ptr;
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index a2ca3254b30..3b86e04308e 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -2419,7 +2419,6 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case OB_GPENCIL:
data.icon = ICON_OUTLINER_OB_GREASEPENCIL;
break;
- break;
}
}
else {
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index c81d292a859..c55140db46f 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -770,11 +770,7 @@ static int outliner_id_copy_exec(bContext *C, wmOperator *op)
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
BKE_copybuffer_save(bmain, str, op->reports);
- BKE_reportf(op->reports,
- RPT_INFO,
- num_ids == 1 ? "Copied %d selected data-block" :
- "Copied %d selected data-blocks",
- num_ids);
+ BKE_reportf(op->reports, RPT_INFO, "Copied %d selected data-block(s)", num_ids);
return OPERATOR_FINISHED;
}
@@ -808,11 +804,7 @@ static int outliner_id_paste_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WINDOW, NULL);
- BKE_reportf(op->reports,
- RPT_INFO,
- num_pasted == 1 ? "%d data-block pasted" :
- "%d data-blocks pasted",
- num_pasted);
+ BKE_reportf(op->reports, RPT_INFO, "%d data-block(s) pasted", num_pasted);
return OPERATOR_FINISHED;
}
@@ -2265,11 +2257,7 @@ static int outliner_orphans_purge_exec(bContext *C, wmOperator *op)
BKE_id_multi_tagged_delete(bmain);
- BKE_reportf(op->reports,
- RPT_INFO,
- num_tagged[INDEX_ID_NULL] == 1 ? "Deleted %d data-block" :
- "Deleted %d data-blocks",
- num_tagged[INDEX_ID_NULL]);
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %d data-block(s)", num_tagged[INDEX_ID_NULL]);
/* XXX: tree management normally happens from draw_outliner(), but when
* you're clicking to fast on Delete object from context menu in
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 44e67fa1508..f1e884adc3d 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -263,7 +263,8 @@ static void do_outliner_object_select_recursive(ViewLayer *view_layer,
for (base = FIRSTBASE(view_layer); base; base = base->next) {
Object *ob = base->object;
- if ((((base->flag & BASE_VISIBLE) != 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
+ if ((((base->flag & BASE_VISIBLE_DEPSGRAPH) != 0) &&
+ BKE_object_is_child_recursive(ob_parent, ob))) {
ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
}
}
@@ -1198,7 +1199,7 @@ static void do_outliner_item_activate_tree_element(bContext *C,
Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
if ((ob != NULL) && (ob->data == tselem->id)) {
Base *base = BKE_view_layer_base_find(view_layer, ob);
- if ((base != NULL) && (base->flag & BASE_VISIBLE)) {
+ if ((base != NULL) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) {
do_outliner_activate_obdata(C, scene, view_layer, base, extend);
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index fd6a052b84d..7f7cfff12ef 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1365,7 +1365,7 @@ static void outliner_add_layer_collection_objects(
TreeElement *te_object = outliner_add_element(soops, tree, base->object, ten, 0, 0);
te_object->directdata = base;
- if (!(base->flag & BASE_VISIBLE)) {
+ if (!(base->flag & BASE_VISIBLE_DEPSGRAPH)) {
te_object->flag |= TE_DISABLED;
}
}
@@ -1398,7 +1398,7 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops,
tselem->flag &= ~TSE_CLOSED;
}
- if (exclude || (lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0) {
+ if (exclude || (lc->runtime_flag & LAYER_COLLECTION_VISIBLE_VIEW_LAYER) == 0) {
ten->flag |= TE_DISABLED;
}
}
@@ -2085,12 +2085,12 @@ static bool outliner_element_visible_get(ViewLayer *view_layer,
}
if (exclude_filter & SO_FILTER_OB_STATE_VISIBLE) {
- if ((base->flag & BASE_VISIBLE) == 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
return false;
}
}
else if (exclude_filter & SO_FILTER_OB_STATE_HIDDEN) {
- if ((base->flag & BASE_VISIBLE) != 0) {
+ if ((base->flag & BASE_VISIBLE_DEPSGRAPH) != 0) {
return false;
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 9d7163cd6d9..865dfb45278 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -1600,6 +1600,7 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
if (success) {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
return OPERATOR_FINISHED;
}
else {
@@ -1693,6 +1694,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
if (sa) {
ED_area_status_text(sa, NULL);
}
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index affb6d3fd88..4c20fc1707a 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -319,7 +319,7 @@ void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int sequencer_select_exec(bContext *C, wmOperator *op)
{
View2D *v2d = UI_view2d_fromcontext(C);
Scene *scene = CTX_data_scene(C);
@@ -328,7 +328,13 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
const bool linked_handle = RNA_boolean_get(op->ptr, "linked_handle");
const bool linked_time = RNA_boolean_get(op->ptr, "linked_time");
+ bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
int left_right = RNA_enum_get(op->ptr, "left_right");
+ int mval[2];
+ int ret_value = OPERATOR_CANCELLED;
+
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
Sequence *seq, *neighbor, *act_orig;
int hand, sel_side;
@@ -338,9 +344,13 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
return OPERATOR_CANCELLED;
}
+ if (extend) {
+ wait_to_deselect_others = false;
+ }
+
marker = find_nearest_marker(SCE_MARKERS, 1); // XXX - dummy function for now
- seq = find_nearest_seq(scene, v2d, &hand, event->mval);
+ seq = find_nearest_seq(scene, v2d, &hand, mval);
// XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip
if (seq && linked_time && (left_right == SEQ_SELECT_LR_MOUSE)) {
@@ -364,6 +374,8 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* deselect_markers(0, 0); */
marker->flag |= SELECT;
}
+
+ ret_value = OPERATOR_FINISHED;
}
else if (left_right != SEQ_SELECT_LR_NONE) {
/* use different logic for this */
@@ -374,7 +386,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
switch (left_right) {
case SEQ_SELECT_LR_MOUSE:
- x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
+ x = UI_view2d_region_to_view_x(v2d, mval[0]);
break;
case SEQ_SELECT_LR_LEFT:
x = CFRA - 1.0f;
@@ -409,13 +421,27 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
}
}
+
+ ret_value = OPERATOR_FINISHED;
}
else {
act_orig = ed->act_seq;
if (seq) {
- if (!extend && !linked_handle) {
+ /* Are we trying to select a handle that's already selected? */
+ const bool handle_selected = ((hand == SEQ_SIDE_LEFT) && (seq->flag & SEQ_LEFTSEL)) ||
+ ((hand == SEQ_SIDE_RIGHT) && (seq->flag & SEQ_RIGHTSEL));
+
+ if (wait_to_deselect_others && (seq->flag & SELECT) &&
+ (hand == SEQ_SIDE_NONE || handle_selected)) {
+ ret_value = OPERATOR_RUNNING_MODAL;
+ }
+ else if (!extend && !linked_handle) {
ED_sequencer_deselect_all(scene);
+ ret_value = OPERATOR_FINISHED;
+ }
+ else {
+ ret_value = OPERATOR_FINISHED;
}
BKE_sequencer_active_set(scene, seq);
@@ -509,6 +535,8 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp);
}
}
+
+ ret_value = OPERATOR_FINISHED;
}
else {
if (extend && (seq->flag & SELECT) && ed->act_seq == act_orig) {
@@ -525,6 +553,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
seq->flag ^= SEQ_RIGHTSEL;
break;
}
+ ret_value = OPERATOR_FINISHED;
}
else {
seq->flag |= SELECT;
@@ -542,9 +571,12 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
if (linked_time) {
select_linked_time(ed->seqbasep, seq);
}
+
+ BLI_assert((ret_value & OPERATOR_CANCELLED) == 0);
}
else if (deselect_all) {
ED_sequencer_deselect_all(scene);
+ ret_value = OPERATOR_FINISHED;
}
}
@@ -552,8 +584,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
- /* allowing tweaks */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ return ret_value;
}
void SEQUENCER_OT_select(wmOperatorType *ot)
@@ -565,6 +596,7 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
{SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select right"},
{0, NULL, 0, NULL, NULL},
};
+ PropertyRNA *prop;
/* identifiers */
ot->name = "Select";
@@ -572,14 +604,16 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
ot->description = "Select a strip (last selected becomes the \"active strip\")";
/* api callbacks */
- ot->invoke = sequencer_select_invoke;
+ ot->exec = sequencer_select_exec;
+ ot->invoke = WM_generic_select_invoke;
+ ot->modal = WM_generic_select_modal;
ot->poll = ED_operator_sequencer_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- PropertyRNA *prop;
+ WM_operator_properties_generic_select(ot);
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
prop = RNA_def_boolean(ot->srna,
"deselect_all",
diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c
index 347d46a4234..935e288c7be 100644
--- a/source/blender/editors/space_text/text_format_lua.c
+++ b/source/blender/editors/space_text/text_format_lua.c
@@ -48,7 +48,7 @@ static int txtfmt_lua_find_keyword(const char *string)
/* Keep aligned args for readability. */
/* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "and", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "and", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "break", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "do", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "else", len)) { i = len;
@@ -66,8 +66,7 @@ static int txtfmt_lua_find_keyword(const char *string)
} else if (STR_LITERAL_STARTSWITH(string, "then", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "until", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "while", len)) { i = len;
- } else { i = 0;
-}
+ } else { i = 0; }
/* clang-format on */
@@ -96,7 +95,7 @@ static int txtfmt_lua_find_specialvar(const char *string)
/* Keep aligned args for readability. */
/* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "assert", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "assert", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "collectgarbage", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "dofile", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "error", len)) { i = len;
@@ -124,8 +123,7 @@ static int txtfmt_lua_find_specialvar(const char *string)
} else if (STR_LITERAL_STARTSWITH(string, "unpack", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "_VERSION", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "xpcall", len)) { i = len;
- } else { i = 0;
-}
+ } else { i = 0; }
/* clang-format on */
@@ -140,18 +138,13 @@ static int txtfmt_lua_find_bool(const char *string)
{
int i, len;
- if (STR_LITERAL_STARTSWITH(string, "nil", len)) {
- i = len;
- }
- else if (STR_LITERAL_STARTSWITH(string, "true", len)) {
- i = len;
- }
- else if (STR_LITERAL_STARTSWITH(string, "false", len)) {
- i = len;
- }
- else {
- i = 0;
- }
+ /* Keep aligned args for readability. */
+ /* clang-format off */
+
+ if (STR_LITERAL_STARTSWITH(string, "nil", len)) { i = len;
+ } else if (STR_LITERAL_STARTSWITH(string, "true", len)) { i = len;
+ } else if (STR_LITERAL_STARTSWITH(string, "false", len)) { i = len;
+ } else { i = 0; }
/* clang-format on */
@@ -169,10 +162,9 @@ static char txtfmt_lua_format_identifier(const char *str)
/* Keep aligned args for readability. */
/* clang-format off */
- if ((txtfmt_lua_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
+ if ((txtfmt_lua_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
} else if ((txtfmt_lua_find_keyword(str)) != -1) { fmt = FMT_TYPE_KEYWORD;
- } else { fmt = FMT_TYPE_DEFAULT;
-}
+ } else { fmt = FMT_TYPE_DEFAULT; }
/* clang-format on */
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index fb9ddcb09cb..2da4488e901 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -40,7 +40,7 @@ static int txtfmt_osl_find_builtinfunc(const char *string)
/* list is from
* https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
*/
- if (STR_LITERAL_STARTSWITH(string, "break", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "break", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "closure", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "color", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "continue", len)) { i = len;
@@ -86,7 +86,7 @@ static int txtfmt_osl_find_reserved(const char *string)
/* list is from...
* https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
*/
- if (STR_LITERAL_STARTSWITH(string, "bool", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "bool", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "case", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "catch", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "char", len)) { i = len;
@@ -149,7 +149,7 @@ static int txtfmt_osl_find_specialvar(const char *string)
/* clang-format off */
/* OSL shader types */
- if (STR_LITERAL_STARTSWITH(string, "shader", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "shader", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "surface", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "volume", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "displacement", len)) { i = len;
@@ -189,7 +189,7 @@ static char txtfmt_osl_format_identifier(const char *str)
/* Keep aligned args for readability. */
/* clang-format off */
- if ((txtfmt_osl_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
+ if ((txtfmt_osl_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
} else if ((txtfmt_osl_find_builtinfunc(str)) != -1) { fmt = FMT_TYPE_KEYWORD;
} else if ((txtfmt_osl_find_reserved(str)) != -1) { fmt = FMT_TYPE_RESERVED;
} else if ((txtfmt_osl_find_preprocessor(str)) != -1) { fmt = FMT_TYPE_DIRECTIVE;
@@ -323,7 +323,7 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const bool do_
/* Special vars(v) or built-in keywords(b) */
/* keep in sync with 'txtfmt_osl_format_identifier()' */
- if ((i = txtfmt_osl_find_specialvar(str)) != -1) { prev = FMT_TYPE_SPECIAL;
+ if ((i = txtfmt_osl_find_specialvar(str)) != -1) { prev = FMT_TYPE_SPECIAL;
} else if ((i = txtfmt_osl_find_builtinfunc(str)) != -1) { prev = FMT_TYPE_KEYWORD;
} else if ((i = txtfmt_osl_find_reserved(str)) != -1) { prev = FMT_TYPE_RESERVED;
} else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) { prev = FMT_TYPE_DIRECTIVE;
diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c
index a5e1a3845cf..21df7b5b76a 100644
--- a/source/blender/editors/space_text/text_format_pov.c
+++ b/source/blender/editors/space_text/text_format_pov.c
@@ -48,7 +48,7 @@ static int txtfmt_pov_find_keyword(const char *string)
int i, len;
/* Language Directives */
- if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "persistent", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "version", len)) { i = len;
@@ -101,7 +101,7 @@ static int txtfmt_pov_find_reserved_keywords(const char *string)
/* clang-format off */
/* Float Functions */
- if (STR_LITERAL_STARTSWITH(string, "conserve_energy", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "conserve_energy", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "max_intersections", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "dimension_size", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "bitwise_and", len)) { i = len;
@@ -261,7 +261,7 @@ static int txtfmt_pov_find_reserved_builtins(const char *string)
/* clang-format off */
/* Language Keywords */
- if (STR_LITERAL_STARTSWITH(string, "reflection_exponent", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "reflection_exponent", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "area_illumination", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "all_intersections", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "cutaway_textures", len)) { i = len;
@@ -500,7 +500,7 @@ static int txtfmt_pov_find_specialvar(const char *string)
{
int i, len;
/* Modifiers */
- if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "projected_through", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "double_illuminate", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "expand_thresholds", len)) { i = len;
@@ -710,7 +710,7 @@ static int txtfmt_pov_find_bool(const char *string)
/* clang-format off */
/* Built-in Constants */
- if (STR_LITERAL_STARTSWITH(string, "unofficial", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "unofficial", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "false", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "no", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "off", len)) { i = len;
diff --git a/source/blender/editors/space_text/text_format_pov_ini.c b/source/blender/editors/space_text/text_format_pov_ini.c
index 04f4b992cc6..b349b38e551 100644
--- a/source/blender/editors/space_text/text_format_pov_ini.c
+++ b/source/blender/editors/space_text/text_format_pov_ini.c
@@ -49,7 +49,7 @@ static int txtfmt_ini_find_keyword(const char *string)
/* clang-format off */
/* Language Directives */
- if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "declare", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "default", len)) { i = len;
@@ -111,7 +111,7 @@ static int txtfmt_ini_find_reserved(const char *string)
* list is from...
* http://www.povray.org/documentation/view/3.7.0/212/
*/
- if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSoundEnabled", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSoundEnabled", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "Create_Continue_Trace_Log", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSoundEnabled", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSoundEnabled", len)) { i = len;
@@ -321,7 +321,7 @@ static int txtfmt_ini_find_bool(const char *string)
/* clang-format off */
/* Built-in Constants */
- if (STR_LITERAL_STARTSWITH(string, "false", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "false", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "no", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "off", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "true", len)) { i = len;
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 98eeee61c3a..d84beb79be6 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -58,11 +58,11 @@ static int txtfmt_py_find_builtinfunc(const char *string)
/* Keep aligned args for readability. */
/* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "and", len)) { i = len;
- } else if (STR_LITERAL_STARTSWITH(string, "as", len)) { i = len;
- } else if (STR_LITERAL_STARTSWITH(string, "assert", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "assert", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "async", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "await", len)) { i = len;
+ } else if (STR_LITERAL_STARTSWITH(string, "and", len)) { i = len;
+ } else if (STR_LITERAL_STARTSWITH(string, "as", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "break", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "continue", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "del", len)) { i = len;
@@ -114,7 +114,7 @@ static int txtfmt_py_find_specialvar(const char *string)
/* Keep aligned args for readability. */
/* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "def", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "def", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "class", len)) { i = len;
} else { i = 0;
}
@@ -155,7 +155,7 @@ static int txtfmt_py_find_bool(const char *string)
/* Keep aligned args for readability. */
/* clang-format off */
- if (STR_LITERAL_STARTSWITH(string, "None", len)) { i = len;
+ if (STR_LITERAL_STARTSWITH(string, "None", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "True", len)) { i = len;
} else if (STR_LITERAL_STARTSWITH(string, "False", len)) { i = len;
} else { i = 0;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index fbb6dfb8f8f..8b02a52d7f9 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -341,6 +341,9 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
v3dn->runtime.properties_storage = NULL;
}
+ v3dn->local_collections_uuid = 0;
+ v3dn->flag &= ~V3D_LOCAL_COLLECTIONS;
+
if (v3dn->shading.type == OB_RENDER) {
v3dn->shading.type = OB_SOLID;
}
@@ -1096,6 +1099,9 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win),
if (wmn->data & ND_GPENCIL_EDITMODE) {
ED_region_tag_redraw(ar);
}
+ else if (wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
break;
case NC_BRUSH:
ED_region_tag_redraw(ar);
@@ -1460,7 +1466,7 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
if (view_layer->basact) {
Object *ob = view_layer->basact->object;
/* if hidden but in edit mode, we still display, can happen with animation */
- if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT)) {
+ if ((view_layer->basact->flag & BASE_VISIBLE_DEPSGRAPH) != 0 || (ob->mode & OB_MODE_EDIT)) {
CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact);
}
}
@@ -1472,7 +1478,8 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
if (view_layer->basact) {
Object *ob = view_layer->basact->object;
/* if hidden but in edit mode, we still display, can happen with animation */
- if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
+ if ((view_layer->basact->flag & BASE_VISIBLE_DEPSGRAPH) != 0 ||
+ (ob->mode & OB_MODE_EDIT) != 0) {
CTX_data_id_pointer_set(result, &ob->id);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index aafd36a5bb8..3ee9755cb06 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1422,18 +1422,24 @@ static void draw_grid_unit_name(
{
if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
const char *grid_unit = NULL;
+ int font_id = BLF_default();
ED_view3d_grid_view_scale(scene, v3d, rv3d, &grid_unit);
if (grid_unit) {
char numstr[32] = "";
- UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
if (v3d->grid != 1.0f) {
BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
}
*yoffset -= U.widget_unit;
+ BLF_enable(font_id, BLF_SHADOW);
+ BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
+ BLF_shadow_offset(font_id, 1, -1);
BLF_draw_default_ascii(
xoffset, *yoffset, 0.0f, numstr[0] ? numstr : grid_unit, sizeof(numstr));
+
+ BLF_disable(font_id, BLF_SHADOW);
}
}
}
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index acc46935eb5..17b575cedae 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -179,7 +179,7 @@ static void validate_object_select_id(
return;
}
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
+ if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
Base *base = BKE_view_layer_base_find(view_layer, obact);
DRW_select_buffer_context_create(&base, 1, -1);
}
@@ -226,7 +226,7 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc)
ARegion *ar = vc->ar;
Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
+ if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
DRW_draw_depth_object(vc->ar, viewport, obact_eval);
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
index 615589347da..dbad06da5ec 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
@@ -25,6 +25,7 @@
#include "BKE_armature.h"
#include "BKE_action.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_object.h"
#include "DNA_object_types.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
index 42931d5abb5..ba5ca5fbd15 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
@@ -24,6 +24,7 @@
#include "BKE_camera.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "DNA_object_types.h"
#include "DNA_camera_types.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_empty.c b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
index b37f1e41294..793aec42dcd 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_empty.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
@@ -22,6 +22,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_object.h"
#include "BKE_image.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
index 44ad1d14dba..90b1539c8a7 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
@@ -21,6 +21,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_object.h"
#include "DNA_object_types.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c
index 35677b2e4c2..890de0ae611 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_light.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c
@@ -22,6 +22,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_object.h"
#include "DEG_depsgraph.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 5625333d837..a5b7fac624d 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -407,6 +407,17 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
/** \name Ruler/Grease Pencil Conversion
* \{ */
+/* Helper: Find the layer created as ruler. */
+static bGPDlayer *view3d_ruler_layer_get(bGPdata *gpd)
+{
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->flag & GP_LAYER_IS_RULER) {
+ return gpl;
+ }
+ }
+ return NULL;
+}
+
#define RULER_ID "RulerData3D"
static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
{
@@ -427,12 +438,12 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
}
gpd = scene->gpd;
- gpl = BLI_findstring(&gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ gpl = view3d_ruler_layer_get(gpd);
if (gpl == NULL) {
gpl = BKE_gpencil_layer_addnew(gpd, ruler_name, false);
copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
gpl->thickness = 1;
- gpl->flag |= GP_LAYER_HIDE;
+ gpl->flag |= GP_LAYER_HIDE | GP_LAYER_IS_RULER;
}
gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
@@ -485,8 +496,7 @@ static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *gzgroup)
if (scene->gpd) {
bGPDlayer *gpl;
- const char *ruler_name = RULER_ID;
- gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ gpl = view3d_ruler_layer_get(scene->gpd);
if (gpl) {
bGPDframe *gpf;
gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 37eea6b03d7..cfdd3dcbb6f 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -79,11 +79,7 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
BKE_copybuffer_save(bmain, str, op->reports);
- BKE_reportf(op->reports,
- RPT_INFO,
- num_copied == 1 ? "Copied %d selected object" :
- "Copied %d selected objects",
- num_copied);
+ BKE_reportf(op->reports, RPT_INFO, "Copied %d selected object(s)", num_copied);
return OPERATOR_FINISHED;
}
@@ -122,11 +118,7 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WINDOW, NULL);
- BKE_reportf(op->reports,
- RPT_INFO,
- num_pasted == 1 ? "%d object pasted" :
- "%d objects pasted",
- num_pasted);
+ BKE_reportf(op->reports, RPT_INFO, "%d object(s) pasted", num_pasted);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 198b5d05540..3eee76277e8 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1020,10 +1020,12 @@ static void do_lasso_select_armature__doSelectBone(void *userData,
is_ignore_flag |= BONESEL_TIP;
}
- if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) ||
- BLI_lasso_is_edge_inside(
- data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) {
- is_inside_flag |= BONESEL_BONE;
+ if (is_ignore_flag == 0) {
+ if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) ||
+ BLI_lasso_is_edge_inside(
+ data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) {
+ is_inside_flag |= BONESEL_BONE;
+ }
}
ebone->temp.i = is_inside_flag | (is_ignore_flag >> 16);
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index dd8e2e07271..d7af307bc53 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -1583,7 +1583,13 @@ static uint free_localcollection_bit(Main *bmain,
static void local_collections_reset_uuid(LayerCollection *layer_collection,
const unsigned short local_view_bit)
{
- layer_collection->local_collections_bits |= local_view_bit;
+ if (layer_collection->flag & LAYER_COLLECTION_HIDE) {
+ layer_collection->local_collections_bits &= ~local_view_bit;
+ }
+ else {
+ layer_collection->local_collections_bits |= local_view_bit;
+ }
+
LISTBASE_FOREACH (LayerCollection *, child, &layer_collection->layer_collections) {
local_collections_reset_uuid(child, local_view_bit);
}
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index ac9ad30d719..a7402a622d5 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -204,6 +204,8 @@ typedef struct WalkInfo {
* (this would need to un-key all previous frames).
*/
bool anim_playing;
+ bool need_rotation_keyframe;
+ bool need_translation_keyframe;
/** Previous 2D mouse values. */
int prev_mval[2];
@@ -538,6 +540,8 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
#endif
walk->anim_playing = ED_screen_animation_playing(wm);
+ walk->need_rotation_keyframe = false;
+ walk->need_translation_keyframe = false;
walk->time_lastdraw = PIL_check_seconds_timer();
@@ -930,9 +934,12 @@ static void walkMoveCamera(bContext *C,
/* we only consider autokeying on playback or if user confirmed walk on the same frame
* otherwise we get a keyframe even if the user cancels. */
const bool use_autokey = is_confirm || walk->anim_playing;
-
ED_view3d_cameracontrol_update(
walk->v3d_camera_control, use_autokey, C, do_rotate, do_translate);
+ if (use_autokey) {
+ walk->need_rotation_keyframe = false;
+ walk->need_translation_keyframe = false;
+ }
}
static float getFreeFallDistance(const float gravity, const float time)
@@ -1280,9 +1287,10 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
add_v3_v3(rv3d->ofs, dvec_tmp);
if (rv3d->persp == RV3D_CAMOB) {
- const bool do_rotate = (moffset[0] || moffset[1]);
- const bool do_translate = (walk->speed != 0.0f);
- walkMoveCamera(C, walk, do_rotate, do_translate, is_confirm);
+ walk->need_rotation_keyframe |= (moffset[0] || moffset[1]);
+ walk->need_translation_keyframe |= (len_squared_v3(dvec_tmp) > FLT_EPSILON);
+ walkMoveCamera(
+ C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm);
}
}
else {
@@ -1322,7 +1330,10 @@ static void walkApply_ndof(bContext *C, WalkInfo *walk, bool is_confirm)
walk->redraw = true;
if (walk->rv3d->persp == RV3D_CAMOB) {
- walkMoveCamera(C, walk, has_rotate, has_translate, is_confirm);
+ walk->need_rotation_keyframe |= has_rotate;
+ walk->need_translation_keyframe |= has_translate;
+ walkMoveCamera(
+ C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm);
}
}
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 67ea0f255fc..b98c14150d5 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -2346,9 +2346,11 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
- Object *ob = CTX_data_active_object(C);
- if (ob && ob->mode == OB_MODE_SCULPT && ob->sculpt) {
- options |= CTX_SCULPT;
+ if (CTX_wm_view3d(C) != NULL) {
+ Object *ob = CTX_data_active_object(C);
+ if (ob && ob->mode == OB_MODE_SCULPT && ob->sculpt) {
+ options |= CTX_SCULPT;
+ }
}
t->options = options;
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 5862faaf667..64ad8b2091e 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -429,7 +429,7 @@ static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
bone->flag |= BONE_TRANSFORM_CHILD;
}
else {
- bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
+ bone->flag &= ~BONE_TRANSFORM;
}
bone_children_clear_transflag(mode, around, &bone->childbase);
@@ -455,14 +455,14 @@ int count_set_pose_transflags(Object *ob,
bone->flag |= BONE_TRANSFORM;
}
else {
- bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
+ bone->flag &= ~BONE_TRANSFORM;
}
bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
bone->flag &= ~BONE_TRANSFORM_CHILD;
}
else {
- bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
+ bone->flag &= ~BONE_TRANSFORM;
}
}
@@ -1542,8 +1542,8 @@ void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short t
}
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & (BONE_TRANSFORM | BONE_TRANSFORM_MIRROR)) {
-
+ if ((pchan->bone->flag & BONE_TRANSFORM) ||
+ ((pose->flag & POSE_MIRROR_EDIT) && (pchan->bone->flag & BONE_TRANSFORM_MIRROR))) {
ListBase dsources = {NULL, NULL};
/* clear any 'unkeyed' flag it may have */
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 7f9c4ee2fcc..f1928433491 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -1451,7 +1451,7 @@ void createTransUVs(bContext *C, TransInfo *t)
const bool use_facesel = (ts->uv_flag & UV_SYNC_SELECTION) == 0;
elementmap = BM_uv_element_map_create(em->bm, use_facesel, false, true);
if (elementmap == NULL) {
- return;
+ continue;
}
if (is_prop_connected) {
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 53e36f86a64..2e4f4344481 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -794,6 +794,12 @@ static void pose_transform_mirror_update(Object *ob, PoseInitData_Mirror *pid)
for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig;
pchan_orig = pchan_orig->next) {
+ /* Clear the MIRROR flag from previous runs */
+ pchan_orig->bone->flag &= ~BONE_TRANSFORM_MIRROR;
+ }
+
+ for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig;
+ pchan_orig = pchan_orig->next) {
/* no layer check, correct mirror is more important */
if (pchan_orig->bone->flag & BONE_TRANSFORM) {
bPoseChannel *pchan = BKE_pose_channel_get_mirrored(ob->pose, pchan_orig->name);
@@ -1707,7 +1713,9 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
else {
- if (ISMOUSE(t->launch_event) && (U.flag & USER_RELEASECONFIRM)) {
+ /* Release confirms preference should not affect node editor (T69288, T70504). */
+ if (ISMOUSE(t->launch_event) &&
+ ((U.flag & USER_RELEASECONFIRM) || (t->spacetype == SPACE_NODE))) {
/* Global "release confirm" on mouse bindings */
t->flag |= T_RELEASE_CONFIRM;
}
@@ -1832,7 +1840,7 @@ static void freeTransCustomData(TransInfo *t, TransDataContainer *tc, TransCusto
custom_data->data = NULL;
}
/* In case modes are switched in the same transform session. */
- custom_data->free_cb = false;
+ custom_data->free_cb = NULL;
custom_data->use_free = false;
}
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 65fd9c6f5e9..157cf96a85e 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -516,9 +516,15 @@ static void protectflag_to_drawflags(short protectflag, short *drawflags)
}
/* for pose mode */
-static void protectflag_to_drawflags_pchan(RegionView3D *rv3d, const bPoseChannel *pchan)
+static void protectflag_to_drawflags_pchan(RegionView3D *rv3d,
+ const bPoseChannel *pchan,
+ short orientation_type)
{
- protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
+ /* Protect-flags apply to local space in pose mode, so only let them influence axis
+ * visibility if we show the global orientation, otherwise it's confusing. */
+ if (orientation_type == V3D_ORIENT_LOCAL) {
+ protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
+ }
}
/* for editmode*/
@@ -742,7 +748,14 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
bGPdata *gpd = CTX_data_gpencil_data(C);
const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
int a, totsel = 0;
+
const int pivot_point = scene->toolsettings->transform_pivot_point;
+ const short orientation_type = params->orientation_type ?
+ (params->orientation_type - 1) :
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+ const short orientation_index_custom =
+ params->orientation_type ? params->orientation_index_custom :
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
/* transform widget matrix */
unit_m4(rv3d->twmat);
@@ -756,12 +769,6 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
/* global, local or normal orientation?
* if we could check 'totsel' now, this should be skipped with no selection. */
if (ob) {
- const short orientation_type = params->orientation_type ?
- (params->orientation_type - 1) :
- scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
- const short orientation_index_custom =
- params->orientation_type ? params->orientation_index_custom :
- scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
float mat[3][3];
ED_transform_calc_orientation_from_type_ex(
C, mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
@@ -888,7 +895,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
calc_tw_center_with_matrix(tbounds, ebo->head, use_mat_local, mat_local);
totsel++;
}
- if (ebo->flag & BONE_SELECTED) {
+ if (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
protectflag_to_drawflags_ebone(rv3d, ebo);
}
}
@@ -1038,7 +1045,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
Bone *bone = pchan->bone;
if (bone && (bone->flag & BONE_TRANSFORM)) {
calc_tw_center_with_matrix(tbounds, pchan->pose_head, use_mat_local, mat_local);
- protectflag_to_drawflags_pchan(rv3d, pchan);
+ protectflag_to_drawflags_pchan(rv3d, pchan, orientation_type);
}
}
totsel += totsel_iter;
@@ -1122,7 +1129,12 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
calc_tw_center(tbounds, co);
}
}
- protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
+
+ /* Protect-flags apply to world space in object mode, so only let them influence axis
+ * visibility if we show the global orientation, otherwise it's confusing. */
+ if (orientation_type == V3D_ORIENT_GLOBAL) {
+ protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
+ }
totsel++;
}
@@ -1338,6 +1350,7 @@ static void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup,
}
WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_gz_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, EditBone, lock, &msg_sub_value_gz_tag_refresh);
}
void drawDial3d(const TransInfo *t)
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index cbe9505d3f2..3159464072e 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -44,6 +44,7 @@
#include "BKE_curve.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_workspace.h"
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 1601acb1c8f..f35a2808f22 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -47,6 +47,7 @@
#include "BKE_object.h"
#include "BKE_anim.h" /* for duplis */
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_tracking.h"
#include "BKE_context.h"
@@ -2367,6 +2368,7 @@ static short snapEditMesh(SnapObjectContext *sctx,
if (treedata_vert && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BLI_bvhtree_find_nearest_projected(treedata_vert->tree,
lpmat,
snapdata->win_size,
@@ -2382,6 +2384,7 @@ static short snapEditMesh(SnapObjectContext *sctx,
int last_index = nearest.index;
nearest.index = -1;
BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
+ BM_mesh_elem_index_ensure(em->bm, BM_EDGE | BM_VERT);
BLI_bvhtree_find_nearest_projected(treedata_edge->tree,
lpmat,
snapdata->win_size,
diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h
index f4fd2b132e8..263b5429161 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.h
+++ b/source/blender/freestyle/intern/stroke/Stroke.h
@@ -590,7 +590,8 @@ class Stroke : public Interface1D {
/*! Resampling method.
* Resamples the curve so that it eventually has iNPoints. That means it is going to add
* iNPoints-vertices_size, if vertices_size is the number of points we already have. If
- * vertices_size >= iNPoints, no resampling is done. \param iNPoints: The number of vertices we
+ * vertices_size >= iNPoints, no resampling is done.
+ * \param iNPoints: The number of vertices we
* eventually want in our stroke.
*/
int Resample(int iNPoints);
@@ -840,8 +841,10 @@ class Stroke : public Interface1D {
vertex_iterator vertices_end();
/*! Returns a StrokeVertexIterator pointing on the first StrokeVertex of the Stroke. One can
- * specify a sampling value to resample the Stroke on the fly if needed. \param t: The resampling
- * value with which we want our Stroke to be resampled. If 0 is specified, no resampling is done.
+ * specify a sampling value to resample the Stroke on the fly if needed.
+ *
+ * \param t: The resampling value with which we want our Stroke to be resampled.
+ * If 0 is specified, no resampling is done.
*/
StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t = 0.0f);
diff --git a/source/blender/freestyle/intern/view_map/Interface1D.h b/source/blender/freestyle/intern/view_map/Interface1D.h
index 7a72a176902..ab489bff4c9 100644
--- a/source/blender/freestyle/intern/view_map/Interface1D.h
+++ b/source/blender/freestyle/intern/view_map/Interface1D.h
@@ -156,15 +156,17 @@ class Interface1D {
/*! Returns an iterator over the Interface1D points, pointing to the first point. The difference
* with verticesBegin() is that here we can iterate over points of the 1D element at a any given
- * sampling. Indeed, for each iteration, a virtual point is created. \param t: The sampling with
- * which we want to iterate over points of this 1D element.
+ * sampling. Indeed, for each iteration, a virtual point is created.
+ *
+ * \param t: The sampling with which we want to iterate over points of this 1D element.
*/
virtual Interface0DIterator pointsBegin(float t = 0.0f);
/*! Returns an iterator over the Interface1D points, pointing after the last point. The
* difference with verticesEnd() is that here we can iterate over points of the 1D element at a
- * any given sampling. Indeed, for each iteration, a virtual point is created. \param t: The
- * sampling with which we want to iterate over points of this 1D element.
+ * any given sampling. Indeed, for each iteration, a virtual point is created.
+ *
+ * \param t: The sampling with which we want to iterate over points of this 1D element.
*/
virtual Interface0DIterator pointsEnd(float t = 0.0f);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
index 1f2f0554dd5..27c8175af3f 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
@@ -203,5 +203,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Armature = {
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
index c311497ffbb..bb70b548675 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
@@ -317,14 +317,6 @@ static void foreachObjectLink(GpencilModifierData *md,
walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
}
-static int getDuplicationFactor(GpencilModifierData *md)
-{
- ArrayGpencilModifierData *mmd = (ArrayGpencilModifierData *)md;
- int t = mmd->count;
- CLAMP_MIN(t, 1);
- return t;
-}
-
GpencilModifierTypeInfo modifierType_Gpencil_Array = {
/* name */ "Array",
/* structName */ "ArrayGpencilModifierData",
@@ -347,5 +339,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Array = {
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ getDuplicationFactor,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
index d72ace7a191..e3e7168330d 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
@@ -550,5 +550,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Build = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
index cb429b874a2..cbe2d9a4c4f 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
@@ -168,5 +168,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Color = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
index 234b4deeceb..bc62d0d69bb 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
@@ -357,5 +357,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Hook = {
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
index 6b74f96ce31..9dbf7b35bc5 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
@@ -219,5 +219,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Lattice = {
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
index e391adde829..ef06e14b3d7 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
@@ -203,21 +203,6 @@ static void foreachObjectLink(GpencilModifierData *md,
walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
}
-static int getDuplicationFactor(GpencilModifierData *md)
-{
- MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md;
- int factor = 1;
- /* create a duplication for each axis */
- for (int xi = 0; xi < 3; xi++) {
- if (mmd->flag & (GP_MIRROR_AXIS_X << xi)) {
- factor++;
- }
- }
- CLAMP_MIN(factor, 1);
-
- return factor;
-}
-
GpencilModifierTypeInfo modifierType_Gpencil_Mirror = {
/* name */ "Mirror",
/* structName */ "MirrorGpencilModifierData",
@@ -240,5 +225,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Mirror = {
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ getDuplicationFactor,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
index b286b55829e..f34477aaab2 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
@@ -274,5 +274,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Noise = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
index 08f67eedc86..70d463fff76 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
@@ -148,5 +148,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Offset = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
index 22610771045..c0892a1d91a 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
@@ -206,5 +206,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Opacity = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
index 25a56c4385c..9594fc8581e 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
@@ -144,5 +144,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Simplify = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
index 5ec7fe4ff18..68060711681 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
@@ -155,5 +155,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Smooth = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
index ce75ca59fe1..89d6565d0dd 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
@@ -67,7 +67,7 @@ static void deformStroke(GpencilModifierData *md,
/* It makes sense when adding points to a straight line */
/* e.g. for creating thickness variation in later modifiers. */
- const int minimum_vert = (mmd->flag | GP_SUBDIV_SIMPLE) ? 2 : 3;
+ const int minimum_vert = (mmd->flag & GP_SUBDIV_SIMPLE) ? 2 : 3;
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
@@ -103,14 +103,6 @@ static void bakeModifier(struct Main *UNUSED(bmain),
}
}
-static int getDuplicationFactor(GpencilModifierData *md)
-{
- SubdivGpencilModifierData *mmd = (SubdivGpencilModifierData *)md;
- int t = (mmd->level + 1) * (mmd->level + 1);
- CLAMP_MIN(t, 2);
- return t;
-}
-
GpencilModifierTypeInfo modifierType_Gpencil_Subdiv = {
/* name */ "Subdivision",
/* structName */ "SubdivGpencilModifierData",
@@ -133,5 +125,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Subdiv = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ getDuplicationFactor,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
index e9e92f7a1e2..036464e718d 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
@@ -210,5 +210,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Thick = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c
index 296e01d6d31..01bb0ae2b93 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c
@@ -182,5 +182,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Time = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
index f6ddcf89bcf..f03bc489521 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
@@ -174,5 +174,4 @@ GpencilModifierTypeInfo modifierType_Gpencil_Tint = {
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
- /* getDuplicationFactor */ NULL,
};
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index bc08da4b2cb..9320e849194 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -69,6 +69,7 @@ set(SRC
intern/gpu_init_exit.c
intern/gpu_material.c
intern/gpu_matrix.c
+ intern/gpu_platform.c
intern/gpu_primitive.c
intern/gpu_select.c
intern/gpu_select_pick.c
@@ -101,6 +102,7 @@ set(SRC
GPU_legacy_stubs.h
GPU_material.h
GPU_matrix.h
+ GPU_platform.h
GPU_primitive.h
GPU_select.h
GPU_shader.h
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
index 7d8c3347eb4..d7218e97bf0 100644
--- a/source/blender/gpu/GPU_batch.h
+++ b/source/blender/gpu/GPU_batch.h
@@ -193,8 +193,10 @@ GPUBatch *create_BatchInGeneral(GPUPrimType, VertexBufferStuff, ElementListStuff
#endif /* future plans */
-/* GPUDrawList is an API to do lots of similar drawcalls very fast using multidrawindirect.
- * There is a fallback if the feature is not supported. */
+/**
+ * #GPUDrawList is an API to do lots of similar draw-calls very fast using multi-draw-indirect.
+ * There is a fallback if the feature is not supported.
+ */
typedef struct GPUDrawList GPUDrawList;
GPUDrawList *GPU_draw_list_create(int length);
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 552bad2b0d6..6d2b0ad3be3 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -31,6 +31,7 @@ struct CCGElem;
struct CCGKey;
struct DMFlagMat;
struct GSet;
+struct Mesh;
struct MLoop;
struct MLoopCol;
struct MLoopTri;
@@ -49,7 +50,8 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
const struct MLoopTri *looptri,
const struct MVert *verts,
const int *face_indices,
- const int face_indices_len);
+ const int face_indices_len,
+ const struct Mesh *mesh);
GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, unsigned int **grid_hidden);
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 023cbb804d9..245f7f47510 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -55,34 +55,6 @@ void GPU_mem_stats_get(int *totalmem, int *freemem);
void GPU_code_generate_glsl_lib(void);
-/* GPU Types */
-
-typedef enum eGPUDeviceType {
- GPU_DEVICE_NVIDIA = (1 << 0),
- GPU_DEVICE_ATI = (1 << 1),
- GPU_DEVICE_INTEL = (1 << 2),
- GPU_DEVICE_INTEL_UHD = (1 << 3),
- GPU_DEVICE_SOFTWARE = (1 << 4),
- GPU_DEVICE_UNKNOWN = (1 << 5),
- GPU_DEVICE_ANY = (0xff),
-} eGPUDeviceType;
-
-typedef enum eGPUOSType {
- GPU_OS_WIN = (1 << 8),
- GPU_OS_MAC = (1 << 9),
- GPU_OS_UNIX = (1 << 10),
- GPU_OS_ANY = (0xff00),
-} eGPUOSType;
-
-typedef enum eGPUDriverType {
- GPU_DRIVER_OFFICIAL = (1 << 16),
- GPU_DRIVER_OPENSOURCE = (1 << 17),
- GPU_DRIVER_SOFTWARE = (1 << 18),
- GPU_DRIVER_ANY = (0xff0000),
-} eGPUDriverType;
-
-bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_platform.h b/source/blender/gpu/GPU_platform.h
new file mode 100644
index 00000000000..f199a748cb5
--- /dev/null
+++ b/source/blender/gpu/GPU_platform.h
@@ -0,0 +1,75 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_PLATFORM_H__
+#define __GPU_PLATFORM_H__
+
+#include "BLI_sys_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* GPU platform support */
+
+/* GPU Types */
+typedef enum eGPUDeviceType {
+ GPU_DEVICE_NVIDIA = (1 << 0),
+ GPU_DEVICE_ATI = (1 << 1),
+ GPU_DEVICE_INTEL = (1 << 2),
+ GPU_DEVICE_INTEL_UHD = (1 << 3),
+ GPU_DEVICE_SOFTWARE = (1 << 4),
+ GPU_DEVICE_UNKNOWN = (1 << 5),
+ GPU_DEVICE_ANY = (0xff),
+} eGPUDeviceType;
+
+typedef enum eGPUOSType {
+ GPU_OS_WIN = (1 << 8),
+ GPU_OS_MAC = (1 << 9),
+ GPU_OS_UNIX = (1 << 10),
+ GPU_OS_ANY = (0xff00),
+} eGPUOSType;
+
+typedef enum eGPUDriverType {
+ GPU_DRIVER_OFFICIAL = (1 << 16),
+ GPU_DRIVER_OPENSOURCE = (1 << 17),
+ GPU_DRIVER_SOFTWARE = (1 << 18),
+ GPU_DRIVER_ANY = (0xff0000),
+} eGPUDriverType;
+
+typedef enum eGPUSupportLevel {
+ GPU_SUPPORT_LEVEL_SUPPORTED,
+ GPU_SUPPORT_LEVEL_LIMITED,
+ GPU_SUPPORT_LEVEL_UNSUPPORTED,
+} eGPUSupportLevel;
+
+bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver);
+eGPUSupportLevel GPU_platform_support_level(void);
+const char *GPU_platform_support_level_key(void);
+const char *GPU_platform_gpu_name(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_PLATFORM_H__ */
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index 2620ba49799..fc578b4466c 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -29,6 +29,7 @@
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
#include "GPU_extensions.h"
+#include "GPU_platform.h"
#include "GPU_matrix.h"
#include "GPU_shader.h"
@@ -718,8 +719,11 @@ void GPU_draw_primitive(GPUPrimType prim_type, int v_count)
#if 0
# define USE_MULTI_DRAW_INDIRECT 0
#else
+/* TODO: partial workaround for NVIDIA driver bug on recent GTX/RTX cards,
+ * that breaks instancing when using indirect draw-call (see T70011). */
# define USE_MULTI_DRAW_INDIRECT \
- (GL_ARB_multi_draw_indirect && GPU_arb_base_instance_is_supported())
+ (GL_ARB_multi_draw_indirect && GPU_arb_base_instance_is_supported() && \
+ !GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL))
#endif
typedef struct GPUDrawCommand {
@@ -852,16 +856,19 @@ void GPU_draw_list_submit(GPUDrawList *list)
uintptr_t offset = list->cmd_offset;
uint cmd_len = list->cmd_len;
size_t bytes_used = cmd_len * sizeof(GPUDrawCommandIndexed);
- list->cmd_offset += bytes_used;
list->cmd_len = 0; /* Avoid reuse. */
- if (USE_MULTI_DRAW_INDIRECT) {
+ /* Only do multi-draw indirect if doing more than 2 drawcall.
+ * This avoids the overhead of buffer mapping if scene is
+ * not very instance friendly. */
+ if (USE_MULTI_DRAW_INDIRECT && cmd_len > 2) {
GLenum prim = batch->gl_prim_type;
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, list->buffer_id);
glFlushMappedBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, bytes_used);
glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);
list->commands = NULL; /* Unmapped */
+ list->cmd_offset += bytes_used;
if (batch->elem) {
glMultiDrawElementsIndirect(prim, INDEX_TYPE(batch->elem), (void *)offset, cmd_len, 0);
@@ -875,6 +882,8 @@ void GPU_draw_list_submit(GPUDrawList *list)
if (batch->elem) {
GPUDrawCommandIndexed *cmd = list->commands_indexed;
for (int i = 0; i < cmd_len; i++, cmd++) {
+ /* Index start was added by Draw manager. Avoid counting it twice. */
+ cmd->v_first -= batch->elem->index_start;
GPU_batch_draw_advanced(batch, cmd->v_first, cmd->v_count, cmd->i_first, cmd->i_count);
}
}
diff --git a/source/blender/gpu/intern/gpu_batch_utils.c b/source/blender/gpu/intern/gpu_batch_utils.c
index 3a8b392ef1d..825f72e175b 100644
--- a/source/blender/gpu/intern/gpu_batch_utils.c
+++ b/source/blender/gpu/intern/gpu_batch_utils.c
@@ -164,7 +164,6 @@ GPUBatch *GPU_batch_wire_from_poly_2d_encoded(const uchar *polys_flat,
BLI_assert(polys_step_len >= 2);
for (uint i_prev = polys_step_len - 1, i = 0; i < polys_step_len; i_prev = i++) {
union {
- uint8_t as_u8[4];
uint16_t as_u16[2];
uint32_t as_u32;
} data;
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index ed606ccb8c6..2c74afd2d8e 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -316,10 +316,12 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
const MLoopTri *looptri,
const MVert *mvert,
const int *face_indices,
- const int face_indices_len)
+ const int face_indices_len,
+ const struct Mesh *mesh)
{
GPU_PBVH_Buffers *buffers;
int i, tottri;
+ int tot_real_edges = 0;
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
@@ -332,6 +334,13 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
for (i = 0, tottri = 0; i < face_indices_len; i++) {
const MLoopTri *lt = &looptri[face_indices[i]];
if (!paint_is_face_hidden(lt, mvert, mloop)) {
+ int r_edges[3];
+ BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges);
+ for (int j = 0; j < 3; j++) {
+ if (r_edges[j] != -1) {
+ tot_real_edges++;
+ }
+ }
tottri++;
}
}
@@ -355,7 +364,7 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
/* Fill the triangle and line buffers. */
GPUIndexBufBuilder elb, elb_lines;
GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, INT_MAX);
- GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, INT_MAX);
+ GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tot_real_edges, INT_MAX);
for (i = 0; i < face_indices_len; i++) {
const MLoopTri *lt = &looptri[face_indices[i]];
@@ -366,11 +375,18 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
}
GPU_indexbuf_add_tri_verts(&elb, UNPACK3(face_vert_indices[i]));
+ int r_edges[3];
+ BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges);
- /* TODO skip "non-real" edges. */
- GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][0], face_vert_indices[i][1]);
- GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][1], face_vert_indices[i][2]);
- GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][2], face_vert_indices[i][0]);
+ if (r_edges[0] != -1) {
+ GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][0], face_vert_indices[i][1]);
+ }
+ if (r_edges[1] != -1) {
+ GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][1], face_vert_indices[i][2]);
+ }
+ if (r_edges[2] != -1) {
+ GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][2], face_vert_indices[i][0]);
+ }
}
buffers->index_buf = GPU_indexbuf_build(&elb);
buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
@@ -378,7 +394,7 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
else {
/* Fill the only the line buffer. */
GPUIndexBufBuilder elb_lines;
- GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, INT_MAX);
+ GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tot_real_edges, INT_MAX);
int vert_idx = 0;
for (i = 0; i < face_indices_len; i++) {
@@ -389,10 +405,18 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
continue;
}
- /* TODO skip "non-real" edges. */
- GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 0, vert_idx * 3 + 1);
- GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 1, vert_idx * 3 + 2);
- GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 2, vert_idx * 3 + 0);
+ int r_edges[3];
+ BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges);
+ if (r_edges[0] != -1) {
+ GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 0, vert_idx * 3 + 1);
+ }
+ if (r_edges[1] != -1) {
+ GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 1, vert_idx * 3 + 2);
+ }
+ if (r_edges[2] != -1) {
+ GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 2, vert_idx * 3 + 0);
+ }
+
vert_idx++;
}
buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
@@ -729,47 +753,36 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hid
/** \name BMesh PBVH
* \{ */
-/* Output a BMVert into a VertexBufferFormat array
- *
- * The vertex is skipped if hidden, otherwise the output goes into
- * index '*v_index' in the 'vert_data' array and '*v_index' is
- * incremented.
- */
-static void gpu_bmesh_vert_to_buffer_copy__gwn(BMVert *v,
- GPUVertBuf *vert_buf,
- int *v_index,
- const float fno[3],
- const float *fmask,
- const int cd_vert_mask_offset,
- const bool show_mask,
- const bool show_vcol,
- bool *empty_mask)
+/* Output a BMVert into a VertexBufferFormat array at v_index. */
+static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
+ GPUVertBuf *vert_buf,
+ int v_index,
+ const float fno[3],
+ const float *fmask,
+ const int cd_vert_mask_offset,
+ const bool show_mask,
+ const bool show_vcol,
+ bool *empty_mask)
{
- if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
-
- /* Set coord, normal, and mask */
- GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co);
-
- short no_short[3];
- normal_float_to_short_v3(no_short, fno ? fno : v->no);
- GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short);
+ /* Vertex should always be visible if it's used by a visible face. */
+ BLI_assert(!BM_elem_flag_test(v, BM_ELEM_HIDDEN));
- if (show_mask) {
- float effective_mask = fmask ? *fmask : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
- GPU_vertbuf_attr_set(vert_buf, g_vbo_id.msk, *v_index, &effective_mask);
- *empty_mask = *empty_mask && (effective_mask == 0.0f);
- }
+ /* Set coord, normal, and mask */
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, v_index, v->co);
- if (show_vcol) {
- static char vcol[4] = {255, 255, 255, 255};
- GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col, *v_index, &vcol);
- }
+ short no_short[3];
+ normal_float_to_short_v3(no_short, fno ? fno : v->no);
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, v_index, no_short);
- /* Assign index for use in the triangle index buffer */
- /* note: caller must set: bm->elem_index_dirty |= BM_VERT; */
- BM_elem_index_set(v, (*v_index)); /* set_dirty! */
+ if (show_mask) {
+ float effective_mask = fmask ? *fmask : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.msk, v_index, &effective_mask);
+ *empty_mask = *empty_mask && (effective_mask == 0.0f);
+ }
- (*v_index)++;
+ if (show_vcol) {
+ static char vcol[4] = {255, 255, 255, 255};
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col, v_index, &vcol);
}
}
@@ -839,7 +852,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
{
const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
- int tottri, totvert, maxvert = 0;
+ int tottri, totvert;
bool empty_mask = true;
BMFace *f = NULL;
@@ -869,135 +882,118 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
/* Fill vertex buffer */
- if (gpu_pbvh_vert_buf_data_set(buffers, totvert)) {
- int v_index = 0;
-
- if (buffers->smooth) {
- GSetIterator gs_iter;
-
- /* Vertices get an index assigned for use in the triangle
- * index buffer */
- bm->elem_index_dirty |= BM_VERT;
-
- GSET_ITER (gs_iter, bm_unique_verts) {
- gpu_bmesh_vert_to_buffer_copy__gwn(BLI_gsetIterator_getKey(&gs_iter),
- buffers->vert_buf,
- &v_index,
- NULL,
- NULL,
- cd_vert_mask_offset,
- show_mask,
- show_vcol,
- &empty_mask);
- }
-
- GSET_ITER (gs_iter, bm_other_verts) {
- gpu_bmesh_vert_to_buffer_copy__gwn(BLI_gsetIterator_getKey(&gs_iter),
- buffers->vert_buf,
- &v_index,
- NULL,
- NULL,
- cd_vert_mask_offset,
- show_mask,
- show_vcol,
- &empty_mask);
- }
+ if (!gpu_pbvh_vert_buf_data_set(buffers, totvert)) {
+ /* Memory map failed */
+ return;
+ }
- maxvert = v_index;
- }
- else {
- GSetIterator gs_iter;
+ int v_index = 0;
- GPUIndexBufBuilder elb_lines;
- GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert);
+ if (buffers->smooth) {
+ /* Fill the vertex and triangle buffer in one pass over faces. */
+ GPUIndexBufBuilder elb, elb_lines;
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, totvert);
+ GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert);
- GSET_ITER (gs_iter, bm_faces) {
- f = BLI_gsetIterator_getKey(&gs_iter);
+ GHash *bm_vert_to_index = BLI_ghash_int_new_ex("bm_vert_to_index", totvert);
- BLI_assert(f->len == 3);
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, bm_faces) {
+ f = BLI_gsetIterator_getKey(&gs_iter);
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- BMVert *v[3];
- float fmask = 0.0f;
- int i;
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ BMVert *v[3];
+ BM_face_as_array_vert_tri(f, v);
- BM_face_as_array_vert_tri(f, v);
+ uint idx[3];
+ for (int i = 0; i < 3; i++) {
+ void **idx_p;
+ if (!BLI_ghash_ensure_p(bm_vert_to_index, v[i], &idx_p)) {
+ /* Add vertex to the vertex buffer each time a new one is encountered */
+ *idx_p = POINTER_FROM_UINT(v_index);
- /* Average mask value */
- for (i = 0; i < 3; i++) {
- fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset);
+ gpu_bmesh_vert_to_buffer_copy(v[i],
+ buffers->vert_buf,
+ v_index,
+ NULL,
+ NULL,
+ cd_vert_mask_offset,
+ show_mask,
+ show_vcol,
+ &empty_mask);
+
+ idx[i] = v_index;
+ v_index++;
}
- fmask /= 3.0f;
-
- GPU_indexbuf_add_line_verts(&elb_lines, v_index + 0, v_index + 1);
- GPU_indexbuf_add_line_verts(&elb_lines, v_index + 1, v_index + 2);
- GPU_indexbuf_add_line_verts(&elb_lines, v_index + 2, v_index + 0);
-
- for (i = 0; i < 3; i++) {
- gpu_bmesh_vert_to_buffer_copy__gwn(v[i],
- buffers->vert_buf,
- &v_index,
- f->no,
- &fmask,
- cd_vert_mask_offset,
- show_mask,
- show_vcol,
- &empty_mask);
+ else {
+ /* Vertex already in the vertex buffer, just get the index. */
+ idx[i] = POINTER_AS_UINT(*idx_p);
}
}
- }
- buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
- buffers->tot_tri = tottri;
+ GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
+
+ GPU_indexbuf_add_line_verts(&elb_lines, idx[0], idx[1]);
+ GPU_indexbuf_add_line_verts(&elb_lines, idx[1], idx[2]);
+ GPU_indexbuf_add_line_verts(&elb_lines, idx[2], idx[0]);
+ }
}
- /* gpu_bmesh_vert_to_buffer_copy sets dirty index values */
- bm->elem_index_dirty |= BM_VERT;
+ BLI_ghash_free(bm_vert_to_index, NULL, NULL);
+
+ buffers->tot_tri = tottri;
+ if (buffers->index_buf == NULL) {
+ buffers->index_buf = GPU_indexbuf_build(&elb);
+ }
+ else {
+ GPU_indexbuf_build_in_place(&elb, buffers->index_buf);
+ }
+ buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
}
else {
- /* Memory map failed */
- return;
- }
+ GSetIterator gs_iter;
- if (buffers->smooth) {
- /* Fill the triangle buffer */
- GPUIndexBufBuilder elb, elb_lines;
- GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, maxvert);
- GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, maxvert);
-
- /* Fill triangle index buffer */
- {
- GSetIterator gs_iter;
+ GPUIndexBufBuilder elb_lines;
+ GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, tottri * 3);
- GSET_ITER (gs_iter, bm_faces) {
- f = BLI_gsetIterator_getKey(&gs_iter);
+ GSET_ITER (gs_iter, bm_faces) {
+ f = BLI_gsetIterator_getKey(&gs_iter);
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- BMVert *v[3];
+ BLI_assert(f->len == 3);
- BM_face_as_array_vert_tri(f, v);
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ BMVert *v[3];
+ float fmask = 0.0f;
+ int i;
- const uint idx[3] = {
- BM_elem_index_get(v[0]), BM_elem_index_get(v[1]), BM_elem_index_get(v[2])};
- GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
+ BM_face_as_array_vert_tri(f, v);
- GPU_indexbuf_add_line_verts(&elb_lines, idx[0], idx[1]);
- GPU_indexbuf_add_line_verts(&elb_lines, idx[1], idx[2]);
- GPU_indexbuf_add_line_verts(&elb_lines, idx[2], idx[0]);
+ /* Average mask value */
+ for (i = 0; i < 3; i++) {
+ fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset);
+ }
+ fmask /= 3.0f;
+
+ GPU_indexbuf_add_line_verts(&elb_lines, v_index + 0, v_index + 1);
+ GPU_indexbuf_add_line_verts(&elb_lines, v_index + 1, v_index + 2);
+ GPU_indexbuf_add_line_verts(&elb_lines, v_index + 2, v_index + 0);
+
+ for (i = 0; i < 3; i++) {
+ gpu_bmesh_vert_to_buffer_copy(v[i],
+ buffers->vert_buf,
+ v_index++,
+ f->no,
+ &fmask,
+ cd_vert_mask_offset,
+ show_mask,
+ show_vcol,
+ &empty_mask);
}
}
-
- buffers->tot_tri = tottri;
-
- if (buffers->index_buf == NULL) {
- buffers->index_buf = GPU_indexbuf_build(&elb);
- }
- else {
- GPU_indexbuf_build_in_place(&elb, buffers->index_buf);
- }
-
- buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
}
+
+ buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
+ buffers->tot_tri = tottri;
}
/* Get material index from the last face we iterated on. */
@@ -1054,6 +1050,7 @@ void GPU_pbvh_buffers_update_flush(GPU_PBVH_Buffers *buffers)
GPU_BATCH_DISCARD_SAFE(buffers->triangles);
GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
+ buffers->clear_bmesh_on_flush = false;
}
/* Force flushing to the GPU. */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index c9ae6c60293..7fa2eb6424c 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -66,6 +66,7 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
+#include "GPU_platform.h"
#include "GPU_texture.h"
#include "PIL_time.h"
diff --git a/source/blender/gpu/intern/gpu_element.c b/source/blender/gpu/intern/gpu_element.c
index 166a6236893..518829d1c78 100644
--- a/source/blender/gpu/intern/gpu_element.c
+++ b/source/blender/gpu/intern/gpu_element.c
@@ -243,7 +243,7 @@ GPUIndexBuf *GPU_indexbuf_create_subrange(GPUIndexBuf *elem_src, uint start, uin
{
GPUIndexBuf *elem = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
BLI_assert(elem_src && !elem_src->is_subrange);
- BLI_assert(start + length <= elem_src->index_len);
+ BLI_assert((length == 0) || (start + length <= elem_src->index_len));
#if GPU_TRACK_INDEX_RANGE
elem->index_type = elem_src->index_type;
elem->gl_index_type = elem_src->gl_index_type;
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index c6425854ee4..33f918559f7 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -35,6 +35,7 @@
#include "GPU_framebuffer.h"
#include "GPU_glew.h"
#include "GPU_texture.h"
+#include "GPU_platform.h"
#include "intern/gpu_private.h"
@@ -68,9 +69,6 @@ static struct GPUGlobal {
GLint maxubosize;
GLint maxubobinds;
int samples_color_texture_max;
- eGPUDeviceType device;
- eGPUOSType os;
- eGPUDriverType driver;
float line_width_range[2];
/* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
* calculate dfdy in shader differently when drawing to an offscreen buffer. First
@@ -126,13 +124,6 @@ static void gpu_detect_mip_render_workaround(void)
GPU_texture_free(tex);
}
-/* GPU Types */
-
-bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
-{
- return (GG.device & device) && (GG.os & os) && (GG.driver & driver);
-}
-
/* GPU Extensions */
int GPU_max_texture_size(void)
@@ -266,11 +257,7 @@ void gpu_extensions_init(void)
const char *renderer = (const char *)glGetString(GL_RENDERER);
const char *version = (const char *)glGetString(GL_VERSION);
- if (strstr(vendor, "ATI") || strstr(vendor, "AMD")) {
- GG.device = GPU_DEVICE_ATI;
- GG.driver = GPU_DRIVER_OFFICIAL;
-
-#ifdef _WIN32
+ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_OFFICIAL)) {
if (strstr(version, "4.5.13399") || strstr(version, "4.5.13417") ||
strstr(version, "4.5.13422")) {
/* The renderers include:
@@ -282,75 +269,14 @@ void gpu_extensions_init(void)
GG.unused_fb_slot_workaround = true;
}
-#endif
+ }
-#if defined(__APPLE__)
+ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_MAC, GPU_DRIVER_OFFICIAL)) {
if (strstr(renderer, "AMD Radeon Pro") || strstr(renderer, "AMD Radeon R9") ||
strstr(renderer, "AMD Radeon RX")) {
GG.depth_blitting_workaround = true;
}
-#endif
- }
- else if (strstr(vendor, "NVIDIA")) {
- GG.device = GPU_DEVICE_NVIDIA;
- GG.driver = GPU_DRIVER_OFFICIAL;
- }
- else if (strstr(vendor, "Intel") ||
- /* src/mesa/drivers/dri/intel/intel_context.c */
- strstr(renderer, "Mesa DRI Intel") || strstr(renderer, "Mesa DRI Mobile Intel")) {
- GG.device = GPU_DEVICE_INTEL;
- GG.driver = GPU_DRIVER_OFFICIAL;
-
- if (strstr(renderer, "UHD Graphics") ||
- /* Not UHD but affected by the same bugs. */
- strstr(renderer, "HD Graphics 530") || strstr(renderer, "Kaby Lake GT2")) {
- GG.device |= GPU_DEVICE_INTEL_UHD;
- }
}
- else if ((strstr(renderer, "Mesa DRI R")) ||
- (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) ||
- (strstr(renderer, "AMD") && strstr(vendor, "X.Org")) ||
- (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) ||
- (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD "))) {
- GG.device = GPU_DEVICE_ATI;
- GG.driver = GPU_DRIVER_OPENSOURCE;
- }
- else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
- GG.device = GPU_DEVICE_NVIDIA;
- GG.driver = GPU_DRIVER_OPENSOURCE;
- }
- else if (strstr(vendor, "Mesa")) {
- GG.device = GPU_DEVICE_SOFTWARE;
- GG.driver = GPU_DRIVER_SOFTWARE;
- }
- else if (strstr(vendor, "Microsoft")) {
- GG.device = GPU_DEVICE_SOFTWARE;
- GG.driver = GPU_DRIVER_SOFTWARE;
- }
- else if (strstr(renderer, "Apple Software Renderer")) {
- GG.device = GPU_DEVICE_SOFTWARE;
- GG.driver = GPU_DRIVER_SOFTWARE;
- }
- else if (strstr(renderer, "llvmpipe")) {
- GG.device = GPU_DEVICE_SOFTWARE;
- GG.driver = GPU_DRIVER_SOFTWARE;
- }
- else {
- printf("Warning: Could not find a matching GPU name. Things may not behave as expected.\n");
- printf("Detected OpenGL configuration:\n");
- printf("Vendor: %s\n", vendor);
- printf("Renderer: %s\n", renderer);
- GG.device = GPU_DEVICE_ANY;
- GG.driver = GPU_DRIVER_ANY;
- }
-
-#ifdef _WIN32
- GG.os = GPU_OS_WIN;
-#elif defined(__APPLE__)
- GG.os = GPU_OS_MAC;
-#else
- GG.os = GPU_OS_UNIX;
-#endif
GG.glew_arb_base_instance_is_supported = GLEW_ARB_base_instance;
gpu_detect_mip_render_workaround();
@@ -372,11 +298,12 @@ void gpu_extensions_init(void)
GG.dfdyfactors[0] = 1.0;
GG.dfdyfactors[1] = 1.0;
- if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) {
+ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY) &&
+ strstr(version, "3.3.10750")) {
GG.dfdyfactors[0] = 1.0;
GG.dfdyfactors[1] = -1.0;
}
- else if ((GG.device == GPU_DEVICE_INTEL) && (GG.os == GPU_OS_WIN)) {
+ else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY)) {
if (strstr(version, "4.0.0 - Build 10.18.10.3308") ||
strstr(version, "4.0.0 - Build 9.18.10.3186") ||
strstr(version, "4.0.0 - Build 9.18.10.3165") ||
@@ -401,8 +328,7 @@ void gpu_extensions_init(void)
GG.context_local_shaders_workaround = true;
}
}
- else if ((GG.device == GPU_DEVICE_ATI) && (GG.os == GPU_OS_UNIX) &&
- (GG.driver == GPU_DRIVER_OPENSOURCE)) {
+ else if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) {
/* See T70187: merging vertices fail. This has been tested from 18.2.2 till 19.3.0~dev of the
* Mesa driver */
GG.unused_fb_slot_workaround = true;
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 0009e7d8c47..7b6016e11cb 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -46,7 +46,7 @@ void GPU_init(void)
}
initialized = true;
-
+ gpu_platform_init();
gpu_extensions_init(); /* must come first */
gpu_codegen_init();
@@ -82,7 +82,8 @@ void GPU_exit(void)
gpu_framebuffer_module_exit();
gpu_codegen_exit();
- gpu_extensions_exit(); /* must come last */
+ gpu_extensions_exit();
+ gpu_platform_exit(); /* must come last */
initialized = false;
}
diff --git a/source/blender/gpu/intern/gpu_platform.c b/source/blender/gpu/intern/gpu_platform.c
new file mode 100644
index 00000000000..871052bb070
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_platform.c
@@ -0,0 +1,229 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Wrap OpenGL features such as textures, shaders and GLSL
+ * with checks for drivers and GPU support.
+ */
+#include "GPU_platform.h"
+#include "GPU_glew.h"
+#include "gpu_private.h"
+
+#include <string.h>
+
+#include "BLI_dynstr.h"
+#include "BLI_string.h"
+
+#include "MEM_guardedalloc.h"
+
+static struct GPUPlatformGlobal {
+ bool initialized;
+ eGPUDeviceType device;
+ eGPUOSType os;
+ eGPUDriverType driver;
+ eGPUSupportLevel support_level;
+ char *support_key;
+ char *gpu_name;
+} GPG = {false};
+
+typedef struct GPUPlatformSupportTest {
+ eGPUSupportLevel support_level;
+ eGPUDeviceType device;
+ eGPUOSType os;
+ eGPUDriverType driver;
+ const char *vendor;
+ const char *renderer;
+ const char *version;
+} GPUPlatformSupportTest;
+
+eGPUSupportLevel GPU_platform_support_level(void)
+{
+ return GPG.support_level;
+}
+
+const char *GPU_platform_support_level_key(void)
+{
+ return GPG.support_key;
+}
+
+const char *GPU_platform_gpu_name(void)
+{
+ return GPG.gpu_name;
+}
+
+/* GPU Types */
+bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
+{
+ return (GPG.device & device) && (GPG.os & os) && (GPG.driver & driver);
+}
+
+static char *gpu_platform_create_key(eGPUSupportLevel support_level,
+ const char *vendor,
+ const char *renderer,
+ const char *version)
+{
+ DynStr *ds = BLI_dynstr_new();
+ BLI_dynstr_append(ds, "{");
+ BLI_dynstr_append(ds, vendor);
+ BLI_dynstr_append(ds, "/");
+ BLI_dynstr_append(ds, renderer);
+ BLI_dynstr_append(ds, "/");
+ BLI_dynstr_append(ds, version);
+ BLI_dynstr_append(ds, "}");
+ BLI_dynstr_append(ds, "=");
+ if (support_level == GPU_SUPPORT_LEVEL_SUPPORTED) {
+ BLI_dynstr_append(ds, "SUPPORTED");
+ }
+ else if (support_level == GPU_SUPPORT_LEVEL_LIMITED) {
+ BLI_dynstr_append(ds, "LIMITED");
+ }
+ else {
+ BLI_dynstr_append(ds, "UNSUPPORTED");
+ }
+
+ char *support_key = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+ BLI_str_replace_char(support_key, '\n', ' ');
+ BLI_str_replace_char(support_key, '\r', ' ');
+ return support_key;
+}
+
+static char *gpu_platform_create_gpu_name(const char *vendor,
+ const char *renderer,
+ const char *version)
+{
+ DynStr *ds = BLI_dynstr_new();
+ BLI_dynstr_append(ds, vendor);
+ BLI_dynstr_append(ds, " ");
+ BLI_dynstr_append(ds, renderer);
+ BLI_dynstr_append(ds, " ");
+ BLI_dynstr_append(ds, version);
+
+ char *gpu_name = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+ BLI_str_replace_char(gpu_name, '\n', ' ');
+ BLI_str_replace_char(gpu_name, '\r', ' ');
+ return gpu_name;
+}
+
+void gpu_platform_init(void)
+{
+ if (GPG.initialized) {
+ return;
+ }
+
+#ifdef _WIN32
+ GPG.os = GPU_OS_WIN;
+#elif defined(__APPLE__)
+ GPG.os = GPU_OS_MAC;
+#else
+ GPG.os = GPU_OS_UNIX;
+#endif
+
+ const char *vendor = (const char *)glGetString(GL_VENDOR);
+ const char *renderer = (const char *)glGetString(GL_RENDERER);
+ const char *version = (const char *)glGetString(GL_VERSION);
+
+ if (strstr(vendor, "ATI") || strstr(vendor, "AMD")) {
+ GPG.device = GPU_DEVICE_ATI;
+ GPG.driver = GPU_DRIVER_OFFICIAL;
+ }
+ else if (strstr(vendor, "NVIDIA")) {
+ GPG.device = GPU_DEVICE_NVIDIA;
+ GPG.driver = GPU_DRIVER_OFFICIAL;
+ }
+ else if (strstr(vendor, "Intel") ||
+ /* src/mesa/drivers/dri/intel/intel_context.c */
+ strstr(renderer, "Mesa DRI Intel") || strstr(renderer, "Mesa DRI Mobile Intel")) {
+ GPG.device = GPU_DEVICE_INTEL;
+ GPG.driver = GPU_DRIVER_OFFICIAL;
+
+ if (strstr(renderer, "UHD Graphics") ||
+ /* Not UHD but affected by the same bugs. */
+ strstr(renderer, "HD Graphics 530") || strstr(renderer, "Kaby Lake GT2")) {
+ GPG.device |= GPU_DEVICE_INTEL_UHD;
+ }
+ }
+ else if ((strstr(renderer, "Mesa DRI R")) ||
+ (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) ||
+ (strstr(renderer, "AMD") && strstr(vendor, "X.Org")) ||
+ (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) ||
+ (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD "))) {
+ GPG.device = GPU_DEVICE_ATI;
+ GPG.driver = GPU_DRIVER_OPENSOURCE;
+ }
+ else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
+ GPG.device = GPU_DEVICE_NVIDIA;
+ GPG.driver = GPU_DRIVER_OPENSOURCE;
+ }
+ else if (strstr(vendor, "Mesa")) {
+ GPG.device = GPU_DEVICE_SOFTWARE;
+ GPG.driver = GPU_DRIVER_SOFTWARE;
+ }
+ else if (strstr(vendor, "Microsoft")) {
+ GPG.device = GPU_DEVICE_SOFTWARE;
+ GPG.driver = GPU_DRIVER_SOFTWARE;
+ }
+ else if (strstr(renderer, "Apple Software Renderer")) {
+ GPG.device = GPU_DEVICE_SOFTWARE;
+ GPG.driver = GPU_DRIVER_SOFTWARE;
+ }
+ else if (strstr(renderer, "llvmpipe") || strstr(renderer, "softpipe")) {
+ GPG.device = GPU_DEVICE_SOFTWARE;
+ GPG.driver = GPU_DRIVER_SOFTWARE;
+ }
+ else {
+ printf("Warning: Could not find a matching GPU name. Things may not behave as expected.\n");
+ printf("Detected OpenGL configuration:\n");
+ printf("Vendor: %s\n", vendor);
+ printf("Renderer: %s\n", renderer);
+ GPG.device = GPU_DEVICE_ANY;
+ GPG.driver = GPU_DRIVER_ANY;
+ }
+
+ /* Detect support level */
+ if (!GLEW_VERSION_3_3) {
+ GPG.support_level = GPU_SUPPORT_LEVEL_UNSUPPORTED;
+ }
+ else {
+ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY)) {
+ /* Old Intel drivers with known bugs that cause material properties to crash.
+ * Version Build 10.18.14.5067 is the latest available and appears to be working
+ * ok with our workarounds, so excluded from this list. */
+ if (strstr(version, "Build 7.14") || strstr(version, "Build 7.15") ||
+ strstr(version, "Build 8.15") || strstr(version, "Build 9.17") ||
+ strstr(version, "Build 9.18") || strstr(version, "Build 10.18.10.3") ||
+ strstr(version, "Build 10.18.10.4") || strstr(version, "Build 10.18.10.5") ||
+ strstr(version, "Build 10.18.14.4")) {
+ GPG.support_level = GPU_SUPPORT_LEVEL_LIMITED;
+ }
+ }
+ }
+ GPG.support_key = gpu_platform_create_key(GPG.support_level, vendor, renderer, version);
+ GPG.gpu_name = gpu_platform_create_gpu_name(vendor, renderer, version);
+ GPG.initialized = true;
+}
+
+void gpu_platform_exit(void)
+{
+ MEM_SAFE_FREE(GPG.support_key);
+ MEM_SAFE_FREE(GPG.gpu_name);
+}
diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h
index b9af8f1b38c..7846bff87f4 100644
--- a/source/blender/gpu/intern/gpu_private.h
+++ b/source/blender/gpu/intern/gpu_private.h
@@ -22,6 +22,10 @@
#define __GPU_PRIVATE_H__
/* call this before running any of the functions below */
+void gpu_platform_init(void);
+void gpu_platform_exit(void);
+
+/* call this before running any of the functions below */
void gpu_extensions_init(void);
void gpu_extensions_exit(void);
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 015df078228..5df73d1a0c6 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -36,6 +36,7 @@
#include "DNA_space_types.h"
#include "GPU_extensions.h"
+#include "GPU_platform.h"
#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index a54d90f37f5..497fc13a2c8 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -38,6 +38,7 @@
#include "GPU_extensions.h"
#include "GPU_glew.h"
#include "GPU_framebuffer.h"
+#include "GPU_platform.h"
#include "GPU_texture.h"
#include "gpu_context_private.h"
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl
index abe6081489d..e089aec1d92 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl
@@ -92,14 +92,14 @@ void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol)
void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol)
{
fac = clamp(fac, 0.0, 1.0);
- outcol.rgb = min(col1.rgb, col2.rgb * fac);
+ outcol.rgb = mix(col1.rgb, min(col1.rgb, col2.rgb), fac);
outcol.a = col1.a;
}
void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol)
{
fac = clamp(fac, 0.0, 1.0);
- outcol.rgb = max(col1.rgb, col2.rgb * fac);
+ outcol.rgb = mix(col1.rgb, max(col1.rgb, col2.rgb), fac);
outcol.a = col1.a;
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
index 140213a9ed9..7af409dd410 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
@@ -113,14 +113,14 @@ void node_bsdf_principled(vec4 base_color,
result = CLOSURE_DEFAULT;
result.radiance = out_spec + out_refr;
result.radiance += out_diff * out_sheen; /* Coarse approx. */
+ result.radiance += emission.rgb;
+ result.radiance *= alpha;
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
mixed_ss_base_color *= alpha * (1.0 - transmission);
closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result);
- result.radiance += emission.rgb;
- result.radiance *= alpha;
result.transmittance = vec3(1.0 - alpha);
}
@@ -169,9 +169,11 @@ void node_bsdf_principled_dielectric(vec4 base_color,
result = CLOSURE_DEFAULT;
result.radiance = out_spec + out_diff * (diffuse + out_sheen);
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
result.radiance += emission.rgb;
result.radiance *= alpha;
+
+ closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+
result.transmittance = vec3(1.0 - alpha);
}
@@ -213,9 +215,11 @@ void node_bsdf_principled_metallic(vec4 base_color,
result = CLOSURE_DEFAULT;
result.radiance = out_spec;
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
result.radiance += emission.rgb;
result.radiance *= alpha;
+
+ closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+
result.transmittance = vec3(1.0 - alpha);
}
@@ -267,9 +271,11 @@ void node_bsdf_principled_clearcoat(vec4 base_color,
result = CLOSURE_DEFAULT;
result.radiance = out_spec;
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
result.radiance += emission.rgb;
result.radiance *= alpha;
+
+ closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+
result.transmittance = vec3(1.0 - alpha);
}
@@ -333,14 +339,15 @@ void node_bsdf_principled_subsurface(vec4 base_color,
result = CLOSURE_DEFAULT;
result.radiance = out_spec;
+ result.radiance += out_diff * out_sheen;
+ result.radiance += emission.rgb;
+ result.radiance *= alpha;
+
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
mixed_ss_base_color *= alpha * (1.0 - transmission);
closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result);
- result.radiance += out_diff * out_sheen;
- result.radiance += emission.rgb;
- result.radiance *= alpha;
result.transmittance = vec3(1.0 - alpha);
}
@@ -402,9 +409,9 @@ void node_bsdf_principled_glass(vec4 base_color,
result = CLOSURE_DEFAULT;
result.radiance = mix(out_refr, out_spec, fresnel);
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
result.radiance += emission.rgb;
result.radiance *= alpha;
+ closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
result.transmittance = vec3(1.0 - alpha);
}
#else
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 9e9c47194e1..173c8135f96 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -700,6 +700,8 @@ void imb_freemipmapImBuf(struct ImBuf *ibuf);
bool imb_addtilesImBuf(struct ImBuf *ibuf);
void imb_freetilesImBuf(struct ImBuf *ibuf);
+void imb_freerectImbuf_all(struct ImBuf *ibuf);
+
/* threaded processors */
void IMB_processor_apply_threaded(
int buffer_lines,
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 75db3fd3c73..381de9de610 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -197,6 +197,17 @@ void IMB_freezbuffloatImBuf(ImBuf *ibuf)
ibuf->mall &= ~IB_zbuffloat;
}
+/** Free all pixel data (assosiated with image size). */
+void imb_freerectImbuf_all(ImBuf *ibuf)
+{
+ imb_freerectImBuf(ibuf);
+ imb_freerectfloatImBuf(ibuf);
+ imb_freetilesImBuf(ibuf);
+ IMB_freezbufImBuf(ibuf);
+ IMB_freezbuffloatImBuf(ibuf);
+ freeencodedbufferImBuf(ibuf);
+}
+
void IMB_freeImBuf(ImBuf *ibuf)
{
if (ibuf) {
@@ -212,12 +223,7 @@ void IMB_freeImBuf(ImBuf *ibuf)
BLI_spin_unlock(&refcounter_spin);
if (needs_free) {
- imb_freerectImBuf(ibuf);
- imb_freerectfloatImBuf(ibuf);
- imb_freetilesImBuf(ibuf);
- IMB_freezbufImBuf(ibuf);
- IMB_freezbuffloatImBuf(ibuf);
- freeencodedbufferImBuf(ibuf);
+ imb_freerectImbuf_all(ibuf);
IMB_metadata_free(ibuf->metadata);
colormanage_cache_free(ibuf);
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index 49e9c4c54d2..ec03a0a07b8 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -401,11 +401,6 @@ typedef struct ScanlineGlobalData {
int total_scanlines;
} ScanlineGlobalData;
-typedef struct ScanlineTask {
- int start_scanline;
- int num_scanlines;
-} ScanlineTask;
-
static void processor_apply_scanline_func(TaskPool *__restrict pool,
void *taskdata,
int UNUSED(threadid))
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index 3163a960892..7150e41841b 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -262,7 +262,7 @@ void IMB_rect_crop(ImBuf *ibuf, const rcti *crop)
BLI_rcti_size_x(crop) + 1,
BLI_rcti_size_y(crop) + 1,
};
- BLI_assert(size_dst[0] > 0 && size_dst[0] > 0);
+ BLI_assert(size_dst[0] > 0 && size_dst[1] > 0);
BLI_assert(crop->xmin >= 0 && crop->ymin >= 0);
BLI_assert(crop->xmax < ibuf->x && crop->ymax < ibuf->y);
@@ -304,7 +304,7 @@ static void rect_realloc_16bytes(void **buf_p, const uint size[2])
*/
void IMB_rect_size_set(ImBuf *ibuf, const uint size[2])
{
- BLI_assert(size[0] > 0 && size[0] > 0);
+ BLI_assert(size[0] > 0 && size[1] > 0);
if ((size[0] == ibuf->x) && (size[1] == ibuf->y)) {
return;
}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index a6212e09567..47bf49294b6 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -697,6 +697,13 @@ enum {
FILTER_ID_LP = (1u << 31),
};
+#define FILTER_ID_ALL \
+ (FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU | FILTER_ID_GD | \
+ FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA | FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | \
+ FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | \
+ FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO | FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | \
+ FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | FILTER_ID_LP)
+
/* IMPORTANT: this enum matches the order currently use in set_listbasepointers,
* keep them in sync! */
enum {
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index aec28c0fe75..fc8763f1519 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -502,7 +502,8 @@ typedef enum eBrushUVSculptTool {
SCULPT_TOOL_SCRAPE, \
SCULPT_TOOL_FLATTEN)
-#define SCULPT_TOOL_HAS_NORMAL_WEIGHT(t) ELEM(t, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK)
+#define SCULPT_TOOL_HAS_NORMAL_WEIGHT(t) \
+ ELEM(t, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_ELASTIC_DEFORM)
#define SCULPT_TOOL_HAS_RAKE(t) ELEM(t, SCULPT_TOOL_SNAKE_HOOK)
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 2dffdf82688..1435d0a64b4 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -401,6 +401,8 @@ typedef enum eGPDlayer_Flag {
GP_LAYER_USE_MASK = (1 << 13),
/* Flag used to display in Paint mode only layers with keyframe */
GP_LAYER_SOLO_MODE = (1 << 4),
+ /* Ruler Layer */
+ GP_LAYER_IS_RULER = (1 << 14),
} eGPDlayer_Flag;
/* bGPDlayer->onion_flag */
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index 3af1da46f80..4de98e0b684 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -118,13 +118,13 @@ enum {
BASE_HIDDEN = (1 << 8), /* Object is hidden for editing. */
/* Runtime evaluated flags. */
- BASE_VISIBLE = (1 << 1), /* Object is enabled and visible. */
- BASE_SELECTABLE = (1 << 2), /* Object can be selected. */
- BASE_FROM_DUPLI = (1 << 3), /* Object comes from duplicator. */
- /* BASE_DEPRECATED = (1 << 4), */
- BASE_FROM_SET = (1 << 5), /* Object comes from set. */
- BASE_ENABLED_VIEWPORT = (1 << 6), /* Object is enabled in viewport. */
- BASE_ENABLED_RENDER = (1 << 7), /* Object is enabled in final render */
+ BASE_VISIBLE_DEPSGRAPH = (1 << 1), /* Object is enabled and visible for the depsgraph. */
+ BASE_SELECTABLE = (1 << 2), /* Object can be selected. */
+ BASE_FROM_DUPLI = (1 << 3), /* Object comes from duplicator. */
+ BASE_VISIBLE_VIEWLAYER = (1 << 4), /* Object is enabled and visible for the viewlayer. */
+ BASE_FROM_SET = (1 << 5), /* Object comes from set. */
+ BASE_ENABLED_VIEWPORT = (1 << 6), /* Object is enabled in viewport. */
+ BASE_ENABLED_RENDER = (1 << 7), /* Object is enabled in final render */
/* BASE_DEPRECATED = (1 << 9), */
BASE_HOLDOUT = (1 << 10), /* Object masked out from render */
BASE_INDIRECT_ONLY = (1 << 11), /* Object only contributes indirectly to render */
@@ -142,10 +142,13 @@ enum {
LAYER_COLLECTION_HIDE = (1 << 7),
};
-/* Layer Collection->runtime_flag */
+/* Layer Collection->runtime_flag
+ Keep it synced with base->flag based on g_base_collection_flags. */
enum {
LAYER_COLLECTION_HAS_OBJECTS = (1 << 0),
- LAYER_COLLECTION_VISIBLE = (1 << 1),
+ LAYER_COLLECTION_VISIBLE_DEPSGRAPH = (1 << 1),
+ LAYER_COLLECTION_RESTRICT_VIEWPORT = (1 << 2),
+ LAYER_COLLECTION_VISIBLE_VIEW_LAYER = (1 << 4),
};
/* ViewLayer->flag */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index ca572f1ddf1..8763f62b385 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1976,14 +1976,7 @@ extern const char *RE_engine_id_CYCLES;
#define MINAFRAME -1048574
#define MINAFRAMEF -1048574.0f
-#define BASE_VISIBLE(v3d, base) \
- (((v3d == NULL) || ((v3d)->localvd == NULL) || \
- ((v3d)->local_view_uuid & (base)->local_view_bits)) && \
- ((v3d == NULL) || (((v3d)->flag & V3D_LOCAL_COLLECTIONS) == 0) || \
- ((v3d)->local_collections_uuid & (base)->local_collections_bits)) && \
- ((v3d == NULL) || \
- (((1 << (base)->object->type) & (v3d)->object_type_exclude_viewport) == 0)) && \
- (((base)->flag & BASE_VISIBLE) != 0))
+#define BASE_VISIBLE(v3d, base) BKE_base_is_visible(v3d, base)
#define BASE_SELECTABLE(v3d, base) \
(BASE_VISIBLE(v3d, base) && \
((v3d == NULL) || (((1 << (base)->object->type) & (v3d)->object_type_exclude_select) == 0)) && \
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 126b4638ca1..b9f43c0e579 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -394,6 +394,8 @@ typedef struct ThemeSpace {
/** NLA - warning color for duplicate instances of tweaking strip. */
unsigned char nla_tweakdupli[4];
+ /** NLA "Track" */
+ unsigned char nla_track[4];
/** NLA "Transition" strips. */
unsigned char nla_transition[4], nla_transition_sel[4];
/** NLA "Meta" strips. */
@@ -414,7 +416,6 @@ typedef struct ThemeSpace {
unsigned char metadatabg[4];
unsigned char metadatatext[4];
- char _pad2[4];
} ThemeSpace;
/* set of colors for use as a custom color set for Objects/Bones wire drawing */
@@ -606,7 +607,8 @@ typedef struct UserDef {
/** #eUserPref_PrefFlag preferences for the preferences. */
char pref_flag;
char savetime;
- char _pad4[4];
+ char mouse_emulate_3_button_modifier;
+ char _pad4[3];
/** FILE_MAXDIR length. */
char tempdir[768];
char fontdir[768];
@@ -726,11 +728,13 @@ typedef struct UserDef {
short curssize;
/** #eColorPicker_Types. */
short color_picker_type;
+ /** Curve smoothing type for newly added F-Curves. */
+ char auto_smoothing_new;
/** Interpolation mode for newly added F-Curves. */
char ipo_new;
/** Handle types for newly added keyframes. */
char keyhandles_new;
- char _pad11[3];
+ char _pad11[2];
/** #eZoomFrame_Mode. */
char view_frame_type;
@@ -1240,6 +1244,11 @@ typedef enum eUserpref_TempSpaceDisplayType {
USER_TEMP_SPACE_DISPLAY_WINDOW,
} eUserpref_TempSpaceDisplayType;
+typedef enum eUserpref_EmulateMMBMod {
+ USER_EMU_MMB_MOD_ALT = 0,
+ USER_EMU_MMB_MOD_OSKEY = 1,
+} eUserpref_EmulateMMBMod;
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index e72a55b5a9e..458f031ceae 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -90,6 +90,7 @@ extern const EnumPropertyItem rna_enum_color_sets_items[];
extern const EnumPropertyItem rna_enum_beztriple_keyframe_type_items[];
extern const EnumPropertyItem rna_enum_beztriple_interpolation_mode_items[];
extern const EnumPropertyItem rna_enum_beztriple_interpolation_easing_items[];
+extern const EnumPropertyItem rna_enum_fcurve_auto_smoothing_items[];
extern const EnumPropertyItem rna_enum_keyframe_handle_type_items[];
extern const EnumPropertyItem rna_enum_driver_target_rotation_mode_items[];
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 71a3be24810..aeb6d528cdb 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -393,7 +393,7 @@ bool RNA_struct_idprops_check(StructRNA *srna)
return (srna && srna->idproperties);
}
-static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
+IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
{
IDProperty *group = RNA_struct_idprops(ptr, 0);
diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c
index b061c72157e..18fbe7886e9 100644
--- a/source/blender/makesrna/intern/rna_access_compare_override.c
+++ b/source/blender/makesrna/intern/rna_access_compare_override.c
@@ -400,9 +400,39 @@ static bool rna_property_override_operation_store(Main *bmain,
return changed;
}
- BLI_assert(prop_local->override_store == prop_reference->override_store &&
- (!ptr_storage || prop_local->override_store == prop_storage->override_store) &&
- prop_local->override_store != NULL);
+ RNAPropOverrideStore override_store = NULL;
+ /* Special case for IDProps, we use default callback then. */
+ if (prop_local->magic != RNA_MAGIC) {
+ override_store = rna_property_override_store_default;
+ if (prop_reference->magic == RNA_MAGIC && prop_reference->override_store != override_store) {
+ override_store = NULL;
+ }
+ }
+ else if (prop_reference->magic != RNA_MAGIC) {
+ override_store = rna_property_override_store_default;
+ if (prop_local->override_store != override_store) {
+ override_store = NULL;
+ }
+ }
+ else if (prop_local->override_store == prop_reference->override_store) {
+ override_store = prop_local->override_store;
+ }
+
+ if (ptr_storage != NULL && prop_storage->magic == RNA_MAGIC &&
+ prop_storage->override_store != override_store) {
+ override_store = NULL;
+ }
+
+ if (override_store == NULL) {
+#ifndef NDEBUG
+ printf("'%s' gives unmatching or NULL RNA store callbacks, should not happen (%d vs. %d).\n",
+ op->rna_path,
+ prop_local->magic == RNA_MAGIC,
+ prop_reference->magic == RNA_MAGIC);
+#endif
+ BLI_assert(0);
+ return changed;
+ }
for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
/* Only needed for diff operations. */
@@ -413,17 +443,17 @@ static bool rna_property_override_operation_store(Main *bmain,
continue;
}
- if (prop_local->override_store(bmain,
- ptr_local,
- ptr_reference,
- ptr_storage,
- prop_local,
- prop_reference,
- prop_storage,
- len_local,
- len_reference,
- len_storage,
- opop)) {
+ if (override_store(bmain,
+ ptr_local,
+ ptr_reference,
+ ptr_storage,
+ prop_local,
+ prop_reference,
+ prop_storage,
+ len_local,
+ len_reference,
+ len_storage,
+ opop)) {
changed = true;
}
}
@@ -595,6 +625,21 @@ bool RNA_struct_override_matches(Main *bmain,
prop_local = rna_ensure_property_realdata(&prop_local, ptr_local);
prop_reference = rna_ensure_property_realdata(&prop_reference, ptr_reference);
+ /* IDProps (custom properties) are even more of a PITA here, we cannot use
+ * `rna_ensure_property_realdata()` to deal with them, we have to use the path generated from
+ * `prop_local` (which is valid) to access to the actual reference counterpart... */
+ if (prop_local != NULL && prop_local->magic != RNA_MAGIC && prop_local == prop_reference) {
+ /* We could also use (lower in this code, after rna_path has been computed):
+ * RNA_path_resolve_property(ptr_reference, rna_path, &some_rna_ptr, &prop_reference);
+ * But that would be much more costly, and would also fail when ptr_reference
+ * is not an ID pointer itself, so we'd need to rebuild it from its owner_id, then check that
+ * generated some_rna_ptr and ptr_reference do point to the same data, etc.
+ * For now, let's try that simple access, it won't cover all cases but should handle fine
+ * most basic custom properties situations. */
+ prop_reference = (PropertyRNA *)rna_idproperty_find(ptr_reference,
+ ((IDProperty *)prop_local)->name);
+ }
+
if (ELEM(NULL, prop_local, prop_reference)) {
continue;
}
diff --git a/source/blender/makesrna/intern/rna_access_internal.h b/source/blender/makesrna/intern/rna_access_internal.h
index 28ec504e376..c7995746d08 100644
--- a/source/blender/makesrna/intern/rna_access_internal.h
+++ b/source/blender/makesrna/intern/rna_access_internal.h
@@ -30,5 +30,6 @@ struct IDProperty;
PropertyRNA *rna_ensure_property(PropertyRNA *prop);
void rna_idproperty_touch(struct IDProperty *idprop);
+struct IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name);
#endif /* __ACCESS_RNA_INTERNAL_H__ */
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index d7bb941b266..57a3d889437 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1452,81 +1452,77 @@ static void rna_def_brush(BlenderRNA *brna)
PropertyRNA *prop;
static const EnumPropertyItem prop_blend_items[] = {
- {IMB_BLEND_MIX, "MIX", 0, "Mix", "Use mix blending mode while painting"},
+ {IMB_BLEND_MIX, "MIX", 0, "Mix", "Use Mix blending mode while painting"},
{0, "", ICON_NONE, NULL, NULL},
- {IMB_BLEND_DARKEN, "DARKEN", 0, "Darken", "Use darken blending mode while painting"},
- {IMB_BLEND_MUL, "MUL", 0, "Multiply", "Use multiply blending mode while painting"},
+ {IMB_BLEND_DARKEN, "DARKEN", 0, "Darken", "Use Darken blending mode while painting"},
+ {IMB_BLEND_MUL, "MUL", 0, "Multiply", "Use Multiply blending mode while painting"},
{IMB_BLEND_COLORBURN,
"COLORBURN",
0,
- "Color burn",
- "Use color burn blending mode while painting"},
+ "Color Burn",
+ "Use Color Burn blending mode while painting"},
{IMB_BLEND_LINEARBURN,
"LINEARBURN",
0,
- "Linear burn",
- "Use linear burn blending mode while painting"},
+ "Linear Burn",
+ "Use Linear Burn blending mode while painting"},
{0, "", ICON_NONE, NULL, NULL},
- {IMB_BLEND_LIGHTEN, "LIGHTEN", 0, "Lighten", "Use lighten blending mode while painting"},
- {IMB_BLEND_SCREEN, "SCREEN", 0, "Screen", "Use screen blending mode while painting"},
+ {IMB_BLEND_LIGHTEN, "LIGHTEN", 0, "Lighten", "Use Lighten blending mode while painting"},
+ {IMB_BLEND_SCREEN, "SCREEN", 0, "Screen", "Use Screen blending mode while painting"},
{IMB_BLEND_COLORDODGE,
"COLORDODGE",
0,
- "Color dodge",
- "Use color dodge blending mode while painting"},
- {IMB_BLEND_ADD, "ADD", 0, "Add", "Use add blending mode while painting"},
+ "Color Dodge",
+ "Use Color Dodge blending mode while painting"},
+ {IMB_BLEND_ADD, "ADD", 0, "Add", "Use Add blending mode while painting"},
{0, "", ICON_NONE, NULL, NULL},
- {IMB_BLEND_OVERLAY, "OVERLAY", 0, "Overlay", "Use overlay blending mode while painting"},
+ {IMB_BLEND_OVERLAY, "OVERLAY", 0, "Overlay", "Use Overlay blending mode while painting"},
{IMB_BLEND_SOFTLIGHT,
"SOFTLIGHT",
0,
- "Soft light",
- "Use softlight blending mode while painting"},
+ "Soft Light",
+ "Use Soft Light blending mode while painting"},
{IMB_BLEND_HARDLIGHT,
"HARDLIGHT",
0,
- "Hard light",
- "Use hard light blending mode while painting"},
+ "Hard Light",
+ "Use Hard Light blending mode while painting"},
{IMB_BLEND_VIVIDLIGHT,
"VIVIDLIGHT",
0,
- "Vivid light",
- "Use vividlight blending mode while painting"},
+ "Vivid Light",
+ "Use Vivid Light blending mode while painting"},
{IMB_BLEND_LINEARLIGHT,
"LINEARLIGHT",
0,
- "Linear light",
- "Use linearlight blending mode while painting"},
+ "Linear Light",
+ "Use Linear Light blending mode while painting"},
{IMB_BLEND_PINLIGHT,
"PINLIGHT",
0,
- "Pin light",
- "Use pinlight blending mode while painting"},
+ "Pin Light",
+ "Use Pin Light blending mode while painting"},
{0, "", ICON_NONE, NULL, NULL},
{IMB_BLEND_DIFFERENCE,
"DIFFERENCE",
0,
"Difference",
- "Use difference blending mode while painting"},
+ "Use Difference blending mode while painting"},
{IMB_BLEND_EXCLUSION,
"EXCLUSION",
0,
"Exclusion",
- "Use exclusion blending mode while painting"},
- {IMB_BLEND_SUB, "SUB", 0, "Subtract", "Use subtract blending mode while painting"},
+ "Use Exclusion blending mode while painting"},
+ {IMB_BLEND_SUB, "SUB", 0, "Subtract", "Use Subtract blending mode while painting"},
{0, "", ICON_NONE, NULL, NULL},
- {IMB_BLEND_HUE, "HUE", 0, "Hue", "Use hue blending mode while painting"},
+ {IMB_BLEND_HUE, "HUE", 0, "Hue", "Use Hue blending mode while painting"},
{IMB_BLEND_SATURATION,
"SATURATION",
0,
"Saturation",
- "Use saturation blending mode while painting"},
- {IMB_BLEND_COLOR, "COLOR", 0, "Color", "Use color blending mode while painting"},
- {IMB_BLEND_LUMINOSITY,
- "LUMINOSITY",
- 0,
- "Luminosity",
- "Use luminosity blending mode while painting"},
+ "Use Saturation blending mode while painting"},
+ {IMB_BLEND_COLOR, "COLOR", 0, "Color", "Use Color blending mode while painting"},
+ {IMB_BLEND_LUMINOSITY, "LUMINOSITY", 0, "Value", "Use Value blending mode while painting"},
{0, "", ICON_NONE, NULL, NULL},
{IMB_BLEND_ERASE_ALPHA, "ERASE_ALPHA", 0, "Erase Alpha", "Erase alpha while painting"},
{IMB_BLEND_ADD_ALPHA, "ADD_ALPHA", 0, "Add Alpha", "Add alpha while painting"},
@@ -1610,15 +1606,11 @@ static void rna_def_brush(BlenderRNA *brna)
};
static const EnumPropertyItem brush_elastic_deform_type_items[] = {
- {BRUSH_ELASTIC_DEFORM_GRAB, "ELASTIC_DEFORM_GRAB", 0, "Grab", ""},
- {BRUSH_ELASTIC_DEFORM_GRAB_BISCALE, "ELASTIC_DEFORM_GRAB_BISCALE", 0, "Bi-scale Grab", ""},
- {BRUSH_ELASTIC_DEFORM_GRAB_TRISCALE,
- "ELASTIC_DEFORM_GRAB_TRISCALE",
- 0,
- "Tri-scale Grab",
- ""},
- {BRUSH_ELASTIC_DEFORM_SCALE, "ELASTIC_DEFORM_SCALE", 0, "Scale", ""},
- {BRUSH_ELASTIC_DEFORM_TWIST, "ELASTIC_DEFORM_TWIST", 0, "Twist", ""},
+ {BRUSH_ELASTIC_DEFORM_GRAB, "GRAB", 0, "Grab", ""},
+ {BRUSH_ELASTIC_DEFORM_GRAB_BISCALE, "GRAB_BISCALE", 0, "Bi-scale Grab", ""},
+ {BRUSH_ELASTIC_DEFORM_GRAB_TRISCALE, "GRAB_TRISCALE", 0, "Tri-scale Grab", ""},
+ {BRUSH_ELASTIC_DEFORM_SCALE, "SCALE", 0, "Scale", ""},
+ {BRUSH_ELASTIC_DEFORM_TWIST, "TWIST", 0, "Twist", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -1893,8 +1885,8 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "normal_radius_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "normal_radius_factor");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 3);
+ RNA_def_property_range(prop, 0.0f, 2.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 2.0f, 0.001, 3);
RNA_def_property_ui_text(prop,
"Normal Radius",
"Ratio between the brush radius and the radius that is going to be "
@@ -1967,7 +1959,7 @@ static void rna_def_brush(BlenderRNA *brna)
/* flag */
/* This is an enum but its unlikely we add other shapes, so expose as a boolean. */
prop = RNA_def_property(srna, "use_projected", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "falloff_shape", BRUSH_AIRBRUSH);
+ RNA_def_property_boolean_sdna(prop, NULL, "falloff_shape", PAINT_FALLOFF_SHAPE_TUBE);
RNA_def_property_ui_text(
prop, "2D Falloff", "Apply brush influence in 2D circle instead of a sphere");
RNA_def_property_update(prop, 0, "rna_Brush_update");
@@ -2419,7 +2411,7 @@ static void rna_def_operator_stroke_element(BlenderRNA *brna)
prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE);
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
- RNA_def_property_ui_text(prop, "Brush Size", "Brush Size in screen space");
+ RNA_def_property_ui_text(prop, "Brush Size", "Brush size in screen space");
prop = RNA_def_property(srna, "pen_flip", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_IDPROPERTY);
diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c
index ebd9bd8e925..2072b07ecb3 100644
--- a/source/blender/makesrna/intern/rna_depsgraph.c
+++ b/source/blender/makesrna/intern/rna_depsgraph.c
@@ -261,8 +261,13 @@ static void rna_Depsgraph_debug_stats(Depsgraph *depsgraph, char *result)
outer);
}
-static void rna_Depsgraph_update(Depsgraph *depsgraph, Main *bmain)
+static void rna_Depsgraph_update(Depsgraph *depsgraph, Main *bmain, ReportList *reports)
{
+ if (DEG_is_evaluating(depsgraph)) {
+ BKE_report(reports, RPT_ERROR, "Dependency graph update requested during evaluation");
+ return;
+ }
+
# ifdef WITH_PYTHON
/* Allow drivers to be evaluated */
BPy_BEGIN_ALLOW_THREADS;
@@ -654,7 +659,7 @@ static void rna_def_depsgraph(BlenderRNA *brna)
func,
"Re-evaluate any modified data-blocks, for example for animation or modifiers. "
"This invalidates all references to evaluated data-blocks from this dependency graph.");
- RNA_def_function_flag(func, FUNC_USE_MAIN);
+ RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS);
/* Queries for original datablockls (the ones depsgraph is built for). */
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 254f3bc3710..424bb4a492f 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -76,6 +76,22 @@ const EnumPropertyItem rna_enum_fmodifier_type_items[] = {
{0, NULL, 0, NULL, NULL},
};
+const EnumPropertyItem rna_enum_fcurve_auto_smoothing_items[] = {
+ {FCURVE_SMOOTH_NONE,
+ "NONE",
+ 0,
+ "None",
+ "Automatic handles only take immediately adjacent keys into account"},
+ {FCURVE_SMOOTH_CONT_ACCEL,
+ "CONT_ACCEL",
+ 0,
+ "Continuous Acceleration",
+ "Automatic handles are adjusted to avoid jumps in acceleration, resulting "
+ "in smoother curves. However, key changes may affect interpolation over a "
+ "larger stretch of the curve"},
+ {0, NULL, 0, NULL, NULL},
+};
+
const EnumPropertyItem rna_enum_beztriple_keyframe_type_items[] = {
{BEZT_KEYTYPE_KEYFRAME,
"KEYFRAME",
@@ -2258,19 +2274,6 @@ static void rna_def_fcurve(BlenderRNA *brna)
"Use custom hand-picked color for F-Curve"},
{0, NULL, 0, NULL, NULL},
};
- static EnumPropertyItem prop_mode_smoothing_items[] = {
- {FCURVE_SMOOTH_NONE,
- "NONE",
- 0,
- "None",
- "Auto handles only take adjacent keys into account (legacy mode)"},
- {FCURVE_SMOOTH_CONT_ACCEL,
- "CONT_ACCEL",
- 0,
- "Continuous Acceleration",
- "Auto handles are placed to avoid jumps in acceleration"},
- {0, NULL, 0, NULL, NULL},
- };
srna = RNA_def_struct(brna, "FCurve", NULL);
RNA_def_struct_ui_text(srna, "F-Curve", "F-Curve defining values of a period of time");
@@ -2350,7 +2353,7 @@ static void rna_def_fcurve(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
prop = RNA_def_property(srna, "auto_smoothing", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, prop_mode_smoothing_items);
+ RNA_def_property_enum_items(prop, rna_enum_fcurve_auto_smoothing_items);
RNA_def_property_ui_text(
prop, "Auto Handle Smoothing", "Algorithm used to compute automatic handles");
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FCurve_update_data");
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 3ad18fcc7a3..2601600c6ee 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -1457,6 +1457,12 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
prop, "Solo Mode", "In Paint mode display only layers with keyframe in current frame");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+ /* Layer is used as Ruler. */
+ prop = RNA_def_property(srna, "is_ruler", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_IS_RULER);
+ RNA_def_property_ui_text(prop, "Ruler", "This is a special ruler layer");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
/* exposed as layers.active */
# if 0
prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
index bab7375f01b..40c6229f9b1 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -123,18 +123,13 @@ static IDProperty *rna_ViewLayer_idprops(PointerRNA *ptr, bool create)
static bool rna_LayerCollection_visible_get(LayerCollection *layer_collection, bContext *C)
{
View3D *v3d = CTX_wm_view3d(C);
- const bool runtime_visible = (layer_collection->runtime_flag & LAYER_COLLECTION_VISIBLE) != 0;
- if (v3d == NULL) {
- return runtime_visible;
- }
-
- if ((v3d->flag & V3D_LOCAL_COLLECTIONS) == 0) {
- return runtime_visible;
+ if ((v3d == NULL) || ((v3d->flag & V3D_LOCAL_COLLECTIONS) == 0)) {
+ return (layer_collection->runtime_flag & LAYER_COLLECTION_VISIBLE_VIEW_LAYER) != 0;
}
if (v3d->local_collections_uuid & layer_collection->local_collections_bits) {
- return true;
+ return (layer_collection->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) == 0;
}
return false;
@@ -192,15 +187,24 @@ static void rna_LayerObjects_selected_begin(CollectionPropertyIterator *iter, Po
iter, &view_layer->object_bases, rna_ViewLayer_objects_selected_skip);
}
-static void rna_ViewLayer_update_tagged(ID *id_ptr, ViewLayer *view_layer, Main *bmain)
+static void rna_ViewLayer_update_tagged(ID *id_ptr,
+ ViewLayer *view_layer,
+ Main *bmain,
+ ReportList *reports)
{
+ Scene *scene = (Scene *)id_ptr;
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true);
+
+ if (DEG_is_evaluating(depsgraph)) {
+ BKE_report(reports, RPT_ERROR, "Dependency graph update requested during evaluation");
+ return;
+ }
+
# ifdef WITH_PYTHON
/* Allow drivers to be evaluated */
BPy_BEGIN_ALLOW_THREADS;
# endif
- Scene *scene = (Scene *)id_ptr;
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true);
/* NOTE: This is similar to CTX_data_depsgraph_pointer(). Ideally such access would be
* de-duplicated across all possible cases, but for now this is safest and easiest way to go.
*
@@ -415,12 +419,12 @@ static void rna_def_layer_collection(BlenderRNA *brna)
/* Run-time flags. */
prop = RNA_def_property(srna, "is_visible", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "runtime_flag", LAYER_COLLECTION_VISIBLE);
+ RNA_def_property_boolean_sdna(prop, NULL, "runtime_flag", LAYER_COLLECTION_VISIBLE_VIEW_LAYER);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(
- prop,
- "Visible",
- "Whether this collection is visible, take into account the collection parent");
+ RNA_def_property_ui_text(prop,
+ "Visible",
+ "Whether this collection is visible for the viewlayer, take into "
+ "account the collection parent");
func = RNA_def_function(srna, "has_objects", "rna_LayerCollection_has_objects");
RNA_def_function_ui_description(func, "");
@@ -573,7 +577,7 @@ void RNA_def_view_layer(BlenderRNA *brna)
/* debug update routine */
func = RNA_def_function(srna, "update", "rna_ViewLayer_update_tagged");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
RNA_def_function_ui_description(
func, "Update data tagged to be updated from previous access to data or operators");
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index fec991e16da..2c42dba9131 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -461,8 +461,6 @@ static VFont *rna_Main_fonts_load(Main *bmain,
"Cannot read '%s': %s",
filepath,
errno ? strerror(errno) : TIP_("unsupported font format"));
-
- id_us_min((ID *)font);
}
return font;
}
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 9da17c5f0b1..a29031900ac 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -41,7 +41,7 @@ const EnumPropertyItem rna_enum_ramp_blend_items[] = {
{0, "", ICON_NONE, NULL, NULL},
{MA_RAMP_LIGHT, "LIGHTEN", 0, "Lighten", ""},
{MA_RAMP_SCREEN, "SCREEN", 0, "Screen", ""},
- {MA_RAMP_DODGE, "DODGE", 0, "Dodge", ""},
+ {MA_RAMP_DODGE, "DODGE", 0, "Color Dodge", ""},
{MA_RAMP_ADD, "ADD", 0, "Add", ""},
{0, "", ICON_NONE, NULL, NULL},
{MA_RAMP_OVERLAY, "OVERLAY", 0, "Overlay", ""},
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 48562cf2684..287c7502c41 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -3986,7 +3986,7 @@ static void def_mix_rgb(StructRNA *srna)
prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, rna_enum_ramp_blend_items);
- RNA_def_property_ui_text(prop, "Blend Type", "");
+ RNA_def_property_ui_text(prop, "Blending Mode", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 56d25f5bebf..babf388bfc7 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -70,6 +70,7 @@ static const EnumPropertyItem space_items[] = {
# include "BKE_customdata.h"
# include "BKE_font.h"
# include "BKE_global.h"
+# include "BKE_layer.h"
# include "BKE_main.h"
# include "BKE_mesh.h"
# include "BKE_mball.h"
@@ -283,6 +284,11 @@ static void rna_Object_local_view_set(Object *ob,
}
}
+static bool rna_Object_visible_in_viewport_get(Object *ob, View3D *v3d)
+{
+ return BKE_object_is_visible_in_viewport(v3d, ob);
+}
+
/* Convert a given matrix from a space to another (using the object and/or a bone as
* reference). */
static void rna_Object_mat_convert_space(Object *ob,
@@ -825,6 +831,15 @@ void RNA_api_object(StructRNA *srna)
parm = RNA_def_boolean(func, "state", 0, "", "Local view state to define");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* Viewport */
+ func = RNA_def_function(srna, "visible_in_viewport_get", "rna_Object_visible_in_viewport_get");
+ RNA_def_function_ui_description(
+ func, "Check for local view and local collections for this viewport and object");
+ parm = RNA_def_pointer(func, "viewport", "SpaceView3D", "", "Viewport in local collections");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_boolean(func, "result", 0, "", "Object viewport visibility");
+ RNA_def_function_return(func, parm);
+
/* Matrix space conversion */
func = RNA_def_function(srna, "convert_space", "rna_Object_mat_convert_space");
RNA_def_function_ui_description(
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 0f8f8d39c41..8c4b7dd52d9 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -648,7 +648,7 @@ bool rna_PoseChannel_constraints_override_apply(Main *UNUSED(bmain),
/* Remember that insertion operations are defined and stored in correct order, which means that
* even if we insert several items in a row, we always insert first one, then second one, etc.
- * So we should always find 'anchor' constraint in both _src *and* _dst> */
+ * So we should always find 'anchor' constraint in both _src *and* _dst */
bConstraint *con_anchor = NULL;
if (opop->subitem_local_name && opop->subitem_local_name[0]) {
con_anchor = BLI_findstring(
@@ -669,7 +669,11 @@ bool rna_PoseChannel_constraints_override_apply(Main *UNUSED(bmain),
}
con_src = con_src ? con_src->next : pchan_src->constraints.first;
- BLI_assert(con_src != NULL);
+ if (con_src == NULL) {
+ printf("%s: Could not find constraint to insert, doing nothing...\n", __func__);
+ BLI_assert(0);
+ return false;
+ }
bConstraint *con_dst = BKE_constraint_duplicate_ex(con_src, 0, true);
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 26c8df4c7bb..4db702b215f 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -1157,20 +1157,21 @@ static bool rna_property_override_diff_propptr_validate_diffing(PointerRNA *prop
*r_is_id = *r_is_null = *r_is_type_diff = false;
/* Beware, PointerRNA_NULL has no type and is considered a 'blank page'! */
- if (propptr_a->type == NULL) {
- if (propptr_b == NULL || propptr_b->type == NULL) {
+ if (ELEM(NULL, propptr_a->type, propptr_a->data)) {
+ if (ELEM(NULL, propptr_b, propptr_b->type, propptr_b->data)) {
*r_is_null = true;
}
else {
*r_is_id = RNA_struct_is_ID(propptr_b->type);
*r_is_null = true;
- *r_is_type_diff = true;
+ *r_is_type_diff = propptr_a->type != propptr_b->type;
}
is_valid_for_diffing = false;
}
else {
*r_is_id = RNA_struct_is_ID(propptr_a->type);
- *r_is_null = *r_is_type_diff = (ELEM(NULL, propptr_b, propptr_b->type));
+ *r_is_null = (ELEM(NULL, propptr_b, propptr_b->type, propptr_b->data));
+ *r_is_type_diff = (propptr_b == NULL || propptr_b->type != propptr_a->type);
is_valid_for_diffing = !(*r_is_id || *r_is_null);
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 1f967df7232..ef97b184491 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -5683,7 +5683,8 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "frs_sec_base");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 1e-5f, 1e6f);
- RNA_def_property_ui_range(prop, 0.1f, 120.0f, 2, -1);
+ /* Important to show at least 3 decimal points because multiple presets set this to 1.001. */
+ RNA_def_property_ui_range(prop, 0.1f, 120.0f, 2, 3);
RNA_def_property_ui_text(prop, "FPS Base", "Framerate base");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_fps_update");
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 2b1b23a40f4..8a06d594c1f 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -88,7 +88,11 @@ static void rna_Scene_frame_set(Scene *scene, Main *bmain, int frame, float subf
BPy_END_ALLOW_THREADS;
# endif
- BKE_scene_camera_switch_update(scene);
+ if (BKE_scene_camera_switch_update(scene)) {
+ for (bScreen *sc = bmain->screens.first; sc; sc = sc->id.next) {
+ BKE_screen_view3d_scene_sync(sc, scene);
+ }
+ }
/* don't do notifier when we're rendering, avoid some viewport crashes
* redrawing while the data is being modified for render */
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index 728ef3fb706..1637f8cfed5 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -272,7 +272,7 @@ static void rna_Area_ui_type_update(bContext *C, PointerRNA *ptr)
sa->butspacetype_subtype = 0;
}
-static void rna_View2D_region_to_view(struct View2D *v2d, int x, int y, float result[2])
+static void rna_View2D_region_to_view(struct View2D *v2d, float x, float y, float result[2])
{
UI_view2d_region_to_view(v2d, x, y, &result[0], &result[1]);
}
@@ -406,9 +406,9 @@ static void rna_def_view2d_api(StructRNA *srna)
func = RNA_def_function(srna, "region_to_view", "rna_View2D_region_to_view");
RNA_def_function_ui_description(func, "Transform region coordinates to 2D view");
- parm = RNA_def_int(func, "x", 0, INT_MIN, INT_MAX, "x", "Region x coordinate", -10000, 10000);
+ parm = RNA_def_float(func, "x", 0, -FLT_MAX, FLT_MAX, "x", "Region x coordinate", -10000, 10000);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- parm = RNA_def_int(func, "y", 0, INT_MIN, INT_MAX, "y", "Region y coordinate", -10000, 10000);
+ parm = RNA_def_float(func, "y", 0, -FLT_MAX, FLT_MAX, "y", "Region y coordinate", -10000, 10000);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_float_array(func,
"result",
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index dc0cc0482aa..31ead989f25 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -1462,7 +1462,7 @@ static const EnumPropertyItem blend_mode_items[] = {
{0, "", ICON_NONE, NULL, NULL},
{SEQ_TYPE_LIGHTEN, "LIGHTEN", 0, "Lighten", ""},
{SEQ_TYPE_SCREEN, "SCREEN", 0, "Screen", ""},
- {SEQ_TYPE_DODGE, "DODGE", 0, "Dodge", ""},
+ {SEQ_TYPE_DODGE, "DODGE", 0, "Color Dodge", ""},
{SEQ_TYPE_ADD, "ADD", 0, "Add", ""},
{0, "", ICON_NONE, NULL, NULL},
{SEQ_TYPE_OVERLAY, "OVERLAY", 0, "Overlay", ""},
@@ -1723,7 +1723,7 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "blend_mode");
RNA_def_property_enum_items(prop, blend_mode_items);
RNA_def_property_ui_text(
- prop, "Blend Mode", "Method for controlling how the strip combines with other strips");
+ prop, "Blending Mode", "Method for controlling how the strip combines with other strips");
RNA_def_property_update(
prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
@@ -2225,7 +2225,7 @@ static void rna_def_scene(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "Sequence");
prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_ui_text(prop, "Scene", "Scene that this sequence uses");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
@@ -2785,27 +2785,31 @@ static void rna_def_text(StructRNA *srna)
static void rna_def_color_mix(StructRNA *srna)
{
static EnumPropertyItem blend_color_items[] = {
- {SEQ_TYPE_ADD, "ADD", 0, "Add", ""},
- {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", ""},
+ {SEQ_TYPE_DARKEN, "DARKEN", 0, "Darken", ""},
{SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", ""},
+ {SEQ_TYPE_COLOR_BURN, "BURN", 0, "Color Burn", ""},
+ {SEQ_TYPE_LINEAR_BURN, "LINEAR_BURN", 0, "Linear Burn", ""},
+ {0, "", ICON_NONE, NULL, NULL},
{SEQ_TYPE_LIGHTEN, "LIGHTEN", 0, "Lighten", ""},
- {SEQ_TYPE_DARKEN, "DARKEN", 0, "Darken", ""},
{SEQ_TYPE_SCREEN, "SCREEN", 0, "Screen", ""},
+ {SEQ_TYPE_DODGE, "DODGE", 0, "Color Dodge", ""},
+ {SEQ_TYPE_ADD, "ADD", 0, "Add", ""},
+ {0, "", ICON_NONE, NULL, NULL},
{SEQ_TYPE_OVERLAY, "OVERLAY", 0, "Overlay", ""},
- {SEQ_TYPE_DODGE, "DODGE", 0, "Dodge", ""},
- {SEQ_TYPE_COLOR_BURN, "BURN", 0, "Color Burn", ""},
- {SEQ_TYPE_LINEAR_BURN, "LINEAR_BURN", 0, "Linear Burn", ""},
{SEQ_TYPE_SOFT_LIGHT, "SOFT_LIGHT", 0, "Soft Light", ""},
{SEQ_TYPE_HARD_LIGHT, "HARD_LIGHT", 0, "Hard Light", ""},
- {SEQ_TYPE_PIN_LIGHT, "PIN_LIGHT", 0, "Pin Light", ""},
- {SEQ_TYPE_LIN_LIGHT, "LINEAR_LIGHT", 0, "Linear Light", ""},
{SEQ_TYPE_VIVID_LIGHT, "VIVID_LIGHT", 0, "Vivid Light", ""},
- {SEQ_TYPE_BLEND_COLOR, "COLOR", 0, "Color", ""},
+ {SEQ_TYPE_LIN_LIGHT, "LINEAR_LIGHT", 0, "Linear Light", ""},
+ {SEQ_TYPE_PIN_LIGHT, "PIN_LIGHT", 0, "Pin Light", ""},
+ {0, "", ICON_NONE, NULL, NULL},
+ {SEQ_TYPE_DIFFERENCE, "DIFFERENCE", 0, "Difference", ""},
+ {SEQ_TYPE_EXCLUSION, "EXCLUSION", 0, "Exclusion", ""},
+ {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", ""},
+ {0, "", ICON_NONE, NULL, NULL},
{SEQ_TYPE_HUE, "HUE", 0, "Hue", ""},
{SEQ_TYPE_SATURATION, "SATURATION", 0, "Saturation", ""},
+ {SEQ_TYPE_BLEND_COLOR, "COLOR", 0, "Color", ""},
{SEQ_TYPE_VALUE, "VALUE", 0, "Value", ""},
- {SEQ_TYPE_DIFFERENCE, "DIFFERENCE", 0, "Difference", ""},
- {SEQ_TYPE_EXCLUSION, "EXCLUSION", 0, "Exclusion", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -2817,7 +2821,7 @@ static void rna_def_color_mix(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "blend_effect");
RNA_def_property_enum_items(prop, blend_color_items);
RNA_def_property_ui_text(
- prop, "Blend Effect", "Method for controlling how the strip combines with other strips");
+ prop, "Blending Mode", "Method for controlling how the strip combines with other strips");
RNA_def_property_update(
prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 56ba6403596..1b2adfd28c6 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -589,7 +589,7 @@ static void rna_Space_bool_from_region_flag_set_by_type(PointerRNA *ptr,
{
ScrArea *sa = rna_area_from_space(ptr);
ARegion *ar = BKE_area_find_region_type(sa, region_type);
- if (ar) {
+ if (ar && (ar->alignment != RGN_ALIGN_NONE)) {
SET_FLAG_FROM_TEST(ar->flag, value, region_flag);
}
ED_region_tag_redraw(ar);
@@ -787,13 +787,18 @@ static void rna_Space_view2d_sync_update(Main *UNUSED(bmain),
static void rna_GPencil_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
+ bool changed = false;
/* need set all caches as dirty to recalculate onion skinning */
for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
if (ob->type == OB_GPENCIL) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ changed = true;
}
}
- WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
+ if (changed) {
+ WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
+ }
}
/* Space 3D View */
@@ -1105,7 +1110,7 @@ static const EnumPropertyItem *rna_View3DShading_color_type_itemf(bContext *UNUS
}
else {
/* Solid mode, or lookdev mode for workbench engine. */
- r_free = false;
+ *r_free = false;
return rna_enum_shading_color_type_items;
}
}
diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c
index 64a23dfa985..778e817c73e 100644
--- a/source/blender/makesrna/intern/rna_text.c
+++ b/source/blender/makesrna/intern/rna_text.c
@@ -87,8 +87,60 @@ static int rna_Text_current_line_index_get(PointerRNA *ptr)
static void rna_Text_current_line_index_set(PointerRNA *ptr, int value)
{
- Text *text = (Text *)ptr->data;
- txt_move_toline(text, value, 0);
+ Text *text = ptr->data;
+ TextLine *line = BLI_findlink(&text->lines, value);
+ if (line == NULL) {
+ line = text->lines.last;
+ }
+ text->curl = line;
+ text->curc = 0;
+}
+
+static int rna_Text_select_end_line_index_get(PointerRNA *ptr)
+{
+ Text *text = ptr->data;
+ return BLI_findindex(&text->lines, text->sell);
+}
+
+static void rna_Text_select_end_line_index_set(PointerRNA *ptr, int value)
+{
+ Text *text = ptr->data;
+ TextLine *line = BLI_findlink(&text->lines, value);
+ if (line == NULL) {
+ line = text->lines.last;
+ }
+ text->sell = line;
+ text->selc = 0;
+}
+
+static int rna_Text_current_character_get(PointerRNA *ptr)
+{
+ Text *text = ptr->data;
+ return BLI_str_utf8_offset_to_index(text->curl->line, text->curc);
+}
+
+static void rna_Text_current_character_set(PointerRNA *ptr, int index)
+{
+ Text *text = ptr->data;
+ TextLine *line = text->curl;
+ const int len_utf8 = BLI_strlen_utf8(line->line);
+ CLAMP_MAX(index, len_utf8);
+ text->curc = BLI_str_utf8_offset_from_index(line->line, index);
+}
+
+static int rna_Text_select_end_character_get(PointerRNA *ptr)
+{
+ Text *text = ptr->data;
+ return BLI_str_utf8_offset_to_index(text->sell->line, text->selc);
+}
+
+static void rna_Text_select_end_character_set(PointerRNA *ptr, int index)
+{
+ Text *text = ptr->data;
+ TextLine *line = text->sell;
+ const int len_utf8 = BLI_strlen_utf8(line->line);
+ CLAMP_MAX(index, len_utf8);
+ text->selc = BLI_str_utf8_offset_from_index(line->line, index);
}
static void rna_TextLine_body_get(PointerRNA *ptr, char *value)
@@ -209,12 +261,14 @@ static void rna_def_text(BlenderRNA *brna)
prop, "Current Line", "Current line, and start line of selection if one exists");
prop = RNA_def_property(srna, "current_character", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "curc");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_ui_text(prop,
"Current Character",
"Index of current character in current line, and also start index of "
"character in selection if one exists");
+ RNA_def_property_int_funcs(
+ prop, "rna_Text_current_character_get", "rna_Text_current_character_set", NULL);
+ RNA_def_property_update(prop, NC_TEXT | ND_CURSOR, NULL);
prop = RNA_def_property(srna, "current_line_index", PROP_INT, PROP_NONE);
RNA_def_property_int_funcs(
@@ -230,12 +284,20 @@ static void rna_def_text(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "TextLine");
RNA_def_property_ui_text(prop, "Selection End Line", "End line of selection");
+ prop = RNA_def_property(srna, "select_end_line_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(
+ prop, "rna_Text_select_end_line_index_get", "rna_Text_select_end_line_index_set", NULL);
+ RNA_def_property_ui_text(prop, "Select End Line Index", "Index of last TextLine in selection");
+ RNA_def_property_update(prop, NC_TEXT | ND_CURSOR, NULL);
+
prop = RNA_def_property(srna, "select_end_character", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "selc");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_ui_text(prop,
"Selection End Character",
"Index of character after end of selection in the selection end line");
+ RNA_def_property_int_funcs(
+ prop, "rna_Text_select_end_character_get", "rna_Text_select_end_character_set", NULL);
+ RNA_def_property_update(prop, NC_TEXT | ND_CURSOR, NULL);
RNA_api_text(srna);
}
diff --git a/source/blender/makesrna/intern/rna_text_api.c b/source/blender/makesrna/intern/rna_text_api.c
index 524dcfa9ad7..000076eccec 100644
--- a/source/blender/makesrna/intern/rna_text_api.c
+++ b/source/blender/makesrna/intern/rna_text_api.c
@@ -46,6 +46,18 @@ static void rna_Text_write(Text *text, const char *str)
WM_main_add_notifier(NC_TEXT | NA_EDITED, text);
}
+static void rna_Text_select_set(Text *text, int startl, int startc, int endl, int endc)
+{
+ txt_sel_set(text, startl, startc, endl, endc);
+ WM_main_add_notifier(NC_TEXT | NA_EDITED, text);
+}
+
+static void rna_Text_cursor_set(Text *text, int line, int ch, bool select)
+{
+ txt_move_to(text, line, ch, select);
+ WM_main_add_notifier(NC_TEXT | NA_EDITED, text);
+}
+
#else
void RNA_api_text(StructRNA *srna)
@@ -69,6 +81,25 @@ void RNA_api_text(StructRNA *srna)
RNA_def_function_ui_description(func,
"Returns True if the editor supports syntax highlighting "
"for the current text datablock");
+
+ func = RNA_def_function(srna, "select_set", "rna_Text_select_set");
+ RNA_def_function_ui_description(func, "Set selection range by line and character index");
+ parm = RNA_def_int(func, "line_start", 0, INT_MIN, INT_MAX, "Start Line", "", INT_MIN, INT_MAX);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_int(
+ func, "char_start", 0, INT_MIN, INT_MAX, "Start Character", "", INT_MIN, INT_MAX);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_int(func, "line_end", 0, INT_MIN, INT_MAX, "End Line", "", INT_MIN, INT_MAX);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_int(func, "char_end", 0, INT_MIN, INT_MAX, "End Character", "", INT_MIN, INT_MAX);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "cursor_set", "rna_Text_cursor_set");
+ RNA_def_function_ui_description(func, "Set cursor by line and (optionally) character index");
+ parm = RNA_def_int(func, "line", 0, 0, INT_MAX, "Line", "", 0, INT_MAX);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_int(func, "character", 0, 0, INT_MAX, "Character", "", 0, INT_MAX);
+ RNA_def_boolean(func, "select", false, "", "Select when moving the cursor");
}
#endif
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index c9b6f46ab04..07ce07710b1 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -424,6 +424,17 @@ static void rna_userdef_timecode_style_set(PointerRNA *ptr, int value)
}
}
+static int rna_UserDef_mouse_emulate_3_button_modifier_get(PointerRNA *ptr)
+{
+# if !defined(WIN32)
+ UserDef *userdef = ptr->data;
+ return userdef->mouse_emulate_3_button_modifier;
+# else
+ UNUSED_VARS(ptr);
+ return USER_EMU_MMB_MOD_ALT;
+# endif
+}
+
static PointerRNA rna_UserDef_view_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_PreferencesView, ptr->data);
@@ -3190,6 +3201,18 @@ static void rna_def_userdef_theme_space_nla(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "View Sliders", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+ prop = RNA_def_property(srna, "dopesheet_channel", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "ds_channel");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Channel", "Nonlinear Animation Channel");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+
+ prop = RNA_def_property(srna, "nla_track", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "nla_track");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Track", "Nonlinear Animation Track");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+
prop = RNA_def_property(srna, "active_action", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "anim_active");
RNA_def_property_array(prop, 4);
@@ -4634,6 +4657,13 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
"Color for newly added transformation F-Curves (Location, Rotation, Scale) "
"and also Color is based on the transform axis");
+ prop = RNA_def_property(srna, "fcurve_new_auto_smoothing", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_fcurve_auto_smoothing_items);
+ RNA_def_property_enum_sdna(prop, NULL, "auto_smoothing_new");
+ RNA_def_property_ui_text(prop,
+ "New Curve Smoothing Mode",
+ "Auto Handle Smoothing mode used for newly added F-Curves");
+
prop = RNA_def_property(srna, "keyframe_new_interpolation_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_beztriple_interpolation_mode_items);
RNA_def_property_enum_sdna(prop, NULL, "ipo_new");
@@ -5487,6 +5517,21 @@ static void rna_def_userdef_input(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_userdef_keyconfig_reload_update");
+ static const EnumPropertyItem mouse_emulate_3_button_modifier[] = {
+ {USER_EMU_MMB_MOD_ALT, "ALT", 0, "Alt", ""},
+ {USER_EMU_MMB_MOD_OSKEY, "OSKEY", 0, "OS-Key", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ prop = RNA_def_property(srna, "mouse_emulate_3_button_modifier", PROP_ENUM, PROP_NONE);
+ /* Only needed because of WIN32 inability to support the option. */
+ RNA_def_property_enum_funcs(prop, "rna_UserDef_mouse_emulate_3_button_modifier_get", NULL, NULL);
+ RNA_def_property_enum_items(prop, mouse_emulate_3_button_modifier);
+ RNA_def_property_ui_text(
+ prop, "Emulate 3 Button Modifier", "Hold this modifier to emulate the middle mouse button");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_userdef_keyconfig_reload_update");
+
prop = RNA_def_property(srna, "use_emulate_numpad", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_NONUMPAD);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_workspace_api.c b/source/blender/makesrna/intern/rna_workspace_api.c
index b8c6a25ace8..f22c86b3ff2 100644
--- a/source/blender/makesrna/intern/rna_workspace_api.c
+++ b/source/blender/makesrna/intern/rna_workspace_api.c
@@ -110,7 +110,7 @@ void RNA_api_workspace(StructRNA *srna)
FunctionRNA *func;
PropertyRNA *parm;
- func = RNA_def_function(srna, "status_text_set", "ED_workspace_status_text");
+ func = RNA_def_function(srna, "status_text_set_internal", "ED_workspace_status_text");
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
RNA_def_function_ui_description(
func, "Set the status bar text, typically key shortcuts for modal operators");
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index 53bb579128a..883c17aa1e1 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -228,16 +228,22 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
return result;
}
-static void deformVerts(ModifierData *md,
- const ModifierEvalContext *UNUSED(ctx),
- Mesh *mesh,
- float (*vertex_cos)[3],
- int num_verts)
+static void deformMatrices(ModifierData *md,
+ const ModifierEvalContext *UNUSED(ctx),
+ Mesh *mesh,
+ float (*vertex_cos)[3],
+ float (*deform_matrices)[3][3],
+ int num_verts)
+
{
#if !defined(WITH_OPENSUBDIV)
modifier_setError(md, "Disabled, built without OpenSubdiv");
return;
#endif
+
+ /* Subsurf does not require extra space mapping, keep matrices as is. */
+ (void)deform_matrices;
+
MultiresModifierData *mmd = (MultiresModifierData *)md;
SubdivSettings subdiv_settings;
BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
@@ -268,8 +274,8 @@ ModifierTypeInfo modifierType_Multires = {
/* copyData */ copyData,
- /* deformVerts */ deformVerts,
- /* deformMatrices */ NULL,
+ /* deformVerts */ NULL,
+ /* deformMatrices */ deformMatrices,
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* applyModifier */ applyModifier,
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index 55df1b5ddda..4a5887c3122 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -241,16 +241,21 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
return result;
}
-static void deformVerts(ModifierData *md,
- const ModifierEvalContext *UNUSED(ctx),
- Mesh *mesh,
- float (*vertex_cos)[3],
- int num_verts)
+static void deformMatrices(ModifierData *md,
+ const ModifierEvalContext *UNUSED(ctx),
+ Mesh *mesh,
+ float (*vertex_cos)[3],
+ float (*deform_matrices)[3][3],
+ int num_verts)
{
#if !defined(WITH_OPENSUBDIV)
modifier_setError(md, "Disabled, built without OpenSubdiv");
return;
#endif
+
+ /* Subsurf does not require extra space mapping, keep matrices as is. */
+ (void)deform_matrices;
+
SubsurfModifierData *smd = (SubsurfModifierData *)md;
SubdivSettings subdiv_settings;
subdiv_settings_init(&subdiv_settings, smd);
@@ -281,8 +286,8 @@ ModifierTypeInfo modifierType_Subsurf = {
/* copyData */ copyData,
- /* deformVerts */ deformVerts,
- /* deformMatrices */ NULL,
+ /* deformVerts */ NULL,
+ /* deformMatrices */ deformMatrices,
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* applyModifier */ applyModifier,
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 92266600612..4bcd77496c1 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -412,7 +412,8 @@ static void flatten_group_do(bNodeTree *ntree, bNode *gnode)
BLI_remlink(&ngroup->nodes, node);
BLI_addtail(&ntree->nodes, node);
/* ensure unique node name in the node tree */
- nodeUniqueName(ntree, node);
+ /* This is very slow and it has no use for GPU nodetree. (see T70609) */
+ // nodeUniqueName(ntree, node);
}
/* Save first and last link to iterate over flattened group links. */
@@ -441,6 +442,8 @@ static void flatten_group_do(bNodeTree *ntree, bNode *gnode)
}
}
}
+ /* Also iterate over the new links to cover passthrough links. */
+ glinks_last = ntree->links.last;
/* output links */
for (tlink = ntree->links.first; tlink != glinks_first->next; tlink = tlink->next) {
if (tlink->fromnode == gnode) {
@@ -626,7 +629,7 @@ static bNode *ntree_shader_copy_branch(bNodeTree *ntree,
/* Count and tag all nodes inside the displacement branch of the tree. */
start_node->tmp_flag = 0;
int node_count = 1;
- nodeChainIterBackwards(ntree, start_node, ntree_branch_count_and_tag_nodes, &node_count);
+ nodeChainIterBackwards(ntree, start_node, ntree_branch_count_and_tag_nodes, &node_count, 1);
/* Make a full copy of the branch */
bNode **nodes_copy = MEM_mallocN(sizeof(bNode *) * node_count, __func__);
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
@@ -760,13 +763,13 @@ static void node_tag_branch_as_derivative(bNode *node, int dx)
}
}
-static bool ntree_shader_bump_branches(bNode *UNUSED(fromnode), bNode *tonode, void *userdata)
+static bool ntree_shader_bump_branches(bNode *fromnode, bNode *UNUSED(tonode), void *userdata)
{
bNodeTree *ntree = (bNodeTree *)userdata;
- if (tonode->type == SH_NODE_BUMP) {
+ if (fromnode->type == SH_NODE_BUMP) {
bNodeSocket *height_dx_sock, *height_dy_sock, *bump_socket, *bump_dx_socket, *bump_dy_socket;
- bNode *bump = tonode;
+ bNode *bump = fromnode;
bump_socket = ntree_shader_node_find_input(bump, "Height");
bump_dx_socket = ntree_shader_node_find_input(bump, "Height_dx");
bump_dy_socket = ntree_shader_node_find_input(bump, "Height_dy");
@@ -829,7 +832,7 @@ void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tag
/* Make sure sockets links pointers are correct. */
ntreeUpdateTree(G.main, ntree);
- nodeChainIterBackwards(ntree, output_node, ntree_tag_bsdf_cb, tags);
+ nodeChainIterBackwards(ntree, output_node, ntree_tag_bsdf_cb, tags, 0);
}
/* This one needs to work on a local tree. */
@@ -858,7 +861,7 @@ void ntreeGPUMaterialNodes(bNodeTree *localtree,
/* Duplicate bump height branches for manual derivatives.
*/
- nodeChainIterBackwards(localtree, output, ntree_shader_bump_branches, localtree);
+ nodeChainIterBackwards(localtree, output, ntree_shader_bump_branches, localtree, 0);
/* TODO(fclem): consider moving this to the gpu shader tree evaluation. */
nTreeTags tags = {
diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c
index d94141c3699..3798cfbbfac 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geometry.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c
@@ -47,17 +47,32 @@ static int node_shader_gpu_geometry(GPUMaterial *mat,
/* Opti: don't request orco if not needed. */
GPUNodeLink *orco_link = (!out[2].hasoutput) ? GPU_constant(val) : GPU_attribute(CD_ORCO, "");
- return GPU_stack_link(mat,
- node,
- "node_geometry",
- in,
- out,
- GPU_builtin(GPU_VIEW_POSITION),
- GPU_builtin(GPU_WORLD_NORMAL),
- orco_link,
- GPU_builtin(GPU_OBJECT_MATRIX),
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
- bary_link);
+ const bool success = GPU_stack_link(mat,
+ node,
+ "node_geometry",
+ in,
+ out,
+ GPU_builtin(GPU_VIEW_POSITION),
+ GPU_builtin(GPU_WORLD_NORMAL),
+ orco_link,
+ GPU_builtin(GPU_OBJECT_MATRIX),
+ GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
+ bary_link);
+
+ /* for each output */
+ for (int i = 0; sh_node_geometry_out[i].type != -1; i++) {
+ node_shader_gpu_bump_tex_coord(mat, node, &out[i].link);
+ /* Normalize some vectors after dFdx/dFdy offsets.
+ * This is the case for interpolated, non linear functions.
+ * The resulting vector can still be a bit wrong but not as much.
+ * (see T70644) */
+ if (node->branch_tag != 0 && ELEM(i, 1, 2, 4)) {
+ GPU_link(
+ mat, "vector_math_normalize", out[i].link, out[i].link, out[i].link, &out[i].link, NULL);
+ }
+ }
+
+ return success;
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
index 068458b7e1f..8bb17acc4d3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
@@ -63,6 +63,14 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat,
/* for each output. */
for (int i = 0; sh_node_tex_coord_out[i].type != -1; i++) {
node_shader_gpu_bump_tex_coord(mat, node, &out[i].link);
+ /* Normalize some vectors after dFdx/dFdy offsets.
+ * This is the case for interpolated, non linear functions.
+ * The resulting vector can still be a bit wrong but not as much.
+ * (see T70644) */
+ if (node->branch_tag != 0 && ELEM(i, 1, 6)) {
+ GPU_link(
+ mat, "vector_math_normalize", out[i].link, out[i].link, out[i].link, &out[i].link, NULL);
+ }
}
return 1;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
index daf4053f182..56e102a118d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
@@ -136,8 +136,8 @@ static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *nod
tex->musgrave_type != SHD_MUSGRAVE_MULTIFRACTAL &&
tex->musgrave_type != SHD_MUSGRAVE_FBM);
nodeSetSocketAvailability(inGainSock,
- tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL &&
- tex->musgrave_type != SHD_MUSGRAVE_RIDGED_MULTIFRACTAL);
+ tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL ||
+ tex->musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL);
}
void register_node_type_sh_tex_musgrave(void)
diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c
index fd37c8521c1..b6ba119f695 100644
--- a/source/blender/python/bmesh/bmesh_py_ops.c
+++ b/source/blender/python/bmesh/bmesh_py_ops.c
@@ -166,10 +166,10 @@ static PyTypeObject bmesh_op_Type = {
sizeof(BPy_BMeshOpFunc), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
- NULL, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
- NULL, /* getattrfunc tp_getattr; */
- NULL, /* setattrfunc tp_setattr; */
+ NULL, /* tp_dealloc */
+ (printfunc)NULL, /* printfunc tp_print; */
+ NULL, /* getattrfunc tp_getattr; */
+ NULL, /* setattrfunc tp_setattr; */
NULL,
/* tp_compare */ /* DEPRECATED in python 3.0! */
(reprfunc)bpy_bmesh_op_repr, /* tp_repr */
@@ -282,10 +282,10 @@ static PyTypeObject bmesh_ops_fakemod_Type = {
0, /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
- NULL, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
- NULL, /* getattrfunc tp_getattr; */
- NULL, /* setattrfunc tp_setattr; */
+ NULL, /* tp_dealloc */
+ (printfunc)NULL, /* printfunc tp_print; */
+ NULL, /* getattrfunc tp_getattr; */
+ NULL, /* setattrfunc tp_setattr; */
NULL,
/* tp_compare */ /* DEPRECATED in python 3.0! */
NULL, /* tp_repr */
diff --git a/source/blender/python/generic/blf_py_api.c b/source/blender/python/generic/blf_py_api.c
index b90483e89b9..62f5a568ee1 100644
--- a/source/blender/python/generic/blf_py_api.c
+++ b/source/blender/python/generic/blf_py_api.c
@@ -20,6 +20,9 @@
* This file defines the 'bgl' module, used for drawing text in OpenGL.
*/
+/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */
+#define PY_SSIZE_T_CLEAN
+
#include <Python.h>
#include "blf_py_api.h"
@@ -176,7 +179,7 @@ PyDoc_STRVAR(py_blf_draw_doc,
static PyObject *py_blf_draw(PyObject *UNUSED(self), PyObject *args)
{
const char *text;
- int text_length;
+ Py_ssize_t text_length;
int fontid;
if (!PyArg_ParseTuple(args, "is#:blf.draw", &fontid, &text, &text_length)) {
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index 335dea0a2b6..1ea7795a0e3 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -1172,7 +1172,7 @@ PyTypeObject BPy_IDGroup_Type = {
/* Methods to implement standard operations */
NULL, /* destructor tp_dealloc; */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
@@ -1577,7 +1577,7 @@ PyTypeObject BPy_IDArray_Type = {
/* Methods to implement standard operations */
NULL, /* destructor tp_dealloc; */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
@@ -1692,7 +1692,7 @@ PyTypeObject BPy_IDGroup_Iter_Type = {
/* Methods to implement standard operations */
NULL, /* destructor tp_dealloc; */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
diff --git a/source/blender/python/generic/imbuf_py_api.c b/source/blender/python/generic/imbuf_py_api.c
index 6a7f899488b..d35fc027f43 100644
--- a/source/blender/python/generic/imbuf_py_api.c
+++ b/source/blender/python/generic/imbuf_py_api.c
@@ -348,7 +348,7 @@ PyTypeObject Py_ImBuf_Type = {
/* Methods to implement standard operations */
(destructor)py_imbuf_dealloc, /* destructor tp_dealloc; */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index a6983c38f0e..c85a1d9ba05 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -25,9 +25,18 @@
* BLI_string_utf8() for unicode conversion.
*/
+/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */
+#define PY_SSIZE_T_CLEAN
+
#include <Python.h>
#include <frameobject.h>
+/* Needed for 'PyInterpreterState', we should remove this dependency. */
+#if PY_VERSION_HEX >= 0x03080000
+# define Py_BUILD_CORE
+# include <internal/pycore_pystate.h>
+#endif
+
#include "BLI_utildefines.h" /* for bool */
#include "py_capi_utils.h"
@@ -867,7 +876,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...)
va_list vargs;
- int *sizes = PyMem_MALLOC(sizeof(int) * (n / 2));
+ Py_ssize_t *sizes = PyMem_MALLOC(sizeof(*sizes) * (n / 2));
int i;
PyObject *py_dict = PyC_DefaultNameSpace(filepath);
diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c
index 70f76896898..6505e59624b 100644
--- a/source/blender/python/gpu/gpu_py_offscreen.c
+++ b/source/blender/python/gpu/gpu_py_offscreen.c
@@ -183,7 +183,7 @@ static PyObject *bpygpu_offscreen_unbind(BPyGPUOffScreen *self, PyObject *args,
PyDoc_STRVAR(
bpygpu_offscreen_draw_view3d_doc,
- ".. method:: draw_view3d(scene, view3d, region, view_matrix, projection_matrix)\n"
+ ".. method:: draw_view3d(scene, view_layer, view3d, region, view_matrix, projection_matrix)\n"
"\n"
" Draw the 3d viewport in the offscreen object.\n"
"\n"
diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c
index 3c1dbfba72e..fffa43c1dcd 100644
--- a/source/blender/python/intern/bpy_app_translations.c
+++ b/source/blender/python/intern/bpy_app_translations.c
@@ -780,10 +780,10 @@ static PyTypeObject BlenderAppTranslationsType = {
0, /* tp_itemsize */
/* methods */
/* No destructor, this is a singleton! */
- NULL, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
- NULL, /* getattrfunc tp_getattr; */
- NULL, /* setattrfunc tp_setattr; */
+ NULL, /* tp_dealloc */
+ (printfunc)NULL, /* printfunc tp_print; */
+ NULL, /* getattrfunc tp_getattr; */
+ NULL, /* setattrfunc tp_setattr; */
NULL,
/* tp_compare */ /* DEPRECATED in python 3.0! */
NULL, /* tp_repr */
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index 5ea16c8c197..b797624f23c 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -92,7 +92,7 @@ static PyTypeObject bpy_lib_Type = {
0, /* tp_itemsize */
/* methods */
(destructor)bpy_lib_dealloc, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL,
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index 6b63d1ef2c3..4fd81a707fb 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -22,6 +22,9 @@
* existing blender types.
*/
+/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */
+#define PY_SSIZE_T_CLEAN
+
#include <Python.h>
#include "RNA_types.h"
@@ -2101,7 +2104,7 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
if (srna) {
const char *id = NULL, *name = NULL, *description = "";
- int id_len;
+ Py_ssize_t id_len;
bool def = false;
PropertyRNA *prop;
PyObject *pyopts = NULL;
@@ -2204,7 +2207,7 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject
if (srna) {
const char *id = NULL, *name = NULL, *description = "";
- int id_len;
+ Py_ssize_t id_len;
bool def[PYRNA_STACK_ARRAY] = {0};
int size = 3;
PropertyRNA *prop;
@@ -2336,7 +2339,7 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
if (srna) {
const char *id = NULL, *name = NULL, *description = "";
- int id_len;
+ Py_ssize_t id_len;
int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1, def = 0;
PropertyRNA *prop;
PyObject *pyopts = NULL;
@@ -2456,7 +2459,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject
if (srna) {
const char *id = NULL, *name = NULL, *description = "";
- int id_len;
+ Py_ssize_t id_len;
int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1;
int def[PYRNA_STACK_ARRAY] = {0};
int size = 3;
@@ -2599,7 +2602,7 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
if (srna) {
const char *id = NULL, *name = NULL, *description = "";
- int id_len;
+ Py_ssize_t id_len;
float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3,
def = 0.0f;
int precision = 2;
@@ -2735,7 +2738,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec
if (srna) {
const char *id = NULL, *name = NULL, *description = "";
- int id_len;
+ Py_ssize_t id_len;
float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3;
float def[PYRNA_STACK_ARRAY] = {0.0f};
int precision = 2, size = 3;
@@ -2869,7 +2872,7 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw
if (srna) {
const char *id = NULL, *name = NULL, *description = "", *def = "";
- int id_len;
+ Py_ssize_t id_len;
int maxlen = 0;
PropertyRNA *prop;
PyObject *pyopts = NULL;
@@ -3015,7 +3018,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
if (srna) {
const char *id = NULL, *name = NULL, *description = "";
PyObject *def = NULL;
- int id_len;
+ Py_ssize_t id_len;
int defvalue = 0;
PyObject *items, *items_fast;
const EnumPropertyItem *eitems;
@@ -3191,7 +3194,7 @@ PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
if (srna) {
const char *id = NULL, *name = NULL, *description = "";
- int id_len;
+ Py_ssize_t id_len;
PropertyRNA *prop;
StructRNA *ptype;
PyObject *type = Py_None;
@@ -3286,7 +3289,7 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
BPY_PROPDEF_HEAD(CollectionProperty);
if (srna) {
- int id_len;
+ Py_ssize_t id_len;
const char *id = NULL, *name = NULL, *description = "";
PropertyRNA *prop;
StructRNA *ptype;
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 45a7d2dacd1..570c5012ed8 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -70,6 +70,8 @@
/* Only for types. */
#include "BKE_node.h"
+#include "DEG_depsgraph_query.h"
+
#include "../generic/idprop_py_api.h" /* For IDprop lookups. */
#include "../generic/py_capi_utils.h"
#include "../generic/python_utildefines.h"
@@ -918,7 +920,10 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self)
tmp_str = PyUnicode_FromString(id->name + 2);
- if (RNA_struct_is_ID(self->ptr.type) && (id->flag & LIB_PRIVATE_DATA) == 0) {
+ if (DEG_get_original_id(id) != id) {
+ ret = PyUnicode_FromFormat("Evaluated %s %R", BKE_idcode_to_name(GS(id->name)), tmp_str);
+ }
+ else if (RNA_struct_is_ID(self->ptr.type) && (id->flag & LIB_PRIVATE_DATA) == 0) {
ret = PyUnicode_FromFormat(
"bpy.data.%s[%R]", BKE_idcode_to_name_plural(GS(id->name)), tmp_str);
}
@@ -926,14 +931,25 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self)
const char *path;
ID *real_id = NULL;
path = RNA_path_from_real_ID_to_struct(G_MAIN, &self->ptr, &real_id);
- if (path) {
- if (real_id != id) {
+ if (path != NULL) {
+ /* 'real_id' may be NULL in some cases, although the only valid one is evaluated data,
+ * which should have already been caught above.
+ * So assert, but handle it without crashing for release builds. */
+ BLI_assert(real_id != NULL);
+
+ if (real_id != NULL) {
Py_DECREF(tmp_str);
tmp_str = PyUnicode_FromString(real_id->name + 2);
+ ret = PyUnicode_FromFormat(
+ "bpy.data.%s[%R].%s", BKE_idcode_to_name_plural(GS(real_id->name)), tmp_str, path);
+ }
+ else {
+ /* Can't find the path, print something useful as a fallback. */
+ ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s",
+ BKE_idcode_to_name_plural(GS(id->name)),
+ tmp_str,
+ RNA_struct_identifier(self->ptr.type));
}
- ret = PyUnicode_FromFormat(
- "bpy.data.%s[%R].%s", BKE_idcode_to_name_plural(GS(real_id->name)), tmp_str, path);
-
MEM_freeN((void *)path);
}
else {
@@ -6221,10 +6237,10 @@ PyTypeObject pyrna_struct_meta_idprop_Type = {
0, /* tp_itemsize */
/* methods */
- NULL, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
- NULL, /* getattrfunc tp_getattr; */
- NULL, /* setattrfunc tp_setattr; */
+ NULL, /* tp_dealloc */
+ (printfunc)NULL, /* printfunc tp_print; */
+ NULL, /* getattrfunc tp_getattr; */
+ NULL, /* setattrfunc tp_setattr; */
NULL,
/* tp_compare */ /* deprecated in Python 3.0! */
NULL, /* tp_repr */
@@ -6303,7 +6319,7 @@ PyTypeObject pyrna_struct_Type = {
0, /* tp_itemsize */
/* methods */
(destructor)pyrna_struct_dealloc, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL,
@@ -6392,7 +6408,7 @@ PyTypeObject pyrna_prop_Type = {
0, /* tp_itemsize */
/* methods */
(destructor)pyrna_prop_dealloc, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL,
@@ -6476,7 +6492,7 @@ PyTypeObject pyrna_prop_array_Type = {
0, /* tp_itemsize */
/* methods */
(destructor)pyrna_prop_array_dealloc, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL,
@@ -6559,7 +6575,7 @@ PyTypeObject pyrna_prop_collection_Type = {
0, /* tp_itemsize */
/* methods */
(destructor)pyrna_prop_dealloc, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL,
@@ -6645,7 +6661,7 @@ static PyTypeObject pyrna_prop_collection_idprop_Type = {
0, /* tp_itemsize */
/* methods */
(destructor)pyrna_prop_dealloc, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL,
@@ -6730,10 +6746,10 @@ PyTypeObject pyrna_func_Type = {
sizeof(BPy_FunctionRNA), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
- NULL, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
- NULL, /* getattrfunc tp_getattr; */
- NULL, /* setattrfunc tp_setattr; */
+ NULL, /* tp_dealloc */
+ (printfunc)NULL, /* printfunc tp_print; */
+ NULL, /* getattrfunc tp_getattr; */
+ NULL, /* setattrfunc tp_setattr; */
NULL,
/* tp_compare */ /* DEPRECATED in Python 3.0! */
(reprfunc)pyrna_func_repr, /* tp_repr */
@@ -6827,7 +6843,7 @@ static PyTypeObject pyrna_prop_collection_iter_Type = {
0, /* tp_itemsize */
/* methods */
(destructor)pyrna_prop_collection_iter_dealloc, /* tp_dealloc */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL,
diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c
index 4e21a8e0389..b587738c8d7 100644
--- a/source/blender/python/mathutils/mathutils_Color.c
+++ b/source/blender/python/mathutils/mathutils_Color.c
@@ -921,7 +921,7 @@ PyTypeObject color_Type = {
sizeof(ColorObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)BaseMathObject_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
+ (printfunc)NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
NULL, /* tp_compare */
diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c
index 56662465b52..3fd9bf666e2 100644
--- a/source/blender/python/mathutils/mathutils_Euler.c
+++ b/source/blender/python/mathutils/mathutils_Euler.c
@@ -750,7 +750,7 @@ PyTypeObject euler_Type = {
sizeof(EulerObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)BaseMathObject_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
+ (printfunc)NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
NULL, /* tp_compare */
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 6fd0fab2cdd..c6e6d395b6b 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -3141,7 +3141,7 @@ PyTypeObject matrix_Type = {
sizeof(MatrixObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)BaseMathObject_dealloc, /*tp_dealloc*/
- NULL, /*tp_print*/
+ (printfunc)NULL, /*tp_print*/
NULL, /*tp_getattr*/
NULL, /*tp_setattr*/
NULL, /*tp_compare*/
@@ -3532,7 +3532,7 @@ PyTypeObject matrix_access_Type = {
sizeof(MatrixAccessObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)MatrixAccess_dealloc, /*tp_dealloc*/
- NULL, /*tp_print*/
+ (printfunc)NULL, /*tp_print*/
NULL, /*tp_getattr*/
NULL, /*tp_setattr*/
NULL, /*tp_compare*/
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index 2b3aa29a366..0de1ffb9879 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -1527,7 +1527,7 @@ PyTypeObject quaternion_Type = {
sizeof(QuaternionObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)BaseMathObject_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
+ (printfunc)NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
NULL, /* tp_compare */
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index 0555c707ed3..387e560d946 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -3055,7 +3055,7 @@ PyTypeObject vector_Type = {
/* Methods to implement standard operations */
(destructor)BaseMathObject_dealloc, /* destructor tp_dealloc; */
- NULL, /* printfunc tp_print; */
+ (printfunc)NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
index 254177b14fe..d28b9a0de8f 100644
--- a/source/blender/python/mathutils/mathutils_bvhtree.c
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -1267,7 +1267,7 @@ PyTypeObject PyBVHTree_Type = {
0, /* tp_itemsize */
/* methods */
(destructor)py_bvhtree__tp_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
+ (printfunc)NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
NULL, /* tp_compare */
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 13d36e5af91..9a519abd49f 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -1201,8 +1201,8 @@ static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject
PyDoc_STRVAR(M_Geometry_tessellate_polygon_doc,
".. function:: tessellate_polygon(veclist_list)\n"
"\n"
- " Takes a list of polylines (each point a vector) and returns the point indices "
- "for a polyline filled with triangles.\n"
+ " Takes a list of polylines (each point a pair or triplet of numbers) and returns "
+ "the point indices for a polyline filled with triangles.\n"
"\n"
" :arg veclist_list: list of polylines\n"
" :rtype: list\n");
@@ -1211,13 +1211,15 @@ static PyObject *M_Geometry_tessellate_polygon(PyObject *UNUSED(self), PyObject
{
PyObject *tri_list; /*return this list of tri's */
PyObject *polyLine, *polyVec;
- int i, len_polylines, len_polypoints, ls_error = 0;
+ int i, len_polylines, len_polypoints;
+ bool list_parse_error = false;
+ bool is_2d = true;
/* Display #ListBase. */
ListBase dispbase = {NULL, NULL};
DispList *dl;
float *fp; /*pointer to the array of malloced dl->verts to set the points from the vectors */
- int index, *dl_face, totpoints = 0;
+ int totpoints = 0;
if (!PySequence_Check(polyLineSeq)) {
PyErr_SetString(PyExc_TypeError, "expected a sequence of poly lines");
@@ -1238,15 +1240,6 @@ static PyObject *M_Geometry_tessellate_polygon(PyObject *UNUSED(self), PyObject
len_polypoints = PySequence_Size(polyLine);
if (len_polypoints > 0) { /* don't bother adding edges as polylines */
-# if 0
- if (EXPP_check_sequence_consistency(polyLine, &vector_Type) != 1) {
- freedisplist(&dispbase);
- Py_DECREF(polyLine);
- PyErr_SetString(PyExc_TypeError,
- "A point in one of the polylines is not a mathutils.Vector type");
- return NULL;
- }
-# endif
dl = MEM_callocN(sizeof(DispList), "poly disp");
BLI_addtail(&dispbase, dl);
dl->type = DL_INDEX3;
@@ -1254,49 +1247,38 @@ static PyObject *M_Geometry_tessellate_polygon(PyObject *UNUSED(self), PyObject
dl->type = DL_POLY;
dl->parts = 1; /* no faces, 1 edge loop */
dl->col = 0; /* no material */
- dl->verts = fp = MEM_callocN(sizeof(float) * 3 * len_polypoints, "dl verts");
- dl->index = MEM_callocN(sizeof(int) * 3 * len_polypoints, "dl index");
+ dl->verts = fp = MEM_mallocN(sizeof(float[3]) * len_polypoints, "dl verts");
+ dl->index = MEM_callocN(sizeof(int[3]) * len_polypoints, "dl index");
- for (index = 0; index < len_polypoints; index++, fp += 3) {
+ for (int index = 0; index < len_polypoints; index++, fp += 3) {
polyVec = PySequence_GetItem(polyLine, index);
- if (VectorObject_Check(polyVec)) {
-
- if (BaseMath_ReadCallback((VectorObject *)polyVec) == -1) {
- ls_error = 1;
- }
+ const int polyVec_len = mathutils_array_parse(
+ fp, 2, 3 | MU_ARRAY_SPILL, polyVec, "tessellate_polygon: parse coord");
+ Py_DECREF(polyVec);
- fp[0] = ((VectorObject *)polyVec)->vec[0];
- fp[1] = ((VectorObject *)polyVec)->vec[1];
- if (((VectorObject *)polyVec)->size > 2) {
- fp[2] = ((VectorObject *)polyVec)->vec[2];
- }
- else {
- /* if its a 2d vector then set the z to be zero */
- fp[2] = 0.0f;
- }
+ if (UNLIKELY(polyVec_len == -1)) {
+ list_parse_error = true;
}
- else {
- ls_error = 1;
+ else if (polyVec_len == 2) {
+ fp[2] = 0.0f;
+ }
+ else if (polyVec_len == 3) {
+ is_2d = false;
}
totpoints++;
- Py_DECREF(polyVec);
}
}
Py_DECREF(polyLine);
}
- if (ls_error) {
+ if (list_parse_error) {
BKE_displist_free(&dispbase); /* possible some dl was allocated */
- PyErr_SetString(PyExc_TypeError,
- "A point in one of the polylines "
- "is not a mathutils.Vector type");
return NULL;
}
else if (totpoints) {
/* now make the list to return */
- /* TODO, add normal arg */
- BKE_displist_fill(&dispbase, &dispbase, NULL, false);
+ BKE_displist_fill(&dispbase, &dispbase, is_2d ? ((const float[3]){0, 0, -1}) : NULL, false);
/* The faces are stored in a new DisplayList
* that's added to the head of the #ListBase. */
@@ -1309,12 +1291,10 @@ static PyObject *M_Geometry_tessellate_polygon(PyObject *UNUSED(self), PyObject
return NULL;
}
- index = 0;
- dl_face = dl->index;
- while (index < dl->parts) {
+ int *dl_face = dl->index;
+ for (int index = 0; index < dl->parts; index++) {
PyList_SET_ITEM(tri_list, index, PyC_Tuple_Pack_I32(dl_face[0], dl_face[1], dl_face[2]));
dl_face += 3;
- index++;
}
BKE_displist_free(&dispbase);
}
diff --git a/source/blender/python/mathutils/mathutils_kdtree.c b/source/blender/python/mathutils/mathutils_kdtree.c
index b8a7f4d8708..65eac901df5 100644
--- a/source/blender/python/mathutils/mathutils_kdtree.c
+++ b/source/blender/python/mathutils/mathutils_kdtree.c
@@ -393,7 +393,7 @@ PyTypeObject PyKDTree_Type = {
0, /* tp_itemsize */
/* methods */
(destructor)PyKDTree__tp_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
+ (printfunc)NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
NULL, /* tp_compare */
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index ddd0ddb46da..59f99a9ff88 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -68,6 +68,7 @@ set(SRC
intern/wm_operator_type.c
intern/wm_operators.c
intern/wm_panel_type.c
+ intern/wm_platform_support.c
intern/wm_playanim.c
intern/wm_splash_screen.c
intern/wm_stereo.c
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 2d9fa9e5ab6..f8b6b5171da 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -156,8 +156,14 @@ void WM_opengl_context_activate(void *context);
void WM_opengl_context_release(void *context);
struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect);
-struct wmWindow *WM_window_open_temp(
- struct bContext *C, const char *title, int x, int y, int sizex, int sizey, int space_type);
+struct wmWindow *WM_window_open_temp(struct bContext *C,
+ const char *title,
+ int x,
+ int y,
+ int sizex,
+ int sizey,
+ int space_type,
+ bool dialog);
void WM_window_set_dpi(wmWindow *win);
bool WM_stereo3d_enabled(struct wmWindow *win, bool only_fullscreen_test);
@@ -329,6 +335,12 @@ void WM_event_timer_sleep(struct wmWindowManager *wm,
/* operator api, default callbacks */
/* invoke callback, uses enum property named "type" */
+int WM_generic_select_modal(struct bContext *C,
+ struct wmOperator *op,
+ const struct wmEvent *event);
+int WM_generic_select_invoke(struct bContext *C,
+ struct wmOperator *op,
+ const struct wmEvent *event);
void WM_operator_view3d_unit_defaults(struct bContext *C, struct wmOperator *op);
int WM_operator_smooth_viewtx_get(const struct wmOperator *op);
int WM_menu_invoke_ex(struct bContext *C, struct wmOperator *op, int opcontext);
@@ -468,6 +480,7 @@ void WM_operator_properties_select_random(struct wmOperatorType *ot);
int WM_operator_properties_select_random_seed_increment_get(wmOperator *op);
void WM_operator_properties_select_operation(struct wmOperatorType *ot);
void WM_operator_properties_select_operation_simple(struct wmOperatorType *ot);
+void WM_operator_properties_generic_select(struct wmOperatorType *ot);
struct CheckerIntervalParams {
int nth; /* bypass when set to zero */
int skip;
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 4b1abeceebb..8e796a7981a 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -192,6 +192,15 @@ void WM_cursor_set(wmWindow *win, int curs)
GHOST_TStandardCursor ghost_cursor = convert_to_ghost_standard_cursor(curs);
+#if !defined(_WIN32) && !defined(__APPLE__)
+ /* Workaround crosshair cursors with bad visibility in some cursor themes.
+ * Better solution would be to always use custom cursors and support DPI
+ * properly so that the cursors look as good as the native ones. */
+ if (U.curssize && ghost_cursor == GHOST_kStandardCursorCrosshair) {
+ ghost_cursor = GHOST_kStandardCursorCustom;
+ }
+#endif
+
if (ghost_cursor != GHOST_kStandardCursorCustom &&
GHOST_HasCursorShape(win->ghostwin, ghost_cursor)) {
/* Use native GHOST cursor when available. */
@@ -695,38 +704,40 @@ void wm_init_cursor_data(void)
/****************** Normal Cross Cursor ************************/
BEGIN_CURSOR_BLOCK;
static char cross_sbm[] = {
- 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
- 0x01, 0x00, 0x00, 0x3f, 0xfc, 0x3f, 0xfc, 0x00, 0x00, 0x80, 0x01,
- 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
+ 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
+ 0x01, 0x00, 0x00, 0x3e, 0x7c, 0x3e, 0x7c, 0x00, 0x00, 0x80, 0x01,
+ 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00,
+
};
static char cross_smsk[] = {
0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0,
- 0x03, 0x7f, 0xfe, 0x3f, 0xfc, 0x3f, 0xfc, 0x7f, 0xfe, 0xc0, 0x03,
+ 0x03, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0xff, 0xff, 0xc0, 0x03,
0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03,
};
static char cross_lbm[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01,
0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80,
0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
- 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x78, 0x1e, 0x00,
- 0xfc, 0x1f, 0xf8, 0x3f, 0xfc, 0x1f, 0xf8, 0x3f, 0x00, 0x78, 0x1e, 0x00, 0x00, 0x40, 0x02,
- 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80,
+ 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfe, 0x3f, 0xfc, 0x7f, 0xfe, 0x3f, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01,
+ 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80,
0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+
};
static char cross_lmsk[] = {
- 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01,
- 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80,
- 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
- 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00,
- 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01,
- 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80,
- 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
- 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00,
- 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00,
+ 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03,
+ 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0,
+ 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00,
+ 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xc0, 0x03,
+ 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0,
+ 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00,
+ 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00,
+ 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00,
};
static BCursor CrossCursor = {
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 6b4327d5f44..a744cfb8c28 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -2352,7 +2352,8 @@ static int wm_handler_fileselect_do(bContext *C,
U.file_space_data.temp_win_sizex * UI_DPI_FAC,
U.file_space_data.temp_win_sizey * UI_DPI_FAC,
SPACE_FILE,
- U.filebrowser_display_type))) {
+ U.filebrowser_display_type,
+ true))) {
ARegion *region_header = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
BLI_assert(area->spacetype == SPACE_FILE);
@@ -2737,7 +2738,10 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
/* Clear the tool-tip whenever a key binding is handled, without this tool-tips
* are kept when a modal operators starts (annoying but otherwise harmless). */
if (action & WM_HANDLER_BREAK) {
- WM_tooltip_clear(C, CTX_wm_window(C));
+ /* Window may be gone after file read. */
+ if (CTX_wm_window(C) != NULL) {
+ WM_tooltip_clear(C, CTX_wm_window(C));
+ }
}
}
else if (handler_base->type == WM_HANDLER_TYPE_UI) {
@@ -4210,19 +4214,31 @@ static void wm_eventemulation(wmEvent *event, bool test_only)
if (U.flag & USER_TWOBUTTONMOUSE) {
if (event->type == LEFTMOUSE) {
- if (event->val == KM_PRESS && event->alt) {
- event->type = MIDDLEMOUSE;
- event->alt = 0;
+ short *mod = (
+#if !defined(WIN32)
+ (U.mouse_emulate_3_button_modifier == USER_EMU_MMB_MOD_OSKEY) ? &event->oskey :
+ &event->alt
+#else
+ /* Disable for WIN32 for now because it accesses the start menu. */
+ &event->alt
+#endif
+ );
- if (!test_only) {
- emulating_event = MIDDLEMOUSE;
+ if (event->val == KM_PRESS) {
+ if (*mod) {
+ *mod = 0;
+ event->type = MIDDLEMOUSE;
+
+ if (!test_only) {
+ emulating_event = MIDDLEMOUSE;
+ }
}
}
else if (event->val == KM_RELEASE) {
/* only send middle-mouse release if emulated */
if (emulating_event == MIDDLEMOUSE) {
event->type = MIDDLEMOUSE;
- event->alt = 0;
+ *mod = 0;
}
if (!test_only) {
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 70d83153840..c8c35ba1bfc 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -99,6 +99,7 @@
#include "wm.h"
#include "wm_files.h"
#include "wm_window.h"
+#include "wm_platform_support.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -314,6 +315,10 @@ void WM_init(bContext *C, int argc, const char **argv)
#endif
WM_init_opengl(G_MAIN);
+ if (!WM_platform_support_perform_checks()) {
+ exit(-1);
+ }
+
UI_init();
}
diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c
index a8feb22cbf8..21636153904 100644
--- a/source/blender/windowmanager/intern/wm_operator_props.c
+++ b/source/blender/windowmanager/intern/wm_operator_props.c
@@ -396,6 +396,16 @@ void WM_operator_properties_select_operation_simple(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+void WM_operator_properties_generic_select(wmOperatorType *ot)
+{
+ PropertyRNA *prop = RNA_def_boolean(
+ ot->srna, "wait_to_deselect_others", false, "Wait to Deselect Others", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX);
+}
+
void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot)
{
WM_operator_properties_border(ot);
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 285379e90c6..292e27c3cbf 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -700,6 +700,82 @@ void WM_operator_properties_free(PointerRNA *ptr)
/** \name Default Operator Callbacks
* \{ */
+int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ PropertyRNA *wait_to_deselect_prop = RNA_struct_find_property(op->ptr,
+ "wait_to_deselect_others");
+ const short init_event_type = (short)POINTER_AS_INT(op->customdata);
+ int ret_value = 0;
+
+ /* get settings from RNA properties for operator */
+ int mval[2];
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
+
+ if (init_event_type == 0) {
+ if (event->val == KM_PRESS) {
+ RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, true);
+
+ ret_value = op->type->exec(C, op);
+ OPERATOR_RETVAL_CHECK(ret_value);
+
+ op->customdata = POINTER_FROM_INT((int)event->type);
+ if (ret_value & OPERATOR_RUNNING_MODAL) {
+ WM_event_add_modal_handler(C, op);
+ }
+ return ret_value | OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* If we are in init phase, and cannot validate init of modal operations,
+ * just fall back to basic exec.
+ */
+ RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, false);
+
+ ret_value = op->type->exec(C, op);
+ OPERATOR_RETVAL_CHECK(ret_value);
+
+ return ret_value | OPERATOR_PASS_THROUGH;
+ }
+ }
+ else if (event->type == init_event_type && event->val == KM_RELEASE) {
+ RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, false);
+
+ ret_value = op->type->exec(C, op);
+ OPERATOR_RETVAL_CHECK(ret_value);
+
+ return ret_value | OPERATOR_PASS_THROUGH;
+ }
+ else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ const int drag_delta[2] = {
+ mval[0] - event->mval[0],
+ mval[1] - event->mval[1],
+ };
+ /* If user moves mouse more than defined threshold, we consider select operator as
+ * finished. Otherwise, it is still running until we get an 'release' event. In any
+ * case, we pass through event, but select op is not finished yet. */
+ if (WM_event_drag_test_with_delta(event, drag_delta)) {
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* Important not to return anything other than PASS_THROUGH here,
+ * otherwise it prevents underlying tweak detection code to work properly. */
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+}
+
+int WM_generic_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
+ RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
+
+ op->customdata = POINTER_FROM_INT(0);
+
+ return op->type->modal(C, op, event);
+}
+
void WM_operator_view3d_unit_defaults(struct bContext *C, struct wmOperator *op)
{
if (op->flag & OP_IS_INVOKE) {
@@ -2621,38 +2697,38 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
}
else {
delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
- delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
+ delta[1] = 0.0f;
if (rc->zoom_prop) {
RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
delta[0] /= zoom[0];
- delta[1] /= zoom[1];
}
dist = len_v2(delta);
delta[0] = event->x - rc->slow_mouse[0];
- delta[1] = event->y - rc->slow_mouse[1];
if (rc->zoom_prop) {
delta[0] /= zoom[0];
- delta[1] /= zoom[1];
}
- dist = dist + 0.1f * (delta[0] + delta[1]);
+ dist = dist + 0.1f * (delta[0]);
}
}
else {
delta[0] = rc->initial_mouse[0] - event->x;
delta[1] = rc->initial_mouse[1] - event->y;
-
if (rc->zoom_prop) {
RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
delta[0] /= zoom[0];
delta[1] /= zoom[1];
}
-
- dist = len_v2(delta);
+ if (rc->subtype == PROP_ANGLE) {
+ dist = len_v2(delta);
+ }
+ else {
+ dist = clamp_f(-delta[0], 0.0f, FLT_MAX);
+ }
}
/* calculate new value and apply snapping */
diff --git a/source/blender/windowmanager/intern/wm_platform_support.c b/source/blender/windowmanager/intern/wm_platform_support.c
new file mode 100644
index 00000000000..94eceafc59b
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_platform_support.c
@@ -0,0 +1,219 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2019 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup wm
+ */
+#include "wm_platform_support.h"
+#include "wm_window_private.h"
+
+#include <string.h>
+
+#include "BLI_sys_types.h"
+#include "BLI_dynstr.h"
+#include "BLI_path_util.h"
+#include "BLI_fileops.h"
+#include "BLI_string.h"
+#include "BLI_linklist.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_appdir.h"
+#include "BKE_global.h"
+
+#include "GPU_platform.h"
+
+#include "GHOST_C-api.h"
+
+#define WM_PLATFORM_SUPPORT_TEXT_SIZE 1024
+
+/* Check if user has already approved the given platform_support_key. */
+static bool wm_platform_support_check_approval(const char *platform_support_key, bool update)
+{
+ const char *const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
+ bool result = false;
+
+ if (G.factory_startup) {
+ return result;
+ }
+
+ if (cfgdir) {
+ char filepath[FILE_MAX];
+ BLI_make_file_string("/", filepath, cfgdir, BLENDER_PLATFORM_SUPPORT_FILE);
+ LinkNode *lines = BLI_file_read_as_lines(filepath);
+ for (LinkNode *line_node = lines; line_node; line_node = line_node->next) {
+ char *line = line_node->link;
+ if (STREQ(line, platform_support_key)) {
+ result = true;
+ break;
+ }
+ }
+
+ if (!result && update) {
+ FILE *fp = BLI_fopen(filepath, "a");
+ if (fp) {
+ fprintf(fp, "%s\n", platform_support_key);
+ fclose(fp);
+ }
+ }
+
+ BLI_file_free_lines(lines);
+ }
+ return result;
+}
+
+static void wm_platform_support_create_link(char *link)
+{
+ DynStr *ds = BLI_dynstr_new();
+
+ BLI_dynstr_append(ds, "https://docs.blender.org/manual/en/dev/troubleshooting/gpu/");
+#if defined(_WIN32)
+ BLI_dynstr_append(ds, "windows/");
+#elif defined(__APPLE__)
+ BLI_dynstr_append(ds, "apple/");
+#else /* UNIX */
+ BLI_dynstr_append(ds, "linux/");
+#endif
+
+ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+ BLI_dynstr_append(ds, "intel.html");
+ }
+ else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+ BLI_dynstr_append(ds, "nvidia.html");
+ }
+ else if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+ BLI_dynstr_append(ds, "amd.html");
+ }
+ else {
+ BLI_dynstr_append(ds, "unknown.html");
+ }
+
+ BLI_assert(BLI_dynstr_get_len(ds) < WM_PLATFORM_SUPPORT_TEXT_SIZE);
+ BLI_dynstr_get_cstring_ex(ds, link);
+ BLI_dynstr_free(ds);
+}
+
+bool WM_platform_support_perform_checks()
+{
+ char title[WM_PLATFORM_SUPPORT_TEXT_SIZE];
+ char message[WM_PLATFORM_SUPPORT_TEXT_SIZE];
+ char link[WM_PLATFORM_SUPPORT_TEXT_SIZE];
+
+ bool result = true;
+
+ eGPUSupportLevel support_level = GPU_platform_support_level();
+ const char *platform_key = GPU_platform_support_level_key();
+
+ /* check if previous check matches the current check. Don't update the approval when running in
+ * `background`. this could have been triggered by installing addons via installers. */
+ if (support_level != GPU_SUPPORT_LEVEL_UNSUPPORTED && !G.factory_startup &&
+ wm_platform_support_check_approval(platform_key, !G.background)) {
+ /* if it matches the user has confirmed and whishes to use it */
+ return result;
+ }
+
+ /* update the message and link based on the found support level */
+ GHOST_DialogOptions dialog_options = 0;
+
+ switch (support_level) {
+ default:
+ case GPU_SUPPORT_LEVEL_SUPPORTED:
+ break;
+
+ case GPU_SUPPORT_LEVEL_LIMITED: {
+ size_t slen = 0;
+ STR_CONCAT(title, slen, "Blender - ");
+ STR_CONCAT(
+ title, slen, CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "Limited Platform Support"));
+ slen = 0;
+ STR_CONCAT(
+ message,
+ slen,
+ CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER,
+ "Your graphics card or driver has limited support. It may work, but with "
+ "issues."));
+
+ /* TODO: Extra space is needed for the split function in GHOST_SystemX11. We should change
+ * the behavior in GHOST_SystemX11. */
+ STR_CONCAT(message, slen, "\n \n");
+ STR_CONCAT(
+ message,
+ slen,
+ CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER,
+ "Newer graphics drivers may be available to improve Blender support."));
+ STR_CONCAT(message, slen, "\n \n");
+ STR_CONCAT(message, slen, CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "Graphics card:\n"));
+ STR_CONCAT(message, slen, GPU_platform_gpu_name());
+
+ dialog_options = GHOST_DialogWarning;
+ break;
+ }
+
+ case GPU_SUPPORT_LEVEL_UNSUPPORTED: {
+ size_t slen = 0;
+ STR_CONCAT(title, slen, "Blender - ");
+ STR_CONCAT(
+ title, slen, CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "Platform Unsupported"));
+ slen = 0;
+ STR_CONCAT(message,
+ slen,
+ CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER,
+ "Your graphics card or driver is not supported."));
+
+ STR_CONCAT(message, slen, "\n \n");
+ STR_CONCAT(
+ message,
+ slen,
+ CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER,
+ "Newer graphics drivers may be available to improve Blender support."));
+
+ STR_CONCAT(message, slen, "\n \n");
+ STR_CONCAT(message, slen, CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "Graphics card:\n"));
+ STR_CONCAT(message, slen, GPU_platform_gpu_name());
+ STR_CONCAT(message, slen, "\n \n");
+
+ STR_CONCAT(message,
+ slen,
+ CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "The program will now close."));
+ dialog_options = GHOST_DialogError;
+ result = false;
+ break;
+ }
+ }
+ wm_platform_support_create_link(link);
+
+ bool show_message = ELEM(
+ support_level, GPU_SUPPORT_LEVEL_LIMITED, GPU_SUPPORT_LEVEL_UNSUPPORTED);
+
+ /* We are running in the background print the message in the console. */
+ if ((G.background || G.debug & G_DEBUG) && show_message) {
+ printf("%s\n\n%s\n%s\n", title, message, link);
+ }
+ if (G.background) {
+ /* Don't show the message-box when running in background mode.
+ * Printing to console is enough. */
+ result = true;
+ }
+ else if (show_message) {
+ WM_ghost_show_message_box(
+ title, message, "Find Latest Drivers", "Continue Anyway", link, dialog_options);
+ }
+
+ return result;
+}
diff --git a/source/blender/windowmanager/intern/wm_platform_support.h b/source/blender/windowmanager/intern/wm_platform_support.h
new file mode 100644
index 00000000000..a8e20f6bcdf
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_platform_support.h
@@ -0,0 +1,30 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2019 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup wm
+ */
+#ifndef __WM_PLATFORM_SUPPORT_H__
+#define __WM_PLATFORM_SUPPORT_H__
+
+#include "BLI_sys_types.h"
+
+bool WM_platform_support_perform_checks(void);
+
+#endif
diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c
index d3f7661a008..662238b4ae1 100644
--- a/source/blender/windowmanager/intern/wm_splash_screen.c
+++ b/source/blender/windowmanager/intern/wm_splash_screen.c
@@ -178,68 +178,79 @@ static void wm_block_splash_add_labels(uiBlock *block, int x, int y)
#endif /* WITH_BUILDINFO */
}
-static ImBuf *wm_block_splash_image(void)
+static ImBuf *wm_block_splash_image(int r_unit_size[2])
{
#ifndef WITH_HEADLESS
extern char datatoc_splash_png[];
extern int datatoc_splash_png_size;
extern char datatoc_splash_2x_png[];
extern int datatoc_splash_2x_png_size;
+ const bool is_2x = U.dpi_fac > 1.0;
+ const int imb_scale = is_2x ? 2 : 1;
- ImBuf *ibuf = NULL;
+ /* We could allow this to be variable,
+ * for now don't since allowing it might create layout issues.
+ *
+ * Only check width because splashes sometimes change height
+ * and we don't want to break app-templates. */
+ const int x_expect = 501 * imb_scale;
- if (U.dpi_fac > 1.0) {
- ibuf = IMB_ibImageFromMemory((const uchar *)datatoc_splash_2x_png,
- datatoc_splash_2x_png_size,
- IB_rect,
- NULL,
- "<splash screen>");
- }
- else {
- ibuf = IMB_ibImageFromMemory((const uchar *)datatoc_splash_png,
- datatoc_splash_png_size,
- IB_rect,
- NULL,
- "<splash screen>");
- }
+ ImBuf *ibuf = NULL;
- /* overwrite splash with template image */
if (U.app_template[0] != '\0') {
- ImBuf *ibuf_template = NULL;
char splash_filepath[FILE_MAX];
char template_directory[FILE_MAX];
-
if (BKE_appdir_app_template_id_search(
U.app_template, template_directory, sizeof(template_directory))) {
BLI_join_dirfile(splash_filepath,
sizeof(splash_filepath),
template_directory,
- (U.dpi_fac > 1.0) ? "splash_2x.png" : "splash.png");
- ibuf_template = IMB_loadiffname(splash_filepath, IB_rect, NULL);
- if (ibuf_template) {
- const int x_expect = ibuf->x;
- const int y_expect = 250 * (int)U.dpi_fac;
- /* don't cover the header text */
- if (ibuf_template->x == x_expect && ibuf_template->y == y_expect) {
- memcpy(ibuf->rect,
- ibuf_template->rect,
- ibuf_template->x * ibuf_template->y * sizeof(char[4]));
- }
- else {
- CLOG_ERROR(WM_LOG_OPERATORS,
- "Splash expected %dx%d found %dx%d, ignoring: %s\n",
- x_expect,
- y_expect,
- ibuf_template->x,
- ibuf_template->y,
- splash_filepath);
- }
- IMB_freeImBuf(ibuf_template);
+ is_2x ? "splash_2x.png" : "splash.png");
+ ibuf = IMB_loadiffname(splash_filepath, IB_rect, NULL);
+
+ /* We could skip this check, see comment about 'x_expect' above. */
+ if (ibuf->x != x_expect) {
+ CLOG_ERROR(WM_LOG_OPERATORS,
+ "Splash expected %d width found %d, ignoring: %s\n",
+ x_expect,
+ ibuf->x,
+ splash_filepath);
+ IMB_freeImBuf(ibuf);
+ ibuf = NULL;
}
}
}
+
+ if (ibuf == NULL) {
+ const uchar *splash_data;
+ size_t splash_data_size;
+
+ if (is_2x) {
+ splash_data = (const uchar *)datatoc_splash_2x_png;
+ splash_data_size = datatoc_splash_2x_png_size;
+ }
+ else {
+ splash_data = (const uchar *)datatoc_splash_png;
+ splash_data_size = datatoc_splash_png_size;
+ }
+
+ ibuf = IMB_ibImageFromMemory(splash_data, splash_data_size, IB_rect, NULL, "<splash screen>");
+
+ BLI_assert(ibuf->x == x_expect);
+ }
+
+ if (is_2x) {
+ r_unit_size[0] = ibuf->x / 2;
+ r_unit_size[1] = ibuf->y / 2;
+ }
+ else {
+ r_unit_size[0] = ibuf->x;
+ r_unit_size[1] = ibuf->y;
+ }
+
return ibuf;
#else
+ UNUSED_VARS(r_unit_size);
return NULL;
#endif
}
@@ -258,15 +269,17 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_KEEP_OPEN | UI_BLOCK_NO_WIN_CLIP);
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
- ImBuf *ibuf = wm_block_splash_image();
+ /* Size before dpi scaling (halved for hi-dpi image). */
+ int ibuf_unit_size[2];
+ ImBuf *ibuf = wm_block_splash_image(ibuf_unit_size);
but = uiDefBut(block,
UI_BTYPE_IMAGE,
0,
"",
0,
0.5f * U.widget_unit,
- U.dpi_fac * 501,
- U.dpi_fac * 250,
+ U.dpi_fac * ibuf_unit_size[0],
+ U.dpi_fac * ibuf_unit_size[1],
/* Button owns the imbuf now. */
ibuf,
0.0,
@@ -277,17 +290,18 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
UI_but_func_set(but, wm_block_splash_close, block, NULL);
UI_block_func_set(block, wm_block_splash_refreshmenu, block, NULL);
- int x = U.dpi_fac * 502;
- int y = U.dpi_fac * 237;
+ int x = U.dpi_fac * (ibuf_unit_size[0] + 1);
+ int y = U.dpi_fac * (ibuf_unit_size[1] - 13);
wm_block_splash_add_labels(block, x, y);
+ const int layout_margin_x = U.dpi_fac * 26;
uiLayout *layout = UI_block_layout(block,
UI_LAYOUT_VERTICAL,
UI_LAYOUT_PANEL,
- U.dpi_fac * 26,
+ layout_margin_x,
0,
- U.dpi_fac * 450,
+ (U.dpi_fac * ibuf_unit_size[0]) - (layout_margin_x * 2),
U.dpi_fac * 110,
0,
style);
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 2c26a15dce0..fa2320585d7 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -61,7 +61,9 @@
#include "wm.h"
#include "wm_draw.h"
#include "wm_files.h"
+#include "wm_platform_support.h"
#include "wm_window.h"
+#include "wm_window_private.h"
#include "wm_event_system.h"
#include "ED_anim_api.h"
@@ -78,7 +80,7 @@
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
#include "GPU_draw.h"
-#include "GPU_extensions.h"
+#include "GPU_platform.h"
#include "GPU_framebuffer.h"
#include "GPU_init_exit.h"
#include "GPU_immediate.h"
@@ -409,8 +411,10 @@ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
/* this is event from ghost, or exit-blender op */
void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
{
- /* First check if there is another main window remaining. */
wmWindow *win_other;
+ const bool is_dialog = GHOST_IsDialogWindow(win->ghostwin);
+
+ /* First check if there is another main window remaining. */
for (win_other = wm->windows.first; win_other; win_other = win_other->next) {
if (win_other != win && win_other->parent == NULL && !WM_window_is_temp_screen(win_other)) {
break;
@@ -422,10 +426,15 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
return;
}
- /* close child windows */
- for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) {
- if (win_child->parent == win) {
- wm_window_close(C, wm, win_child);
+ /* Close child windows and bring windows back to front that dialogs have pushed behind the main
+ * window. */
+ for (wmWindow *iter_win = wm->windows.first; iter_win; iter_win = iter_win->next) {
+ if (iter_win->parent == win) {
+ wm_window_close(C, wm, iter_win);
+ }
+ else if (is_dialog && iter_win != win && iter_win->parent &&
+ (GHOST_GetWindowState(iter_win->ghostwin) != GHOST_kWindowStateMinimized)) {
+ wm_window_raise(iter_win);
}
}
@@ -547,7 +556,10 @@ static void wm_window_ensure_eventstate(wmWindow *win)
}
/* belongs to below */
-static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wmWindow *win)
+static void wm_window_ghostwindow_add(wmWindowManager *wm,
+ const char *title,
+ wmWindow *win,
+ bool is_dialog)
{
GHOST_WindowHandle ghostwin;
GHOST_GLSettings glSettings = {0};
@@ -569,15 +581,29 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
wmWindow *prev_windrawable = wm->windrawable;
wm_window_clear_drawable(wm);
- ghostwin = GHOST_CreateWindow(g_system,
- title,
- win->posx,
- posy,
- win->sizex,
- win->sizey,
- (GHOST_TWindowState)win->windowstate,
- GHOST_kDrawingContextTypeOpenGL,
- glSettings);
+ if (is_dialog && win->parent) {
+ ghostwin = GHOST_CreateDialogWindow(g_system,
+ win->parent->ghostwin,
+ title,
+ win->posx,
+ posy,
+ win->sizex,
+ win->sizey,
+ (GHOST_TWindowState)win->windowstate,
+ GHOST_kDrawingContextTypeOpenGL,
+ glSettings);
+ }
+ else {
+ ghostwin = GHOST_CreateWindow(g_system,
+ title,
+ win->posx,
+ posy,
+ win->sizex,
+ win->sizey,
+ (GHOST_TWindowState)win->windowstate,
+ GHOST_kDrawingContextTypeOpenGL,
+ glSettings);
+ }
if (ghostwin) {
GHOST_RectangleHandle bounds;
@@ -635,6 +661,68 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
}
}
+static void wm_window_ghostwindow_ensure(wmWindowManager *wm, wmWindow *win, bool is_dialog)
+{
+ wmKeyMap *keymap;
+
+ if (win->ghostwin == NULL) {
+ if ((win->sizex == 0) || (wm_init_state.override_flag & WIN_OVERRIDE_GEOM)) {
+ win->posx = wm_init_state.start_x;
+ win->posy = wm_init_state.start_y;
+ win->sizex = wm_init_state.size_x;
+ win->sizey = wm_init_state.size_y;
+
+ if (wm_init_state.override_flag & WIN_OVERRIDE_GEOM) {
+ win->windowstate = GHOST_kWindowStateNormal;
+ wm_init_state.override_flag &= ~WIN_OVERRIDE_GEOM;
+ }
+ else {
+ win->windowstate = GHOST_WINDOW_STATE_DEFAULT;
+ }
+ }
+
+ if (wm_init_state.override_flag & WIN_OVERRIDE_WINSTATE) {
+ win->windowstate = wm_init_state.windowstate;
+ wm_init_state.override_flag &= ~WIN_OVERRIDE_WINSTATE;
+ }
+
+ /* without this, cursor restore may fail, T45456 */
+ if (win->cursor == 0) {
+ win->cursor = WM_CURSOR_DEFAULT;
+ }
+
+ wm_window_ghostwindow_add(wm, "Blender", win, is_dialog);
+ }
+
+ if (win->ghostwin != NULL) {
+ /* If we have no ghostwin this is a buggy window that should be removed.
+ * However we still need to initialize it correctly so the screen doesn't hang. */
+
+ /* happens after fileread */
+ wm_window_ensure_eventstate(win);
+ }
+
+ /* add keymap handlers (1 handler for all keys in map!) */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Window", 0, 0);
+ WM_event_add_keymap_handler(&win->handlers, keymap);
+
+ keymap = WM_keymap_ensure(wm->defaultconf, "Screen", 0, 0);
+ WM_event_add_keymap_handler(&win->handlers, keymap);
+
+ keymap = WM_keymap_ensure(wm->defaultconf, "Screen Editing", 0, 0);
+ WM_event_add_keymap_handler(&win->modalhandlers, keymap);
+
+ /* add drop boxes */
+ {
+ ListBase *lb = WM_dropboxmap_find("Window", 0, 0);
+ WM_event_add_dropbox_handler(&win->handlers, lb);
+ }
+ wm_window_title(wm, win);
+
+ /* add topbar */
+ ED_screen_global_areas_refresh(win);
+}
+
/**
* Initialize #wmWindow without ghostwin, open these and clear.
*
@@ -650,9 +738,6 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
*/
void wm_window_ghostwindows_ensure(wmWindowManager *wm)
{
- wmKeyMap *keymap;
- wmWindow *win;
-
BLI_assert(G.background == false);
/* No command-line prefsize? then we set this.
@@ -682,63 +767,8 @@ void wm_window_ghostwindows_ensure(wmWindowManager *wm)
#endif
}
- for (win = wm->windows.first; win; win = win->next) {
- if (win->ghostwin == NULL) {
- if ((win->sizex == 0) || (wm_init_state.override_flag & WIN_OVERRIDE_GEOM)) {
- win->posx = wm_init_state.start_x;
- win->posy = wm_init_state.start_y;
- win->sizex = wm_init_state.size_x;
- win->sizey = wm_init_state.size_y;
-
- if (wm_init_state.override_flag & WIN_OVERRIDE_GEOM) {
- win->windowstate = GHOST_kWindowStateNormal;
- wm_init_state.override_flag &= ~WIN_OVERRIDE_GEOM;
- }
- else {
- win->windowstate = GHOST_WINDOW_STATE_DEFAULT;
- }
- }
-
- if (wm_init_state.override_flag & WIN_OVERRIDE_WINSTATE) {
- win->windowstate = wm_init_state.windowstate;
- wm_init_state.override_flag &= ~WIN_OVERRIDE_WINSTATE;
- }
-
- /* without this, cursor restore may fail, T45456 */
- if (win->cursor == 0) {
- win->cursor = WM_CURSOR_DEFAULT;
- }
-
- wm_window_ghostwindow_add(wm, "Blender", win);
- }
-
- if (win->ghostwin != NULL) {
- /* If we have no ghostwin this is a buggy window that should be removed.
- * However we still need to initialize it correctly so the screen doesn't hang. */
-
- /* happens after fileread */
- wm_window_ensure_eventstate(win);
- }
-
- /* add keymap handlers (1 handler for all keys in map!) */
- keymap = WM_keymap_ensure(wm->defaultconf, "Window", 0, 0);
- WM_event_add_keymap_handler(&win->handlers, keymap);
-
- keymap = WM_keymap_ensure(wm->defaultconf, "Screen", 0, 0);
- WM_event_add_keymap_handler(&win->handlers, keymap);
-
- keymap = WM_keymap_ensure(wm->defaultconf, "Screen Editing", 0, 0);
- WM_event_add_keymap_handler(&win->modalhandlers, keymap);
-
- /* add drop boxes */
- {
- ListBase *lb = WM_dropboxmap_find("Window", 0, 0);
- WM_event_add_dropbox_handler(&win->handlers, lb);
- }
- wm_window_title(wm, win);
-
- /* add topbar */
- ED_screen_global_areas_refresh(win);
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ wm_window_ghostwindow_ensure(wm, win, false);
}
}
@@ -795,10 +825,17 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect)
* \param space_type: SPACE_VIEW3D, SPACE_INFO, ... (eSpace_Type)
* \return the window or NULL in case of failure.
*/
-wmWindow *WM_window_open_temp(
- bContext *C, const char *title, int x, int y, int sizex, int sizey, int space_type)
+wmWindow *WM_window_open_temp(bContext *C,
+ const char *title,
+ int x,
+ int y,
+ int sizex,
+ int sizey,
+ int space_type,
+ bool dialog)
{
Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win_prev = CTX_wm_window(C);
wmWindow *win;
bScreen *screen;
@@ -823,9 +860,10 @@ wmWindow *WM_window_open_temp(
/* changes rect to fit within desktop */
wm_window_check_position(&rect);
- /* test if we have a temp screen already */
- for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) {
- if (WM_window_is_temp_screen(win)) {
+ /* Reuse temporary or dialog window if one is open (but don't use a dialog for a regular
+ * temporary window, or vice versa). */
+ for (win = wm->windows.first; win; win = win->next) {
+ if (WM_window_is_temp_screen(win) && (dialog == GHOST_IsDialogWindow(win->ghostwin))) {
break;
}
}
@@ -843,11 +881,6 @@ wmWindow *WM_window_open_temp(
win->sizex = BLI_rcti_size_x(&rect);
win->sizey = BLI_rcti_size_y(&rect);
- if (win->ghostwin) {
- wm_window_set_size(win, win->sizex, win->sizey);
- wm_window_raise(win);
- }
-
if (WM_window_get_active_workspace(win) == NULL) {
WorkSpace *workspace = WM_window_get_active_workspace(win_prev);
BKE_workspace_active_set(win->workspace_hook, workspace);
@@ -872,6 +905,9 @@ wmWindow *WM_window_open_temp(
/* make window active, and validate/resize */
CTX_wm_window_set(C, win);
+ if (!win->ghostwin) {
+ wm_window_ghostwindow_ensure(wm, win, dialog);
+ }
WM_check(C);
/* It's possible `win->ghostwin == NULL`.
@@ -887,15 +923,18 @@ wmWindow *WM_window_open_temp(
ED_area_newspace(C, sa, space_type, false);
ED_screen_change(C, screen);
- ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */
+ ED_screen_refresh(wm, win); /* test scale */
if (win->ghostwin) {
+ wm_window_set_size(win, win->sizex, win->sizey);
+ wm_window_raise(win);
+
GHOST_SetTitle(win->ghostwin, title);
return win;
}
else {
/* very unlikely! but opening a new window can fail */
- wm_window_close(C, CTX_wm_manager(C), win);
+ wm_window_close(C, wm, win);
CTX_wm_window_set(C, win_prev);
return NULL;
@@ -2394,4 +2433,14 @@ void WM_opengl_context_release(void *context)
GHOST_ReleaseOpenGLContext((GHOST_ContextHandle)context);
}
+void WM_ghost_show_message_box(const char *title,
+ const char *message,
+ const char *help_label,
+ const char *continue_label,
+ const char *link,
+ GHOST_DialogOptions dialog_options)
+{
+ BLI_assert(g_system);
+ GHOST_ShowMessageBox(g_system, title, message, help_label, continue_label, link, dialog_options);
+}
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_window_private.h b/source/blender/windowmanager/intern/wm_window_private.h
new file mode 100644
index 00000000000..115539861d7
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_window_private.h
@@ -0,0 +1,42 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2019 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup wm
+ */
+#ifndef __WM_WINDOW_PRIVATE_H__
+#define __WM_WINDOW_PRIVATE_H__
+
+#include "BLI_sys_types.h"
+#include "GHOST_Types.h"
+
+/* *************** Message box *************** */
+/* `WM_ghost_show_message_box` is implemented in `wm_windows.c` it is
+ * defined here as it was implemented to be used for showing
+ * a message to the user when the platform is not (fully) supported.
+ *
+ * In all other cases this message box should not be used. */
+void WM_ghost_show_message_box(const char *title,
+ const char *message,
+ const char *help_label,
+ const char *continue_label,
+ const char *link,
+ GHOST_DialogOptions dialog_options);
+
+#endif
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 8fb4d2905f4..4da1d61a4f1 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -513,6 +513,16 @@ if(UNIX AND NOT APPLE)
DESTINATION "."
)
+ if(EXISTS ${LIBDIR}/mesa)
+ install(DIRECTORY ${LIBDIR}/mesa/lib DESTINATION ".")
+
+ install(
+ PROGRAMS
+ ${CMAKE_SOURCE_DIR}/release/bin/blender-softwaregl
+ DESTINATION "."
+ )
+ endif()
+
set(BLENDER_TEXT_FILES_DESTINATION ".")
else()
# main blender binary
@@ -674,6 +684,13 @@ elseif(WIN32)
set(BLENDER_TEXT_FILES_DESTINATION ".")
+ if(WITH_OPENMP AND MSVC_CLANG)
+ install(
+ FILES ${CLANG_OPENMP_DLL}
+ DESTINATION "."
+ )
+ endif()
+
if(WITH_PYTHON)
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
diff --git a/source/tools b/source/tools
-Subproject 7b740545cd039ddcadbfb9bffcac842476eee27
+Subproject d8c4ae2c23a36d9609d47142dc72f243551258f
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 7d8a1390628..94b6e49181c 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -4,6 +4,7 @@
#
# Getting the install path of the executable is somewhat involved, as there are
# no direct CMake generator expressions to get the install paths of executables.
+get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(GENERATOR_IS_MULTI_CONFIG)
string(REPLACE "\${BUILD_TYPE}" "$<CONFIG>" TEST_INSTALL_DIR ${CMAKE_INSTALL_PREFIX})
else()
diff --git a/tests/gtests/blenlib/BLI_delaunay_2d_test.cc b/tests/gtests/blenlib/BLI_delaunay_2d_test.cc
index 315e5804784..8b29128eb0d 100644
--- a/tests/gtests/blenlib/BLI_delaunay_2d_test.cc
+++ b/tests/gtests/blenlib/BLI_delaunay_2d_test.cc
@@ -667,6 +667,32 @@ TEST(delaunay, TriCutoff)
BLI_delaunay_2d_cdt_free(out);
}
+TEST(delaunay, TriInTri)
+{
+ CDT_input in;
+ CDT_result *out;
+ float p[][2] = {
+ {-5.65685f, 0.0f},
+ {1.41421f, -5.83095f},
+ {0.0f, 0.0f},
+ {-2.47487f, -1.45774f},
+ {-0.707107f, -2.91548f},
+ {-1.06066f, -1.45774f},
+ };
+ int f[] = {0, 1, 2, 3, 4, 5};
+ int fstart[] = {0, 3};
+ int flen[] = {3, 3};
+
+ fill_input_verts(&in, p, 6);
+ add_input_faces(&in, f, fstart, flen, 2);
+ out = BLI_delaunay_2d_cdt_calc(&in, CDT_CONSTRAINTS_VALID_BMESH);
+ EXPECT_EQ(out->verts_len, 6);
+ EXPECT_EQ(out->edges_len, 8);
+ EXPECT_EQ(out->faces_len, 3);
+ BLI_delaunay_2d_cdt_free(out);
+}
+
+#if 0
enum {
RANDOM_PTS,
RANDOM_SEGS,
@@ -739,12 +765,12 @@ static void rand_delaunay_test(int test_kind,
times[lg_size] += PIL_check_seconds_timer() - tstart;
}
}
-#ifdef DO_TIMING
+# ifdef DO_TIMING
fprintf(stderr, "size,time\n");
for (lg_size = 0; lg_size <= max_lg_size; lg_size++) {
fprintf(stderr, "%d,%f\n", 1 << lg_size, times[lg_size] / reps_per_size);
}
-#endif
+# endif
MEM_freeN(p);
if (e)
MEM_freeN(e);
@@ -781,6 +807,7 @@ TEST(delaunay, randompoly_validbmesh)
{
rand_delaunay_test(RANDOM_POLY, 7, 1, CDT_CONSTRAINTS_VALID_BMESH);
}
+#endif
#if 0
/* For debugging or timing large examples.
diff --git a/tests/gtests/blenlib/BLI_memiter_test.cc b/tests/gtests/blenlib/BLI_memiter_test.cc
index c1c07dc7540..d92daefff3b 100644
--- a/tests/gtests/blenlib/BLI_memiter_test.cc
+++ b/tests/gtests/blenlib/BLI_memiter_test.cc
@@ -17,7 +17,7 @@ TEST(memiter, Nop)
BLI_memiter_destroy(mi);
}
-void memiter_empty_test(int num_elems, const int chunk_size)
+static void memiter_empty_test(int num_elems, const int chunk_size)
{
BLI_memiter *mi = BLI_memiter_create(chunk_size);
void *data;
@@ -39,7 +39,7 @@ void memiter_empty_test(int num_elems, const int chunk_size)
}
#define MEMITER_NUMBER_TEST_FN(fn, number_type) \
- void fn(int num_elems, const int chunk_size) \
+ static void fn(int num_elems, const int chunk_size) \
{ \
BLI_memiter *mi = BLI_memiter_create(chunk_size); \
number_type *data; \
@@ -65,7 +65,7 @@ MEMITER_NUMBER_TEST_FN(memiter_short_test, short)
MEMITER_NUMBER_TEST_FN(memiter_int_test, int)
MEMITER_NUMBER_TEST_FN(memiter_long_test, int64_t)
-void memiter_string_test(const char *strings[], const int chunk_size)
+static void memiter_string_test(const char *strings[], const int chunk_size)
{
BLI_memiter *mi = BLI_memiter_create(chunk_size);
char *data;
@@ -95,7 +95,7 @@ void memiter_string_test(const char *strings[], const int chunk_size)
BLI_memiter_destroy(mi);
}
-void memiter_words10k_test(const char split_char, const int chunk_size)
+static void memiter_words10k_test(const char split_char, const int chunk_size)
{
const int words_len = sizeof(words10k) - 1;
char *words = BLI_strdupn(words10k, words_len);