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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt5
-rwxr-xr-xbuild_files/build_environment/install_deps.sh16
-rw-r--r--build_files/config/pipeline_config.yaml18
-rw-r--r--doc/doxygen/Doxyfile2
-rw-r--r--intern/cycles/blender/curves.cpp64
-rw-r--r--intern/cycles/device/hip/device_impl.cpp4
-rw-r--r--intern/cycles/integrator/shader_eval.cpp2
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.cpp5
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm2
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp34
-rw-r--r--intern/ghost/intern/GHOST_XrContext.cpp11
-rw-r--r--intern/ghost/intern/GHOST_XrContext.h1
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h10
-rw-r--r--intern/locale/CMakeLists.txt1
-rw-r--r--release/datafiles/splash.pngbin1026292 -> 842492 bytes
-rw-r--r--release/scripts/modules/rna_manual_reference.py1
-rw-r--r--release/scripts/modules/rna_xml.py30
-rw-r--r--release/scripts/startup/bl_operators/wm.py66
-rw-r--r--release/scripts/startup/bl_ui/space_nla.py3
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py8
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py1
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py2
-rw-r--r--release/scripts/startup/nodeitems_builtins.py2
-rw-r--r--source/blender/blendthumb/CMakeLists.txt1
-rw-r--r--source/blender/blenfont/BLF_api.h2
-rw-r--r--source/blender/blenfont/CMakeLists.txt4
-rw-r--r--source/blender/blenfont/intern/blf_default.c6
-rw-r--r--source/blender/blenfont/intern/blf_font.c59
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c49
-rw-r--r--source/blender/blenfont/intern/blf_internal.h20
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h6
-rw-r--r--source/blender/blenfont/intern/blf_thumbs.c7
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h72
-rw-r--r--source/blender/blenkernel/BKE_action.h1
-rw-r--r--source/blender/blenkernel/BKE_armature.h8
-rw-r--r--source/blender/blenkernel/BKE_attribute_math.hh26
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h6
-rw-r--r--source/blender/blenkernel/BKE_collection.h4
-rw-r--r--source/blender/blenkernel/BKE_constraint.h12
-rw-r--r--source/blender/blenkernel/BKE_image_partial_update.hh4
-rw-r--r--source/blender/blenkernel/BKE_lib_id.h4
-rw-r--r--source/blender/blenkernel/BKE_lib_override.h12
-rw-r--r--source/blender/blenkernel/BKE_lib_query.h3
-rw-r--r--source/blender/blenkernel/BKE_lib_remap.h9
-rw-r--r--source/blender/blenkernel/BKE_modifier.h4
-rw-r--r--source/blender/blenkernel/BKE_node.h2
-rw-r--r--source/blender/blenkernel/BKE_object.h22
-rw-r--r--source/blender/blenkernel/CMakeLists.txt5
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc192
-rw-r--r--source/blender/blenkernel/intern/action.c19
-rw-r--r--source/blender/blenkernel/intern/armature.c167
-rw-r--r--source/blender/blenkernel/intern/armature_update.c58
-rw-r--r--source/blender/blenkernel/intern/attribute.c8
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc17
-rw-r--r--source/blender/blenkernel/intern/attribute_access_intern.hh3
-rw-r--r--source/blender/blenkernel/intern/blendfile.c26
-rw-r--r--source/blender/blenkernel/intern/blendfile_link_append.c83
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c43
-rw-r--r--source/blender/blenkernel/intern/constraint.c47
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c13
-rw-r--r--source/blender/blenkernel/intern/customdata.cc14
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c3
-rw-r--r--source/blender/blenkernel/intern/fcurve_driver.c20
-rw-r--r--source/blender/blenkernel/intern/hair.cc193
-rw-r--r--source/blender/blenkernel/intern/image_partial_update.cc7
-rw-r--r--source/blender/blenkernel/intern/image_partial_update_test.cc2
-rw-r--r--source/blender/blenkernel/intern/lib_id.c65
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c10
-rw-r--r--source/blender/blenkernel/intern/lib_override.c151
-rw-r--r--source/blender/blenkernel/intern/lib_override_proxy_conversion.c176
-rw-r--r--source/blender/blenkernel/intern/lib_query.c4
-rw-r--r--source/blender/blenkernel/intern/lib_remap.c41
-rw-r--r--source/blender/blenkernel/intern/mesh.cc11
-rw-r--r--source/blender/blenkernel/intern/mesh_iterators.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_merge.c13
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c11
-rw-r--r--source/blender/blenkernel/intern/modifier.c4
-rw-r--r--source/blender/blenkernel/intern/node.cc19
-rw-r--r--source/blender/blenkernel/intern/object.cc276
-rw-r--r--source/blender/blenkernel/intern/object_update.c39
-rw-r--r--source/blender/blenkernel/intern/particle.c2
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c171
-rw-r--r--source/blender/blenkernel/intern/type_conversions.cc64
-rw-r--r--source/blender/blenlib/BLI_enumerable_thread_specific.hh2
-rw-r--r--source/blender/blenlib/BLI_string_ref.hh16
-rw-r--r--source/blender/blenlib/intern/math_geom.c4
-rw-r--r--source/blender/blenlib/intern/math_interp.c4
-rw-r--r--source/blender/blenloader/BLO_readfile.h2
-rw-r--r--source/blender/blenloader/CMakeLists.txt4
-rw-r--r--source/blender/blenloader/intern/readblenentry.c3
-rw-r--r--source/blender/blenloader/intern/readfile.c19
-rw-r--r--source/blender/blenloader/intern/readfile.h8
-rw-r--r--source/blender/blenloader/intern/versioning_290.c4
-rw-r--r--source/blender/blentranslation/BLT_translation.h24
-rw-r--r--source/blender/bmesh/CMakeLists.txt4
-rw-r--r--source/blender/bmesh/tools/bmesh_boolean.cc4
-rw-r--r--source/blender/compositor/CMakeLists.txt8
-rw-r--r--source/blender/compositor/intern/COM_Converter.cc8
-rw-r--r--source/blender/compositor/nodes/COM_CombineXYZNode.cc55
-rw-r--r--source/blender/compositor/nodes/COM_CombineXYZNode.h36
-rw-r--r--source/blender/compositor/nodes/COM_SeparateXYZNode.cc63
-rw-r--r--source/blender/compositor/nodes/COM_SeparateXYZNode.h36
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc35
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc68
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc46
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc61
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline_from_ids.cc22
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline_from_ids.h5
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc6
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc24
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.cc7
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.h2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.cc2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.h1
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c7
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c2
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl8
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_data.c2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c2
-rw-r--r--source/blender/draw/engines/image/image_drawing_mode.hh23
-rw-r--r--source/blender/draw/engines/image/image_texture_info.hh4
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.c48
-rw-r--r--source/blender/draw/engines/overlay/overlay_fade.c1
-rw-r--r--source/blender/draw/engines/overlay/overlay_volume.c1
-rw-r--r--source/blender/draw/engines/workbench/shaders/infos/workbench_effect_cavity_info.hh14
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl4
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl6
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_cavity.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader_shared.h2
-rw-r--r--source/blender/draw/intern/DRW_gpu_wrapper.hh28
-rw-r--r--source/blender/draw/intern/DRW_render.h59
-rw-r--r--source/blender/draw/intern/draw_cache_impl_hair.cc71
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c4
-rw-r--r--source/blender/draw/intern/draw_cache_impl_subdivision.cc4
-rw-r--r--source/blender/draw/intern/draw_manager.h30
-rw-r--r--source/blender/draw/intern/draw_manager_data.c97
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c14
-rw-r--r--source/blender/draw/intern/draw_shader_shared.h4
-rw-r--r--source/blender/draw/intern/draw_view_data.h2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc13
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc2
-rw-r--r--source/blender/draw/intern/shaders/common_fxaa_lib.glsl2
-rw-r--r--source/blender/draw/intern/shaders/common_subdiv_lib.glsl2
-rw-r--r--source/blender/draw/intern/shaders/draw_hair_refine_info.hh2
-rw-r--r--source/blender/draw/intern/shaders/draw_view_info.hh4
-rw-r--r--source/blender/editors/animation/CMakeLists.txt4
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c2
-rw-r--r--source/blender/editors/armature/CMakeLists.txt4
-rw-r--r--source/blender/editors/armature/armature_add.c9
-rw-r--r--source/blender/editors/armature/armature_intern.h7
-rw-r--r--source/blender/editors/armature/armature_select.c81
-rw-r--r--source/blender/editors/armature/pose_edit.c34
-rw-r--r--source/blender/editors/armature/pose_group.c4
-rw-r--r--source/blender/editors/armature/pose_select.c4
-rw-r--r--source/blender/editors/asset/CMakeLists.txt1
-rw-r--r--source/blender/editors/asset/intern/asset_ops.cc10
-rw-r--r--source/blender/editors/curve/CMakeLists.txt4
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c17
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt4
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c2
-rw-r--r--source/blender/editors/include/ED_armature.h11
-rw-r--r--source/blender/editors/include/ED_node.h13
-rw-r--r--source/blender/editors/include/ED_view3d.h22
-rw-r--r--source/blender/editors/include/UI_interface.h2
-rw-r--r--source/blender/editors/interface/interface.c5
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c17
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c38
-rw-r--r--source/blender/editors/interface/interface_eyedropper_colorband.c34
-rw-r--r--source/blender/editors/interface/interface_eyedropper_datablock.c30
-rw-r--r--source/blender/editors/interface/interface_eyedropper_depth.c30
-rw-r--r--source/blender/editors/interface/interface_eyedropper_gpencil_color.c8
-rw-r--r--source/blender/editors/interface/interface_eyedropper_intern.h4
-rw-r--r--source/blender/editors/interface/interface_handlers.c9
-rw-r--r--source/blender/editors/interface/interface_ops.c5
-rw-r--r--source/blender/editors/interface/interface_style.c18
-rw-r--r--source/blender/editors/interface/interface_templates.c81
-rw-r--r--source/blender/editors/io/CMakeLists.txt4
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt4
-rw-r--r--source/blender/editors/mesh/editmesh_select.c35
-rw-r--r--source/blender/editors/metaball/CMakeLists.txt1
-rw-r--r--source/blender/editors/metaball/mball_edit.c14
-rw-r--r--source/blender/editors/object/CMakeLists.txt4
-rw-r--r--source/blender/editors/object/object_add.c12
-rw-r--r--source/blender/editors/object/object_constraint.c15
-rw-r--r--source/blender/editors/object/object_data_transfer.c6
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_modifier.c4
-rw-r--r--source/blender/editors/object/object_ops.c1
-rw-r--r--source/blender/editors/object/object_relations.c59
-rw-r--r--source/blender/editors/object/object_vgroup.c42
-rw-r--r--source/blender/editors/physics/CMakeLists.txt4
-rw-r--r--source/blender/editors/render/CMakeLists.txt4
-rw-r--r--source/blender/editors/render/render_internal.cc4
-rw-r--r--source/blender/editors/render/render_opengl.cc9
-rw-r--r--source/blender/editors/render/render_preview.cc2
-rw-r--r--source/blender/editors/scene/CMakeLists.txt3
-rw-r--r--source/blender/editors/screen/CMakeLists.txt4
-rw-r--r--source/blender/editors/screen/screen_ops.c11
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c2
-rw-r--r--source/blender/editors/space_action/action_edit.c2
-rw-r--r--source/blender/editors/space_buttons/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_clip/CMakeLists.txt5
-rw-r--r--source/blender/editors/space_file/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_file/filelist.c2
-rw-r--r--source/blender/editors/space_file/fsmenu.c9
-rw-r--r--source/blender/editors/space_graph/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_graph/graph_edit.c2
-rw-r--r--source/blender/editors/space_graph/graph_slider_ops.c2
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_image/image_undo.c2
-rw-r--r--source/blender/editors/space_info/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_nla/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_node/node_intern.hh75
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.cc3
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.hh15
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.cc82
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.cc28
-rw-r--r--source/blender/editors/space_sequencer/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_spreadsheet/space_spreadsheet.cc2
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_layout.cc22
-rw-r--r--source/blender/editors/space_text/CMakeLists.txt3
-rw-r--r--source/blender/editors/space_text/text_draw.c33
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c11
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt15
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c4189
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c128
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h146
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate.c1593
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate.h282
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_dolly.c337
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_fly.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_move.c188
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_ndof.c661
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_roll.c292
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_rotate.c452
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_smoothview.c406
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_walk.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_zoom.c598
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_zoom_border.c221
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c168
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c428
-rw-r--r--source/blender/editors/transform/CMakeLists.txt4
-rw-r--r--source/blender/editors/transform/transform.h4
-rw-r--r--source/blender/editors/transform/transform_convert.h6
-rw-r--r--source/blender/editors/transform/transform_convert_armature.c78
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c33
-rw-r--r--source/blender/editors/undo/CMakeLists.txt4
-rw-r--r--source/blender/editors/util/CMakeLists.txt4
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt4
-rw-r--r--source/blender/freestyle/CMakeLists.txt4
-rw-r--r--source/blender/functions/FN_field.hh5
-rw-r--r--source/blender/functions/intern/cpp_types.cc2
-rw-r--r--source/blender/functions/intern/field.cc13
-rw-r--r--source/blender/gpencil_modifiers/CMakeLists.txt4
-rw-r--r--source/blender/gpu/CMakeLists.txt2
-rw-r--r--source/blender/gpu/GPU_select.h31
-rw-r--r--source/blender/gpu/GPU_shader.h2
-rw-r--r--source/blender/gpu/GPU_shader_shared.h2
-rw-r--r--source/blender/gpu/GPU_shader_shared_utils.h (renamed from source/blender/gpu/intern/gpu_shader_shared_utils.h)0
-rw-r--r--source/blender/gpu/GPU_state.h13
-rw-r--r--source/blender/gpu/GPU_texture.h3
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c6
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.cc2
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer_private.hh5
-rw-r--r--source/blender/gpu/intern/gpu_select.c44
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c206
-rw-r--r--source/blender/gpu/intern/gpu_select_private.h7
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.cc49
-rw-r--r--source/blender/gpu/intern/gpu_shader.cc92
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.cc83
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.hh248
-rw-r--r--source/blender/gpu/intern/gpu_shader_dependency.cc65
-rw-r--r--source/blender/gpu/intern/gpu_shader_dependency_private.h31
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.hh1
-rw-r--r--source/blender/gpu/intern/gpu_shader_log.cc108
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.hh1
-rw-r--r--source/blender/gpu/opengl/gl_backend.cc6
-rw-r--r--source/blender/gpu/opengl/gl_context.hh2
-rw-r--r--source/blender/gpu/opengl/gl_framebuffer.hh2
-rw-r--r--source/blender/gpu/opengl/gl_shader.cc250
-rw-r--r--source/blender/gpu/opengl/gl_shader.hh8
-rw-r--r--source/blender/gpu/opengl/gl_shader_interface.cc30
-rw-r--r--source/blender/gpu/opengl/gl_shader_log.cc9
-rw-r--r--source/blender/gpu/opengl/gl_state.hh13
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl2
-rw-r--r--source/blender/io/collada/CMakeLists.txt4
-rw-r--r--source/blender/io/usd/intern/usd_reader_camera.cc2
-rw-r--r--source/blender/io/usd/intern/usd_writer_material.cc12
-rw-r--r--source/blender/io/wavefront_obj/CMakeLists.txt6
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc240
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh84
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_io.hh94
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc35
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh32
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_exporter.cc110
-rw-r--r--source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc38
-rw-r--r--source/blender/makesdna/DNA_action_types.h5
-rw-r--r--source/blender/makesdna/DNA_armature_types.h2
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h2
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h8
-rw-r--r--source/blender/makesdna/DNA_hair_types.h85
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h4
-rw-r--r--source/blender/makesdna/DNA_node_types.h9
-rw-r--r--source/blender/makesdna/DNA_object_types.h7
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesdna/intern/makesdna.c12
-rw-r--r--source/blender/makesrna/RNA_access.h15
-rw-r--r--source/blender/makesrna/RNA_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_ID.c15
-rw-r--r--source/blender/makesrna/intern/rna_armature.c11
-rw-r--r--source/blender/makesrna/intern/rna_asset.c2
-rw-r--r--source/blender/makesrna/intern/rna_attribute.c60
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c8
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c2
-rw-r--r--source/blender/makesrna/intern/rna_hair.c152
-rw-r--r--source/blender/makesrna/intern/rna_image.c2
-rw-r--r--source/blender/makesrna/intern/rna_internal.h5
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c4
-rw-r--r--source/blender/makesrna/intern/rna_object.c13
-rw-r--r--source/blender/makesrna/intern/rna_pose.c4
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c7
-rw-r--r--source/blender/makesrna/intern/rna_wm.c3
-rw-r--r--source/blender/modifiers/CMakeLists.txt4
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c1
-rw-r--r--source/blender/modifiers/intern/MOD_array.c1
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c1
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.cc1
-rw-r--r--source/blender/modifiers/intern/MOD_build.c1
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c1
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c1
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c1
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c1
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c1
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c1
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c1
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c1
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c1
-rw-r--r--source/blender/modifiers/intern/MOD_fluid.c1
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c1
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c1
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c1
-rw-r--r--source/blender/modifiers/intern/MOD_mask.cc1
-rw-r--r--source/blender/modifiers/intern/MOD_mesh_to_volume.cc1
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache.c1
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c1
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c1
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c1
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c1
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc152
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.cc2
-rw-r--r--source/blender/modifiers/intern/MOD_none.c1
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c3
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c1
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c1
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c1
-rw-r--r--source/blender/modifiers/intern/MOD_remesh.c1
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c30
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c1
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c1
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c1
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c1
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_softbody.c1
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c1
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c1
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c1
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c1
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c1
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c1
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c4
-rw-r--r--source/blender/modifiers/intern/MOD_volume_displace.cc1
-rw-r--r--source/blender/modifiers/intern/MOD_volume_to_mesh.cc1
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c1
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weld.cc1
-rw-r--r--source/blender/modifiers/intern/MOD_wireframe.c1
-rw-r--r--source/blender/nodes/CMakeLists.txt4
-rw-r--r--source/blender/nodes/NOD_composite.h2
-rw-r--r--source/blender/nodes/NOD_static_types.h2
-rw-r--r--source/blender/nodes/composite/CMakeLists.txt5
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcomb_xyz.cc71
-rw-r--r--source/blender/nodes/function/CMakeLists.txt4
-rw-r--r--source/blender/nodes/geometry/CMakeLists.txt4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_triangulate.cc2
-rw-r--r--source/blender/nodes/shader/CMakeLists.txt4
-rw-r--r--source/blender/nodes/texture/CMakeLists.txt3
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.c2
-rw-r--r--source/blender/render/CMakeLists.txt4
-rw-r--r--source/blender/render/RE_texture.h2
-rw-r--r--source/blender/render/intern/multires_bake.c34
-rw-r--r--source/blender/render/intern/texture_margin.cc49
-rw-r--r--source/blender/sequencer/intern/strip_add.c2
-rw-r--r--source/blender/shader_fx/CMakeLists.txt4
-rw-r--r--source/blender/windowmanager/CMakeLists.txt4
-rw-r--r--source/blender/windowmanager/WM_types.h4
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c4
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c38
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c49
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c4
-rw-r--r--source/blender/windowmanager/intern/wm_files.c30
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c2
-rw-r--r--source/blender/windowmanager/intern/wm_window.c8
-rw-r--r--source/blender/windowmanager/wm_event_system.h1
-rw-r--r--source/blender/windowmanager/wm_event_types.h4
-rw-r--r--source/creator/CMakeLists.txt7
-rw-r--r--tests/python/CMakeLists.txt7
-rw-r--r--tests/python/bl_keymap_validate.py2
-rw-r--r--tests/python/bl_rigging_symmetrize.py244
444 files changed, 9529 insertions, 8865 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f73149adc04..21a398e31a4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -157,8 +157,9 @@ option(WITH_BLENDER "Build blender (disable to build only the blender player)" O
mark_as_advanced(WITH_BLENDER)
if(APPLE)
- # Currently this causes a build error linking, disable.
- set(WITH_BLENDER_THUMBNAILER OFF)
+ # In future, can be used with `quicklookthumbnailing/qlthumbnailreply` to create file
+ # thumbnails for say Finder. Turn it off for now.
+ option(WITH_BLENDER_THUMBNAILER "Build \"blender-thumbnailer\" thumbnail extraction utility" OFF)
elseif(WIN32)
option(WITH_BLENDER_THUMBNAILER "Build \"BlendThumb.dll\" helper for Windows explorer integration" ON)
else()
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index 03a75468400..75c0b3c0009 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -4036,14 +4036,14 @@ install_DEB() {
INFO "Forced Python building, as requested..."
_do_compile_python=true
else
- check_package_version_ge_lt_DEB python3-dev $PYTHON_VERSION_MIN $PYTHON_VERSION_MEX
+ check_package_version_ge_lt_DEB python${PYTHON_VERSION_SHORT}-dev $PYTHON_VERSION_MIN $PYTHON_VERSION_MEX
if [ $? -eq 0 ]; then
- PYTHON_VERSION_INSTALLED=$(echo `get_package_version_DEB python3-dev` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
-
- install_packages_DEB python3-dev
+ install_packages_DEB python${PYTHON_VERSION_SHORT}-dev
clean_Python
PRINT ""
+ PYTHON_VERSION_INSTALLED=$(echo `get_package_version_DEB python${PYTHON_VERSION_SHORT}-dev` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
+
for module in "${PYTHON_MODULES_PACKAGES[@]}"
do
module=($module)
@@ -4681,11 +4681,11 @@ install_RPM() {
else
check_package_version_ge_lt_RPM python3-devel $PYTHON_VERSION_MIN $PYTHON_VERSION_MEX
if [ $? -eq 0 ]; then
- PYTHON_VERSION_INSTALLED=$(echo `get_package_version_RPM python3-devel` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
-
install_packages_RPM python3-devel
clean_Python
+ PYTHON_VERSION_INSTALLED=$(echo `get_package_version_RPM python3-devel` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
+
for module in "${PYTHON_MODULES_PACKAGES[@]}"
do
module=($module)
@@ -5224,12 +5224,12 @@ install_ARCH() {
else
check_package_version_ge_lt_ARCH python $PYTHON_VERSION_MIN $PYTHON_VERSION_MEX
if [ $? -eq 0 ]; then
- PYTHON_VERSION_INSTALLED=$(echo `get_package_version_ARCH python` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
-
install_packages_ARCH python
clean_Python
PRINT ""
+ PYTHON_VERSION_INSTALLED=$(echo `get_package_version_ARCH python` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
+
for module in "${PYTHON_MODULES_PACKAGES[@]}"
do
module=($module)
diff --git a/build_files/config/pipeline_config.yaml b/build_files/config/pipeline_config.yaml
index 5f85d232dce..8222f2ff0b9 100644
--- a/build_files/config/pipeline_config.yaml
+++ b/build_files/config/pipeline_config.yaml
@@ -5,38 +5,38 @@
update-code:
git:
submodules:
- - branch: blender-v3.1-release
+ - branch: master
commit_id: HEAD
path: release/scripts/addons
- - branch: blender-v3.1-release
+ - branch: master
commit_id: HEAD
path: release/scripts/addons_contrib
- - branch: blender-v3.1-release
+ - branch: master
commit_id: HEAD
path: release/datafiles/locale
- - branch: blender-v3.1-release
+ - branch: master
commit_id: HEAD
path: source/tools
svn:
libraries:
darwin-arm64:
- branch: tags/blender-3.1-release
+ branch: trunk
commit_id: HEAD
path: lib/darwin_arm64
darwin-x86_64:
- branch: tags/blender-3.1-release
+ branch: trunk
commit_id: HEAD
path: lib/darwin
linux-x86_64:
- branch: tags/blender-3.1-release
+ branch: trunk
commit_id: HEAD
path: lib/linux_centos7_x86_64
windows-amd64:
- branch: tags/blender-3.1-release
+ branch: trunk
commit_id: HEAD
path: lib/win64_vc15
tests:
- branch: tags/blender-3.1-release
+ branch: trunk
commit_id: HEAD
path: lib/tests
benchmarks:
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile
index 89954d8a155..2f004491c89 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 = V3.1
+PROJECT_NUMBER = V3.2
# 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/intern/cycles/blender/curves.cpp b/intern/cycles/blender/curves.cpp
index 65a02d041cc..4206a1d8a8b 100644
--- a/intern/cycles/blender/curves.cpp
+++ b/intern/cycles/blender/curves.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <optional>
+
#include "blender/sync.h"
#include "blender/util.h"
@@ -625,14 +627,35 @@ void BlenderSync::sync_particle_hair(
}
#ifdef WITH_HAIR_NODES
-static float4 hair_point_as_float4(BL::HairPoint b_point)
+
+static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Hair b_hair)
+{
+ for (BL::Attribute &b_attribute : b_hair.attributes) {
+ if (b_attribute.name() != "radius") {
+ continue;
+ }
+ if (b_attribute.domain() != BL::Attribute::domain_POINT) {
+ continue;
+ }
+ if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
+ continue;
+ }
+ return BL::FloatAttribute{b_attribute};
+ }
+ return std::nullopt;
+}
+
+static float4 hair_point_as_float4(BL::Hair b_hair,
+ std::optional<BL::FloatAttribute> b_attr_radius,
+ const int index)
{
- float4 mP = float3_to_float4(get_float3(b_point.co()));
- mP.w = b_point.radius();
+ float4 mP = float3_to_float4(get_float3(b_hair.position_data[index].vector()));
+ mP.w = b_attr_radius ? b_attr_radius->data[index].value() : 0.0f;
return mP;
}
static float4 interpolate_hair_points(BL::Hair b_hair,
+ std::optional<BL::FloatAttribute> b_attr_radius,
const int first_point_index,
const int num_points,
const float step)
@@ -641,8 +664,8 @@ static float4 interpolate_hair_points(BL::Hair b_hair,
const int point_a = clamp((int)curve_t, 0, num_points - 1);
const int point_b = min(point_a + 1, num_points - 1);
const float t = curve_t - (float)point_a;
- return lerp(hair_point_as_float4(b_hair.points[first_point_index + point_a]),
- hair_point_as_float4(b_hair.points[first_point_index + point_b]),
+ return lerp(hair_point_as_float4(b_hair, b_attr_radius, first_point_index + point_a),
+ hair_point_as_float4(b_hair, b_attr_radius, first_point_index + point_b),
t);
}
@@ -671,12 +694,14 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
hair->reserve_curves(num_curves, num_keys);
+ std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_hair);
+
/* Export curves and points. */
vector<float> points_length;
- for (BL::HairCurve &b_curve : b_hair.curves) {
- const int first_point_index = b_curve.first_point_index();
- const int num_points = b_curve.num_points();
+ for (int i = 0; i < num_curves; i++) {
+ const int first_point_index = b_hair.curve_offset_data[i].value();
+ const int num_points = b_hair.curve_offset_data[i + 1].value() - first_point_index;
float3 prev_co = zero_float3();
float length = 0.0f;
@@ -687,10 +712,9 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
/* Position and radius. */
for (int i = 0; i < num_points; i++) {
- BL::HairPoint b_point = b_hair.points[first_point_index + i];
-
- const float3 co = get_float3(b_point.co());
- const float radius = b_point.radius();
+ const float3 co = get_float3(b_hair.position_data[first_point_index + i].vector());
+ const float radius = b_attr_radius ? b_attr_radius->data[first_point_index + i].value() :
+ 0.0f;
hair->add_curve_key(co, radius);
if (attr_intercept) {
@@ -715,7 +739,7 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
/* Random number per curve. */
if (attr_random != NULL) {
- attr_random->add(hash_uint2_to_float(b_curve.index(), 0));
+ attr_random->add(hash_uint2_to_float(i, 0));
}
/* Curve. */
@@ -737,14 +761,17 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
/* Export motion keys. */
const int num_keys = hair->get_curve_keys().size();
+ const int num_curves = b_hair.curves.length();
float4 *mP = attr_mP->data_float4() + motion_step * num_keys;
bool have_motion = false;
int num_motion_keys = 0;
int curve_index = 0;
- for (BL::HairCurve &b_curve : b_hair.curves) {
- const int first_point_index = b_curve.first_point_index();
- const int num_points = b_curve.num_points();
+ std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_hair);
+
+ for (int i = 0; i < num_curves; i++) {
+ const int first_point_index = b_hair.curve_offset_data[i].value();
+ const int num_points = b_hair.curve_offset_data[i + 1].value() - first_point_index;
Hair::Curve curve = hair->get_curve(curve_index);
curve_index++;
@@ -755,7 +782,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
int point_index = first_point_index + i;
if (point_index < num_keys) {
- mP[num_motion_keys] = hair_point_as_float4(b_hair.points[point_index]);
+ mP[num_motion_keys] = hair_point_as_float4(b_hair, b_attr_radius, point_index);
num_motion_keys++;
if (!have_motion) {
@@ -774,7 +801,8 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
const float step_size = curve.num_keys > 1 ? 1.0f / (curve.num_keys - 1) : 0.0f;
for (int i = 0; i < curve.num_keys; i++) {
const float step = i * step_size;
- mP[num_motion_keys] = interpolate_hair_points(b_hair, first_point_index, num_points, step);
+ mP[num_motion_keys] = interpolate_hair_points(
+ b_hair, b_attr_radius, first_point_index, num_points, step);
num_motion_keys++;
}
have_motion = true;
diff --git a/intern/cycles/device/hip/device_impl.cpp b/intern/cycles/device/hip/device_impl.cpp
index 4f1cbabc89b..85ed3dc5b55 100644
--- a/intern/cycles/device/hip/device_impl.cpp
+++ b/intern/cycles/device/hip/device_impl.cpp
@@ -905,8 +905,8 @@ void HIPDevice::tex_alloc(device_texture &mem)
address_mode = hipAddressModeClamp;
break;
case EXTENSION_CLIP:
- // TODO : (Arya) setting this to Mode Clamp instead of Mode Border because it's unsupported
- // in hip
+ /* TODO(@arya): setting this to Mode Clamp instead of Mode Border
+ * because it's unsupported in HIP. */
address_mode = hipAddressModeClamp;
break;
default:
diff --git a/intern/cycles/integrator/shader_eval.cpp b/intern/cycles/integrator/shader_eval.cpp
index 95a1adeb016..0edd3810c39 100644
--- a/intern/cycles/integrator/shader_eval.cpp
+++ b/intern/cycles/integrator/shader_eval.cpp
@@ -157,7 +157,7 @@ bool ShaderEval::eval_gpu(Device *device,
queue->init_execution();
/* Execute work on GPU in chunk, so we can cancel.
- * TODO : query appropriate size from device.*/
+ * TODO: query appropriate size from device. */
const int32_t chunk_size = 65536;
device_ptr d_input = input.device_pointer;
diff --git a/intern/ghost/intern/GHOST_ImeWin32.cpp b/intern/ghost/intern/GHOST_ImeWin32.cpp
index d1fc80adf56..2a1bfb633b3 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.cpp
+++ b/intern/ghost/intern/GHOST_ImeWin32.cpp
@@ -96,7 +96,7 @@ bool GHOST_ImeWin32::IsEnglishMode()
!(conversion_modes_ & (IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE));
}
-bool GHOST_ImeWin32::IsImeKeyEvent(char ascii)
+bool GHOST_ImeWin32::IsImeKeyEvent(char ascii, GHOST_TKey key)
{
if (!(IsEnglishMode())) {
/* In Chinese, Japanese, Korean, all alpha keys are processed by IME. */
@@ -106,7 +106,8 @@ bool GHOST_ImeWin32::IsImeKeyEvent(char ascii)
if (IsLanguage(IMELANG_JAPANESE) && (ascii >= ' ' && ascii <= '~')) {
return true;
}
- else if (IsLanguage(IMELANG_CHINESE) && ascii && strchr("!\"$'(),.:;<>?[\\]^_`/", ascii)) {
+ else if (IsLanguage(IMELANG_CHINESE) && ascii && strchr("!\"$'(),.:;<>?[\\]^_`/", ascii) &&
+ !(key == GHOST_kKeyNumpadPeriod)) {
return true;
}
}
diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h
index ce0e4d64d53..d17a6d79503 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.h
+++ b/intern/ghost/intern/GHOST_ImeWin32.h
@@ -161,7 +161,7 @@ class GHOST_ImeWin32 {
bool IsEnglishMode();
/* Checks a key whether IME has to do handling. */
- bool IsImeKeyEvent(char ascii);
+ bool IsImeKeyEvent(char ascii, GHOST_TKey key);
/**
* Create the IME windows, and allocate required resources for them.
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index b92c3e73a88..756c4f876ed 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -890,7 +890,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
bool anyProcessed = false;
NSEvent *event;
- // TODO : implement timer ??
+ /* TODO: implement timer? */
#if 0
do {
GHOST_TimerManager* timerMgr = getTimerManager();
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 5251dd01b29..64e1ac3b9b3 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -1220,7 +1220,7 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
}
#ifdef WITH_INPUT_IME
- if (window->getImeInput()->IsImeKeyEvent(ascii)) {
+ if (window->getImeInput()->IsImeKeyEvent(ascii, key)) {
return NULL;
}
#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index b5d0fd8e6db..47d4ff77d17 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -71,6 +71,8 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_mousePresent(false),
m_inLiveResize(false),
m_system(system),
+ m_dropTarget(NULL),
+ m_hWnd(0),
m_hDC(0),
m_isDialog(dialog),
m_hasMouseCaptured(false),
@@ -78,6 +80,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_nPressedButtons(0),
m_customCursor(0),
m_wantAlphaBackground(alphaBackground),
+ m_Bar(NULL),
m_wintab(NULL),
m_lastPointerTabletData(GHOST_TABLET_DATA_NONE),
m_normal_state(GHOST_kWindowStateNormal),
@@ -129,8 +132,24 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_hDC = ::GetDC(m_hWnd);
if (!setDrawingContextType(type)) {
+ const char *title = "Blender - Unsupported Graphics Card Configuration";
+ const char *text =
+ "A graphics card and driver with support for OpenGL 3.3 or higher is "
+ "required.\n\nInstalling the latest driver for your graphics card might resolve the "
+ "issue.";
+ if (GetSystemMetrics(SM_CMONITORS) > 1) {
+ text =
+ "A graphics card and driver with support for OpenGL 3.3 or higher is "
+ "required.\n\nPlugging all monitors into your primary graphics card might resolve "
+ "this issue. Installing the latest driver for your graphics card could also help.";
+ }
+ MessageBox(m_hWnd, text, title, MB_OK | MB_ICONERROR);
+ ::ReleaseDC(m_hWnd, m_hDC);
::DestroyWindow(m_hWnd);
m_hWnd = NULL;
+ if (!parentwindow) {
+ exit(0);
+ }
return;
}
@@ -564,20 +583,13 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
(m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
- if (context->initializeDrawingContext()) {
- return context;
- }
- else {
- MessageBox(m_hWnd,
- "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);
+ if (context && !context->initializeDrawingContext()) {
delete context;
- exit(0);
+ context = nullptr;
}
+ return context;
+
#elif defined(WITH_GL_PROFILE_COMPAT)
// ask for 2.1 context, driver gives any GL version >= 2.1
// (hopefully the latest compatibility profile)
diff --git a/intern/ghost/intern/GHOST_XrContext.cpp b/intern/ghost/intern/GHOST_XrContext.cpp
index 15b40690d83..9fa93f0c4b4 100644
--- a/intern/ghost/intern/GHOST_XrContext.cpp
+++ b/intern/ghost/intern/GHOST_XrContext.cpp
@@ -86,6 +86,7 @@ void GHOST_XrContext::initialize(const GHOST_XrContextCreateInfo *create_info)
initApiLayers();
initExtensions();
if (isDebugMode()) {
+ printSDKVersion();
printAvailableAPILayersAndExtensionsInfo();
}
@@ -156,6 +157,16 @@ void GHOST_XrContext::storeInstanceProperties()
/** \name Debug Printing
* \{ */
+void GHOST_XrContext::printSDKVersion()
+{
+ const XrVersion sdk_version = XR_CURRENT_API_VERSION;
+
+ printf("OpenXR SDK Version: %u.%u.%u\n",
+ XR_VERSION_MAJOR(sdk_version),
+ XR_VERSION_MINOR(sdk_version),
+ XR_VERSION_PATCH(sdk_version));
+}
+
void GHOST_XrContext::printInstanceInfo()
{
assert(m_oxr->instance != XR_NULL_HANDLE);
diff --git a/intern/ghost/intern/GHOST_XrContext.h b/intern/ghost/intern/GHOST_XrContext.h
index 479b50e1537..b00f017ff59 100644
--- a/intern/ghost/intern/GHOST_XrContext.h
+++ b/intern/ghost/intern/GHOST_XrContext.h
@@ -126,6 +126,7 @@ class GHOST_XrContext : public GHOST_IXrContext {
void storeInstanceProperties();
void initDebugMessenger();
+ void printSDKVersion();
void printInstanceInfo();
void printAvailableAPILayersAndExtensionsInfo();
void printExtensionsAndAPILayersToEnable();
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
index 8a20323dcfc..dccb7a32139 100644
--- a/intern/guardedalloc/MEM_guardedalloc.h
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -39,8 +39,8 @@
* second intern/ module with MEM_ prefix, for use in c++.
*
* \subsection memdependencies Dependencies
- * - stdlib
- * - stdio
+ * - `stdlib`
+ * - `stdio`
*
* \subsection memdocs API Documentation
* See \ref MEM_guardedalloc.h
@@ -268,6 +268,12 @@ void MEM_use_guarded_allocator(void);
* Allocate new memory for and constructs an object of type #T.
* #MEM_delete should be used to delete the object. Just calling #MEM_freeN is not enough when #T
* is not a trivial type.
+ *
+ * Note that when no arguments are passed, C++ will do recursive member-wise value initialization.
+ * That is because C++ differentiates between creating an object with `T` (default initialization)
+ * and `T()` (value initialization), whereby this function does the latter. Value initialization
+ * rules are complex, but for C-style structs, memory will be zero-initialized. So this doesn't
+ * match a `malloc()`, but a `calloc()` call in this case. See https://stackoverflow.com/a/4982720.
*/
template<typename T, typename... Args>
inline T *MEM_new(const char *allocation_name, Args &&...args)
diff --git a/intern/locale/CMakeLists.txt b/intern/locale/CMakeLists.txt
index 732fa1e4d11..3e467302d8e 100644
--- a/intern/locale/CMakeLists.txt
+++ b/intern/locale/CMakeLists.txt
@@ -56,7 +56,6 @@ if(WITH_INTERNATIONAL)
list(APPEND LIB
${BOOST_LIBRARIES}
)
- add_definitions(-DWITH_INTERNATIONAL)
add_definitions(${BOOST_DEFINITIONS})
endif()
diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png
index 4e9d58f2ac9..eb1250cf5a5 100644
--- a/release/datafiles/splash.png
+++ b/release/datafiles/splash.png
Binary files differ
diff --git a/release/scripts/modules/rna_manual_reference.py b/release/scripts/modules/rna_manual_reference.py
index 0467e7b5788..232046ebd60 100644
--- a/release/scripts/modules/rna_manual_reference.py
+++ b/release/scripts/modules/rna_manual_reference.py
@@ -677,7 +677,6 @@ url_manual_mapping = (
("bpy.ops.gpencil.stroke_merge_by_distance*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-stroke-merge-by-distance"),
("bpy.ops.node.collapse_hide_unused_toggle*", "interface/controls/nodes/editing.html#bpy-ops-node-collapse-hide-unused-toggle"),
("bpy.ops.object.anim_transforms_to_deltas*", "scene_layout/object/editing/apply.html#bpy-ops-object-anim-transforms-to-deltas"),
- ("bpy.ops.object.convert_proxy_to_override*", "files/linked_libraries/library_overrides.html#bpy-ops-object-convert-proxy-to-override"),
("bpy.ops.object.modifier_copy_to_selected*", "modeling/modifiers/introduction.html#bpy-ops-object-modifier-copy-to-selected"),
("bpy.ops.preferences.app_template_install*", "advanced/app_templates.html#bpy-ops-preferences-app-template-install"),
("bpy.types.actionposemarkers.active_index*", "animation/armatures/properties/pose_library.html#bpy-types-actionposemarkers-active-index"),
diff --git a/release/scripts/modules/rna_xml.py b/release/scripts/modules/rna_xml.py
index 7f7b273c42b..aa8841c5efe 100644
--- a/release/scripts/modules/rna_xml.py
+++ b/release/scripts/modules/rna_xml.py
@@ -298,7 +298,7 @@ def xml2rna(
del value_xml_split
tp_name = 'ARRAY'
-# print(" %s.%s (%s) --- %s" % (type(value).__name__, attr, tp_name, subvalue_type))
+ # print(" %s.%s (%s) --- %s" % (type(value).__name__, attr, tp_name, subvalue_type))
try:
setattr(value, attr, value_xml_coerce)
except ValueError:
@@ -340,7 +340,6 @@ def xml2rna(
else:
# print(elems)
-
if len(elems) == 1:
# sub node named by its type
child_xml_real, = elems
@@ -376,7 +375,6 @@ def _get_context_val(context, path):
def xml_file_run(context, filepath, rna_map):
-
import xml.dom.minidom
xml_nodes = xml.dom.minidom.parse(filepath)
@@ -391,27 +389,25 @@ def xml_file_run(context, filepath, rna_map):
value = _get_context_val(context, rna_path)
if value is not Ellipsis and value is not None:
- print(" loading XML: %r -> %r" % (filepath, rna_path))
+ # print(" loading XML: %r -> %r" % (filepath, rna_path))
xml2rna(xml_node, root_rna=value)
def xml_file_write(context, filepath, rna_map, *, skip_typemap=None):
-
- file = open(filepath, "w", encoding="utf-8")
- fw = file.write
-
- fw("<bpy>\n")
-
- for rna_path, _xml_tag in rna_map:
- # xml_tag is ignored, we get this from the rna
- value = _get_context_val(context, rna_path)
- rna2xml(fw,
+ with open(filepath, "w", encoding="utf-8") as file:
+ fw = file.write
+ fw("<bpy>\n")
+
+ for rna_path, _xml_tag in rna_map:
+ # xml_tag is ignored, we get this from the rna
+ value = _get_context_val(context, rna_path)
+ rna2xml(
+ fw=fw,
root_rna=value,
method='ATTR',
root_ident=" ",
ident_val=" ",
skip_typemap=skip_typemap,
- )
+ )
- fw("</bpy>\n")
- file.close()
+ fw("</bpy>\n")
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index ce8bfa3b058..bb85ad8ca50 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -2961,93 +2961,75 @@ class WM_MT_splash_quick_setup(Menu):
bl_label = "Quick Setup"
def draw(self, context):
- wm = context.window_manager
- # prefs = context.preferences
-
layout = self.layout
-
layout.operator_context = 'EXEC_DEFAULT'
layout.label(text="Quick Setup")
- split = layout.split(factor=0.25)
+ split = layout.split(factor=0.14) # Left margin.
split.label()
- split = split.split(factor=2.0 / 3.0)
+ split = split.split(factor=0.73) # Content width.
col = split.column()
+ col.use_property_split = True
+ col.use_property_decorate = False
+
+ # Languages.
if bpy.app.build_options.international:
- sub = col.split(factor=0.35)
- row = sub.row()
- row.alignment = 'RIGHT'
- row.label(text="Language")
prefs = context.preferences
- sub.prop(prefs.view, "language", text="")
+ col.prop(prefs.view, "language")
+ col.separator()
- col.separator()
+ # Shortcuts.
+ wm = context.window_manager
+ kc = wm.keyconfigs.active
+ kc_prefs = kc.preferences
- sub = col.split(factor=0.35)
- row = sub.row()
- row.alignment = 'RIGHT'
- row.label(text="Shortcuts")
- text = bpy.path.display_name(wm.keyconfigs.active.name)
+ sub = col.column(heading="Shortcuts")
+ text = bpy.path.display_name(kc.name)
if not text:
text = "Blender"
sub.menu("USERPREF_MT_keyconfigs", text=text)
- kc = wm.keyconfigs.active
- kc_prefs = kc.preferences
has_select_mouse = hasattr(kc_prefs, "select_mouse")
if has_select_mouse:
- sub = col.split(factor=0.35)
- row = sub.row()
- row.alignment = 'RIGHT'
- row.label(text="Select With")
- sub.row().prop(kc_prefs, "select_mouse", expand=True)
- has_select_mouse = True
+ col.row().prop(kc_prefs, "select_mouse", text="Select With", expand=True)
has_spacebar_action = hasattr(kc_prefs, "spacebar_action")
if has_spacebar_action:
- sub = col.split(factor=0.35)
- row = sub.row()
- row.alignment = 'RIGHT'
- row.label(text="Spacebar")
- sub.row().prop(kc_prefs, "spacebar_action", expand=True)
- has_select_mouse = True
+ col.row().prop(kc_prefs, "spacebar_action", text="Spacebar")
col.separator()
- sub = col.split(factor=0.35)
- row = sub.row()
- row.alignment = 'RIGHT'
- row.label(text="Theme")
+ # Themes.
+ sub = col.column(heading="Theme")
label = bpy.types.USERPREF_MT_interface_theme_presets.bl_label
if label == "Presets":
label = "Blender Dark"
sub.menu("USERPREF_MT_interface_theme_presets", text=label)
- # Keep height constant
+ # Keep height constant.
if not has_select_mouse:
col.label()
if not has_spacebar_action:
col.label()
- layout.label()
+ layout.separator(factor=2.0)
- row = layout.row()
+ # Save settings buttons.
+ sub = layout.row()
- sub = row.row()
old_version = bpy.types.PREFERENCES_OT_copy_prev.previous_version()
if bpy.types.PREFERENCES_OT_copy_prev.poll(context) and old_version:
- sub.operator("preferences.copy_prev", text=iface_("Load %d.%d Settings", "Operator") % old_version)
+ sub.operator("preferences.copy_prev", text="Load %d.%d Settings" % old_version)
sub.operator("wm.save_userpref", text="Save New Settings")
else:
sub.label()
sub.label()
sub.operator("wm.save_userpref", text="Next")
- layout.separator()
- layout.separator()
+ layout.separator(factor=2.4)
class WM_MT_splash(Menu):
diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py
index 2db2b11a5f9..78c312fd03d 100644
--- a/release/scripts/startup/bl_ui/space_nla.py
+++ b/release/scripts/startup/bl_ui/space_nla.py
@@ -291,6 +291,9 @@ class NLA_MT_context_menu(Menu):
layout.separator()
+ props = layout.operator("wm.call_panel", text="Rename...")
+ props.name = "TOPBAR_PT_name"
+ props.keep_open = False
layout.operator("nla.duplicate", text="Duplicate").linked = False
layout.operator("nla.duplicate", text="Linked Duplicate").linked = True
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index 513c1c2ae2e..ce854155b88 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -832,6 +832,14 @@ class TOPBAR_PT_name(Panel):
row = row_with_icon(layout, 'NODE')
row.prop(item, "label", text="")
found = True
+ elif space_type == 'NLA_EDITOR':
+ layout.label(text="NLA Strip Name")
+ item = next(
+ (strip for strip in context.selected_nla_strips if strip.active), None)
+ if item:
+ row = row_with_icon(layout, 'NLA')
+ row.prop(item, "name", text="")
+ found = True
else:
if mode == 'POSE' or (mode == 'WEIGHT_PAINT' and context.pose_object):
layout.label(text="Bone Name")
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 0548486c786..78ef68e0bab 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -2316,7 +2316,6 @@ class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
context, (
({"property": "use_undo_legacy"}, "T60695"),
({"property": "override_auto_resync"}, "T83811"),
- ({"property": "proxy_to_override_auto_conversion"}, "T91671"),
({"property": "use_cycles_debug"}, None),
({"property": "use_geometry_nodes_legacy"}, "T91274"),
({"property": "show_asset_debug_info"}, None),
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 5eca606216e..03f5d7abe02 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2228,8 +2228,6 @@ class VIEW3D_MT_object_relations(Menu):
layout.operator("object.make_override_library", text="Make Library Override...")
- layout.operator("object.convert_proxy_to_override")
-
layout.operator("object.make_dupli_face")
layout.separator()
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index b841cb5dd13..4b48f5f0680 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -547,6 +547,8 @@ compositor_node_categories = [
NodeItem("CompositorNodeCombYUVA"),
NodeItem("CompositorNodeSepYCCA"),
NodeItem("CompositorNodeCombYCCA"),
+ NodeItem("CompositorNodeSeparateXYZ"),
+ NodeItem("CompositorNodeCombineXYZ"),
NodeItem("CompositorNodeSwitchView"),
NodeItem("CompositorNodeConvertColorSpace"),
]),
diff --git a/source/blender/blendthumb/CMakeLists.txt b/source/blender/blendthumb/CMakeLists.txt
index e2d278255ba..d64e942069d 100644
--- a/source/blender/blendthumb/CMakeLists.txt
+++ b/source/blender/blendthumb/CMakeLists.txt
@@ -65,6 +65,7 @@ else()
)
add_executable(blender-thumbnailer ${SRC} ${SRC_CMD})
+ setup_platform_linker_flags(blender-thumbnailer)
target_link_libraries(blender-thumbnailer bf_blenlib)
target_link_libraries(blender-thumbnailer ${PTHREADS_LIBRARIES})
endif()
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 169107b19cb..638c5b727a6 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -309,7 +309,7 @@ void BLF_thumb_preview(const char *filename,
/* blf_default.c */
void BLF_default_dpi(int dpi);
-void BLF_default_size(int size);
+void BLF_default_size(float size);
void BLF_default_set(int fontid);
/**
* Get default font ID so we can pass it to other functions.
diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt
index dd22bc2e7e0..5d04823cd0a 100644
--- a/source/blender/blenfont/CMakeLists.txt
+++ b/source/blender/blenfont/CMakeLists.txt
@@ -63,10 +63,6 @@ if(WIN32)
)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
list(APPEND INC
diff --git a/source/blender/blenfont/intern/blf_default.c b/source/blender/blenfont/intern/blf_default.c
index 57eeaa6768d..d5a0d514b5f 100644
--- a/source/blender/blenfont/intern/blf_default.c
+++ b/source/blender/blenfont/intern/blf_default.c
@@ -37,15 +37,15 @@
/* Default size and dpi, for BLF_draw_default. */
static int global_font_default = -1;
static int global_font_dpi = 72;
-/* Keep in sync with `UI_style_get()->widgetlabel.points` */
-static int global_font_size = 11;
+/* Keep in sync with `UI_DEFAULT_TEXT_POINTS` */
+static float global_font_size = 11.0f;
void BLF_default_dpi(int dpi)
{
global_font_dpi = dpi;
}
-void BLF_default_size(int size)
+void BLF_default_size(float size)
{
global_font_size = size;
}
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 14d3a208f69..c1410447de6 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -34,7 +34,6 @@
#include FT_FREETYPE_H
#include FT_GLYPH_H
-#include FT_ADVANCES_H /* For FT_Get_Advance */
#include "MEM_guardedalloc.h"
@@ -826,7 +825,10 @@ float blf_font_height(FontBLF *font,
float blf_font_fixed_width(FontBLF *font)
{
- return (float)font->fixed_width;
+ GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
+ float width = (gc) ? (float)gc->fixed_width : font->size / 2.0f;
+ blf_glyph_cache_release(font);
+ return width;
}
static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
@@ -1318,12 +1320,7 @@ FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int m
void blf_font_free(FontBLF *font)
{
- BLI_spin_lock(&blf_glyph_cache_mutex);
- GlyphCacheBLF *gc;
-
- while ((gc = BLI_pophead(&font->cache))) {
- blf_glyph_cache_free(gc);
- }
+ blf_glyph_cache_clear(font);
if (font->kerning_cache) {
MEM_freeN(font->kerning_cache);
@@ -1337,8 +1334,6 @@ void blf_font_free(FontBLF *font)
MEM_freeN(font->name);
}
MEM_freeN(font);
-
- BLI_spin_unlock(&blf_glyph_cache_mutex);
}
/** \} */
@@ -1347,51 +1342,25 @@ void blf_font_free(FontBLF *font)
/** \name Font Configure
* \{ */
-void blf_font_size(FontBLF *font, float size, unsigned int dpi)
+bool blf_font_size(FontBLF *font, float size, unsigned int dpi)
{
- blf_glyph_cache_acquire(font);
-
/* FreeType uses fixed-point integers in 64ths. */
FT_F26Dot6 ft_size = lroundf(size * 64.0f);
- /* Adjust our size to be on even 64ths. */
+ /* Adjust our new size to be on even 64ths. */
size = (float)ft_size / 64.0f;
- GlyphCacheBLF *gc = blf_glyph_cache_find(font, size, dpi);
- if (gc && (font->size == size && font->dpi == dpi)) {
- /* Optimization: do not call FT_Set_Char_Size if size did not change. */
- }
- else {
- const FT_Error err = FT_Set_Char_Size(font->face, 0, ft_size, dpi, dpi);
- if (err) {
- /* FIXME: here we can go through the fixed size and choice a close one */
- printf("The current font don't support the size, %f and dpi, %u\n", size, dpi);
- }
- else {
+ if (font->size != size || font->dpi != dpi) {
+ if (FT_Set_Char_Size(font->face, 0, ft_size, dpi, dpi) == 0) {
font->size = size;
font->dpi = dpi;
- if (gc == NULL) {
- blf_glyph_cache_new(font);
- }
+ }
+ else {
+ printf("The current font does not support the size, %f and dpi, %u\n", size, dpi);
+ return false;
}
}
- blf_glyph_cache_release(font);
-
- /* Set fixed-width size for monospaced output. */
- FT_UInt gindex = FT_Get_Char_Index(font->face, U'0');
- if (gindex) {
- FT_Fixed advance = 0;
- FT_Get_Advance(font->face, gindex, FT_LOAD_NO_HINTING, &advance);
- /* Use CSS 'ch unit' width, advance of zero character. */
- font->fixed_width = (int)(advance >> 16);
- }
- else {
- /* Font does not contain "0" so use CSS fallback of 1/2 of em. */
- font->fixed_width = (int)((font->face->size->metrics.height / 2) >> 6);
- }
- if (font->fixed_width < 1) {
- font->fixed_width = 1;
- }
+ return true;
}
/** \} */
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 4f25f99b65c..bcd9e1fb3a2 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -34,6 +34,7 @@
#include FT_GLYPH_H
#include FT_OUTLINE_H
#include FT_BITMAP_H
+#include FT_ADVANCES_H /* For FT_Get_Advance. */
#include "MEM_guardedalloc.h"
@@ -73,7 +74,7 @@ static FT_Fixed to_16dot16(double val)
/** \name Glyph Cache
* \{ */
-GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
+static GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
{
GlyphCacheBLF *gc = (GlyphCacheBLF *)font->cache.first;
while (gc) {
@@ -86,7 +87,7 @@ GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
return NULL;
}
-GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
+static GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
{
GlyphCacheBLF *gc = (GlyphCacheBLF *)MEM_callocN(sizeof(GlyphCacheBLF), "blf_glyph_cache_new");
@@ -100,6 +101,22 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table));
memset(gc->bucket, 0, sizeof(gc->bucket));
+ /* Determine ideal fixed-width size for monospaced output. */
+ FT_UInt gindex = FT_Get_Char_Index(font->face, U'0');
+ if (gindex) {
+ FT_Fixed advance = 0;
+ FT_Get_Advance(font->face, gindex, FT_LOAD_NO_HINTING, &advance);
+ /* Use CSS 'ch unit' width, advance of zero character. */
+ gc->fixed_width = (int)(advance >> 16);
+ }
+ else {
+ /* Font does not contain "0" so use CSS fallback of 1/2 of em. */
+ gc->fixed_width = (int)((font->face->size->metrics.height / 2) >> 6);
+ }
+ if (gc->fixed_width < 1) {
+ gc->fixed_width = 1;
+ }
+
BLI_addhead(&font->cache, gc);
return gc;
}
@@ -122,20 +139,7 @@ void blf_glyph_cache_release(FontBLF *font)
BLI_spin_unlock(font->glyph_cache_mutex);
}
-void blf_glyph_cache_clear(FontBLF *font)
-{
- GlyphCacheBLF *gc;
-
- BLI_spin_lock(font->glyph_cache_mutex);
-
- while ((gc = BLI_pophead(&font->cache))) {
- blf_glyph_cache_free(gc);
- }
-
- BLI_spin_unlock(font->glyph_cache_mutex);
-}
-
-void blf_glyph_cache_free(GlyphCacheBLF *gc)
+static void blf_glyph_cache_free(GlyphCacheBLF *gc)
{
GlyphBLF *g;
for (uint i = 0; i < ARRAY_SIZE(gc->bucket); i++) {
@@ -152,6 +156,19 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc)
MEM_freeN(gc);
}
+void blf_glyph_cache_clear(FontBLF *font)
+{
+ GlyphCacheBLF *gc;
+
+ BLI_spin_lock(font->glyph_cache_mutex);
+
+ while ((gc = BLI_pophead(&font->cache))) {
+ blf_glyph_cache_free(gc);
+ }
+
+ BLI_spin_unlock(font->glyph_cache_mutex);
+}
+
/**
* Try to find a glyph in cache.
*
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index 4e36f522981..d0bb3385e2c 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -56,7 +56,11 @@ struct FontBLF *blf_font_new(const char *name, const char *filename);
struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size);
void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, int mem_size);
-void blf_font_size(struct FontBLF *font, float size, unsigned int dpi);
+/**
+ * Change font's output size. Returns true if successful in changing the size.
+ */
+bool blf_font_size(struct FontBLF *font, float size, unsigned int dpi);
+
void blf_font_draw(struct FontBLF *font,
const char *str,
size_t str_len,
@@ -65,10 +69,7 @@ void blf_font_draw__wrap(struct FontBLF *font,
const char *str,
size_t str_len,
struct ResultBLF *r_info);
-void blf_font_draw_ascii(struct FontBLF *font,
- const char *str,
- size_t str_len,
- struct ResultBLF *r_info);
+
/**
* Use fixed column width, but an utf8 character may occupy multiple columns.
*/
@@ -137,18 +138,9 @@ int blf_font_count_missing_chars(struct FontBLF *font,
void blf_font_free(struct FontBLF *font);
-/**
- * Find a glyph cache that matches a size, DPI & styles.
- */
-struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font, float size, unsigned int dpi);
-/**
- * Create a new glyph cache for the current size, DPI & styles.
- */
-struct GlyphCacheBLF *blf_glyph_cache_new(struct FontBLF *font);
struct GlyphCacheBLF *blf_glyph_cache_acquire(struct FontBLF *font);
void blf_glyph_cache_release(struct FontBLF *font);
void blf_glyph_cache_clear(struct FontBLF *font);
-void blf_glyph_cache_free(struct GlyphCacheBLF *gc);
/**
* Create (or load from cache) a fully-rendered bitmap glyph.
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 46156edbb1f..c96febd71ae 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -73,6 +73,9 @@ typedef struct GlyphCacheBLF {
bool bold;
bool italic;
+ /* Column width when printing monospaced. */
+ int fixed_width;
+
/* and the glyphs. */
ListBase bucket[257];
@@ -207,9 +210,6 @@ typedef struct FontBLF {
/* font size. */
float size;
- /* Column width when printing monospaced. */
- int fixed_width;
-
/* max texture size. */
int tex_size_max;
diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c
index 06bbd0cf521..f666976547e 100644
--- a/source/blender/blenfont/intern/blf_thumbs.c
+++ b/source/blender/blenfont/intern/blf_thumbs.c
@@ -61,7 +61,6 @@ void BLF_thumb_preview(const char *filename,
int font_shrink = 4;
FontBLF *font;
- GlyphCacheBLF *gc;
/* Create a new blender font obj and fill it with default values */
font = blf_font_new("thumb_font", filename);
@@ -90,10 +89,8 @@ void BLF_thumb_preview(const char *filename,
const size_t draw_str_i18n_len = strlen(draw_str_i18n);
int draw_str_i18n_nbr = 0;
- blf_font_size(font, (float)MAX2(font_size_min, font_size_curr), dpi);
- gc = blf_glyph_cache_find(font, font->size, font->dpi);
- /* There will be no matching glyph cache if blf_font_size() failed to set font size. */
- if (!gc) {
+ CLAMP_MIN(font_size_curr, font_size_min);
+ if (!blf_font_size(font, (float)font_size_curr, dpi)) {
break;
}
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 1801c1ee1c9..4526bc38a70 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -104,14 +104,6 @@ typedef enum DerivedMeshType {
DM_TYPE_CCGDM,
} DerivedMeshType;
-typedef enum DMDirtyFlag {
- /* dm has valid tessellated faces, but tessellated CDDATA need to be updated. */
- DM_DIRTY_TESS_CDLAYERS = 1 << 0,
-
- /* check this with modifier dependsOnNormals callback to see if normals need recalculation */
- DM_DIRTY_NORMALS = 1 << 1,
-} DMDirtyFlag;
-
typedef struct DerivedMesh DerivedMesh;
struct DerivedMesh {
/** Private DerivedMesh data, only for internal DerivedMesh use */
@@ -120,7 +112,6 @@ struct DerivedMesh {
int needsFree; /* checked on ->release, is set to 0 for cached results */
int deformedOnly; /* set by modifier stack if only deformed from original */
DerivedMeshType type;
- DMDirtyFlag dirty;
/**
* \warning Typical access is done via #getLoopTriArray, #getNumLoopTri.
@@ -139,9 +130,6 @@ struct DerivedMesh {
short tangent_mask; /* which tangent layers are calculated */
- /** Calculate vert and face normals */
- void (*calcNormals)(DerivedMesh *dm);
-
/** Loop tessellation cache (WARNING! Only call inside threading-protected code!) */
void (*recalcLoopTri)(DerivedMesh *dm);
/** accessor functions */
@@ -164,7 +152,6 @@ struct DerivedMesh {
*/
struct MVert *(*getVertArray)(DerivedMesh *dm);
struct MEdge *(*getEdgeArray)(DerivedMesh *dm);
- struct MFace *(*getTessFaceArray)(DerivedMesh *dm);
struct MLoop *(*getLoopArray)(DerivedMesh *dm);
struct MPoly *(*getPolyArray)(DerivedMesh *dm);
@@ -173,7 +160,6 @@ struct DerivedMesh {
*/
void (*copyVertArray)(DerivedMesh *dm, struct MVert *r_vert);
void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *r_edge);
- void (*copyTessFaceArray)(DerivedMesh *dm, struct MFace *r_face);
void (*copyLoopArray)(DerivedMesh *dm, struct MLoop *r_loop);
void (*copyPolyArray)(DerivedMesh *dm, struct MPoly *r_poly);
@@ -182,37 +168,18 @@ struct DerivedMesh {
*/
struct MVert *(*dupVertArray)(DerivedMesh *dm);
struct MEdge *(*dupEdgeArray)(DerivedMesh *dm);
- struct MFace *(*dupTessFaceArray)(DerivedMesh *dm);
struct MLoop *(*dupLoopArray)(DerivedMesh *dm);
struct MPoly *(*dupPolyArray)(DerivedMesh *dm);
- /** Return a pointer to a single element of vert/edge/face custom data
- * from the derived mesh (this gives a pointer to the actual data, not
- * a copy)
- */
- void *(*getVertData)(DerivedMesh *dm, int index, int type);
- void *(*getEdgeData)(DerivedMesh *dm, int index, int type);
- void *(*getTessFaceData)(DerivedMesh *dm, int index, int type);
- void *(*getPolyData)(DerivedMesh *dm, int index, int type);
-
/** Return a pointer to the entire array of vert/edge/face custom data
* from the derived mesh (this gives a pointer to the actual data, not
* a copy)
*/
void *(*getVertDataArray)(DerivedMesh *dm, int type);
void *(*getEdgeDataArray)(DerivedMesh *dm, int type);
- void *(*getTessFaceDataArray)(DerivedMesh *dm, int type);
void *(*getLoopDataArray)(DerivedMesh *dm, int type);
void *(*getPolyDataArray)(DerivedMesh *dm, int type);
- /** Retrieves the base CustomData structures for
- * verts/edges/tessfaces/loops/faces. */
- CustomData *(*getVertDataLayout)(DerivedMesh *dm);
- CustomData *(*getEdgeDataLayout)(DerivedMesh *dm);
- CustomData *(*getTessFaceDataLayout)(DerivedMesh *dm);
- CustomData *(*getLoopDataLayout)(DerivedMesh *dm);
- CustomData *(*getPolyDataLayout)(DerivedMesh *dm);
-
/** Optional grid access for subsurf */
int (*getNumGrids)(DerivedMesh *dm);
int (*getGridSize)(DerivedMesh *dm);
@@ -231,11 +198,6 @@ struct DerivedMesh {
/** Get smooth vertex normal, undefined if index is not valid */
void (*getVertNo)(DerivedMesh *dm, int index, float r_no[3]);
- void (*getPolyNo)(DerivedMesh *dm, int index, float r_no[3]);
-
- /** Get a map of vertices to faces
- */
- const struct MeshElemMap *(*getPolyMap)(struct Object *ob, DerivedMesh *dm);
/** Release reference to the DerivedMesh. This function decides internally
* if the DerivedMesh will be freed, or cached for later use. */
@@ -265,15 +227,6 @@ void DM_init(DerivedMesh *dm,
* Utility function to initialize a DerivedMesh for the desired number
* of vertices, edges and faces, with a layer setup copied from source
*/
-void DM_from_template_ex(DerivedMesh *dm,
- DerivedMesh *source,
- DerivedMeshType type,
- int numVerts,
- int numEdges,
- int numTessFaces,
- int numLoops,
- int numPolys,
- const struct CustomData_MeshMasks *mask);
void DM_from_template(DerivedMesh *dm,
DerivedMesh *source,
DerivedMeshType type,
@@ -303,26 +256,9 @@ void DM_set_only_copy(DerivedMesh *dm, const struct CustomData_MeshMasks *mask);
void DM_add_vert_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
void DM_add_edge_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
-void DM_add_tessface_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
-void DM_add_loop_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
void DM_add_poly_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
/* -------------------------------------------------------------------- */
-/** \name Custom Data Access Functions
- *
- * \return pointer to data from first layer which matches type
- * if they return NULL for valid indices, data doesn't exist.
- * \note these return pointers - any change modifies the internals of the mesh.
- * \{ */
-
-void *DM_get_vert_data(struct DerivedMesh *dm, int index, int type);
-void *DM_get_edge_data(struct DerivedMesh *dm, int index, int type);
-void *DM_get_tessface_data(struct DerivedMesh *dm, int index, int type);
-void *DM_get_poly_data(struct DerivedMesh *dm, int index, int type);
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Custom Data Layer Access Functions
*
* \return pointer to first data layer which matches type (a flat array)
@@ -332,7 +268,6 @@ void *DM_get_poly_data(struct DerivedMesh *dm, int index, int type);
void *DM_get_vert_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_edge_data_layer(struct DerivedMesh *dm, int type);
-void *DM_get_tessface_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_poly_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_loop_data_layer(struct DerivedMesh *dm, int type);
@@ -354,8 +289,6 @@ void DM_copy_vert_data(struct DerivedMesh *source,
*/
void DM_DupPolys(DerivedMesh *source, DerivedMesh *target);
-void DM_ensure_normals(DerivedMesh *dm);
-
/**
* Ensure the array is large enough.
*
@@ -401,11 +334,6 @@ void makeDerivedMesh(struct Depsgraph *depsgraph,
struct Object *ob,
const struct CustomData_MeshMasks *dataMask);
-void DM_calc_loop_tangents(DerivedMesh *dm,
- bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME],
- int tangent_names_len);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 0b09bfd8730..5d1b4baedfd 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -365,7 +365,6 @@ void what_does_obaction(struct Object *ob,
char groupname[],
const struct AnimationEvalContext *anim_eval_context);
-/* for proxy */
void BKE_pose_copy_pchan_result(struct bPoseChannel *pchanto,
const struct bPoseChannel *pchanfrom);
/**
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 8584ce6f508..12d8135ba55 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -619,14 +619,6 @@ void BKE_pose_eval_cleanup(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *object);
-void BKE_pose_eval_proxy_init(struct Depsgraph *depsgraph, struct Object *object);
-void BKE_pose_eval_proxy_done(struct Depsgraph *depsgraph, struct Object *object);
-void BKE_pose_eval_proxy_cleanup(struct Depsgraph *depsgraph, struct Object *object);
-
-void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph,
- struct Object *object,
- int pchan_index);
-
/* -------------------------------------------------------------------- */
/** \name Deform 3D Coordinates by Armature (armature_deform.c)
* \{ */
diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh
index 90f349125c9..bf773cd6d75 100644
--- a/source/blender/blenkernel/BKE_attribute_math.hh
+++ b/source/blender/blenkernel/BKE_attribute_math.hh
@@ -50,6 +50,9 @@ inline void convert_to_static_type(const CustomDataType data_type, const Func &f
case CD_PROP_BOOL:
func(bool());
break;
+ case CD_PROP_INT8:
+ func(int8_t());
+ break;
case CD_PROP_COLOR:
func(ColorGeometry4f());
break;
@@ -77,6 +80,9 @@ inline void convert_to_static_type(const fn::CPPType &cpp_type, const Func &func
else if (cpp_type.is<bool>()) {
func(bool());
}
+ else if (cpp_type.is<int8_t>()) {
+ func(int8_t());
+ }
else if (cpp_type.is<ColorGeometry4f>()) {
func(ColorGeometry4f());
}
@@ -93,6 +99,12 @@ inline void convert_to_static_type(const fn::CPPType &cpp_type, const Func &func
template<typename T> T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2);
+template<>
+inline int8_t mix3(const float3 &weights, const int8_t &v0, const int8_t &v1, const int8_t &v2)
+{
+ return static_cast<int8_t>(weights.x * v0 + weights.y * v1 + weights.z * v2);
+}
+
template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2)
{
return (weights.x * v0 + weights.y * v1 + weights.z * v2) >= 0.5f;
@@ -147,6 +159,11 @@ template<> inline bool mix2(const float factor, const bool &a, const bool &b)
return ((1.0f - factor) * a + factor * b) >= 0.5f;
}
+template<> inline int8_t mix2(const float factor, const int8_t &a, const int8_t &b)
+{
+ return static_cast<int8_t>((1.0f - factor) * a + factor * b);
+}
+
template<> inline int mix2(const float factor, const int &a, const int &b)
{
return static_cast<int>((1.0f - factor) * a + factor * b);
@@ -364,6 +381,15 @@ template<> struct DefaultMixerStruct<bool> {
using type = SimpleMixerWithAccumulationType<bool, float, float_to_bool>;
};
+template<> struct DefaultMixerStruct<int8_t> {
+ static int8_t float_to_int8_t(const float &value)
+ {
+ return static_cast<int8_t>(value);
+ }
+ /* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */
+ using type = SimpleMixerWithAccumulationType<int8_t, float, float_to_int8_t>;
+};
+
template<typename T> struct DefaultPropatationMixerStruct {
/* Use void by default. This can be checked for in `if constexpr` statements. */
using type = typename DefaultMixerStruct<T>::type;
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index d1f31e0d2f5..645d049fe71 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -31,15 +31,15 @@ extern "C" {
*/
/* Blender major and minor version. */
-#define BLENDER_VERSION 301
+#define BLENDER_VERSION 302
/* Blender patch version for bugfix releases. */
#define BLENDER_VERSION_PATCH 0
/** Blender release cycle stage: alpha/beta/rc/release. */
-#define BLENDER_VERSION_CYCLE beta
+#define BLENDER_VERSION_CYCLE alpha
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 6
+#define BLENDER_FILE_SUBVERSION 1
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index bce15349880..467d74b17da 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -130,9 +130,9 @@ bool BKE_collection_object_add(struct Main *bmain,
struct Collection *collection,
struct Object *ob);
/**
- * Same as #BKE_collection_object_add, but uncondionnaly adds the object to the given collection.
+ * Same as #BKE_collection_object_add, but unconditionally adds the object to the given collection.
*
- * NOTE: required in certain cases, like do-versionning or complex ID management tasks.
+ * NOTE: required in certain cases, like do-versioning or complex ID management tasks.
*/
bool BKE_collection_object_add_notest(struct Main *bmain,
struct Collection *collection,
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 55e5cd0a149..2da79e27576 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -278,18 +278,6 @@ bool BKE_constraint_apply_and_remove_for_pose(struct Depsgraph *depsgraph,
void BKE_constraint_panel_expand(struct bConstraint *con);
-/* Constraints + Proxies function prototypes */
-
-/**
- * Rescue all constraints tagged as being #CONSTRAINT_PROXY_LOCAL
- * (i.e. added to bone that's proxy-synced in this file).
- */
-void BKE_constraints_proxylocal_extract(struct ListBase *dst, struct ListBase *src);
-/**
- * Returns if the owner of the constraint is proxy-protected.
- */
-bool BKE_constraints_proxylocked_owner(struct Object *ob, struct bPoseChannel *pchan);
-
/* Constraint Evaluation function prototypes */
/**
diff --git a/source/blender/blenkernel/BKE_image_partial_update.hh b/source/blender/blenkernel/BKE_image_partial_update.hh
index ca7c4f40593..0fc05809bbd 100644
--- a/source/blender/blenkernel/BKE_image_partial_update.hh
+++ b/source/blender/blenkernel/BKE_image_partial_update.hh
@@ -23,8 +23,8 @@
* image that are changed. These areas are organized in chunks. Changes that happen over time are
* organized in changesets.
*
- * A common usecase is to update GPUTexture for drawing where only that part is uploaded that only
- * changed.
+ * A common use case is to update #GPUTexture for drawing where only that part is uploaded that
+ * only changed.
*/
#pragma once
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index ebd35cad965..daf13590ca2 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -376,10 +376,6 @@ enum {
/** Clear asset data (in case the ID can actually be made local, in copy case asset data is never
* copied over). */
LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR = 1 << 3,
-
- /* Special type-specific options. */
- /** For Objects, do not clear the proxy pointers while making the data-block local. */
- LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING = 1 << 16,
};
/**
diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h
index 30e75259967..e8065566c97 100644
--- a/source/blender/blenkernel/BKE_lib_override.h
+++ b/source/blender/blenkernel/BKE_lib_override.h
@@ -100,6 +100,9 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
* main. You can add more local IDs to be remapped to use new overriding ones by setting their
* LIB_TAG_DOIT tag.
*
+ * \param owner_library: the library in which the overrides should be created. Besides versioning
+ * and resync code path, this should always be NULL (i.e. the local .blend file).
+ *
* \param reference_library: the library from which the linked data being overridden come from
* (i.e. the library of the linked reference ID).
*
@@ -109,6 +112,7 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
* \return \a true on success, \a false otherwise.
*/
bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
+ struct Library *owner_library,
const struct Library *reference_library,
bool do_no_main);
/**
@@ -122,16 +126,24 @@ bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
*
* \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
* which case \a scene's master collection children hierarchy is used instead).
+ *
+ * \param owner_library: the library in which the overrides should be created. Besides versioning
+ * and resync code path, this should always be NULL (i.e. the local .blend file).
+ *
* \param id_root: The root ID to create an override from.
+ *
* \param id_reference: Some reference ID used to do some post-processing after overrides have been
* created, may be NULL. Typically, the Empty object instantiating the linked collection we
* override, currently.
+ *
* \param r_id_root_override: if not NULL, the override generated for the given \a id_root.
+ *
* \return true if override was successfully created.
*/
bool BKE_lib_override_library_create(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
+ struct Library *owner_library,
struct ID *id_root,
struct ID *id_reference,
struct ID **r_id_root_override);
diff --git a/source/blender/blenkernel/BKE_lib_query.h b/source/blender/blenkernel/BKE_lib_query.h
index d853cb16b13..dd2e2a2f8e5 100644
--- a/source/blender/blenkernel/BKE_lib_query.h
+++ b/source/blender/blenkernel/BKE_lib_query.h
@@ -63,7 +63,7 @@ enum {
/**
* That ID is not really used by its owner, it's just an internal hint/helper.
- * This addresses Their Highest Ugliness the 'from' pointers: Object->from_proxy and Key->from.
+ * This marks the 'from' pointers issue, like Key->from.
* How to handle that kind of cases totally depends on what caller code is doing... */
IDWALK_CB_LOOPBACK = (1 << 4),
@@ -135,7 +135,6 @@ enum {
/** Do not process ID pointers inside embedded IDs. Needed by depsgraph processing e.g. */
IDWALK_IGNORE_EMBEDDED_ID = (1 << 3),
- IDWALK_NO_INDIRECT_PROXY_DATA_USAGE = (1 << 8), /* Ugly special case :(((( */
/** Also process internal ID pointers like `ID.newid` or `ID.orig_id`.
* WARNING: Dangerous, use with caution. */
IDWALK_DO_INTERNAL_RUNTIME_POINTERS = (1 << 9),
diff --git a/source/blender/blenkernel/BKE_lib_remap.h b/source/blender/blenkernel/BKE_lib_remap.h
index cc970342fbb..f14cd75c5c6 100644
--- a/source/blender/blenkernel/BKE_lib_remap.h
+++ b/source/blender/blenkernel/BKE_lib_remap.h
@@ -68,15 +68,6 @@ enum {
* and can cause crashes very easily!
*/
ID_REMAP_FORCE_NEVER_NULL_USAGE = 1 << 3,
- /**
- * Do not consider proxy/_group pointers of local objects as indirect usages...
- * Our oh-so-beloved proxies again...
- * Do not consider data used by local proxy object as indirect usage.
- * This is needed e.g. in reload scenario,
- * since we have to ensure remapping of Armature data of local proxy
- * is also performed. Usual nightmare...
- */
- ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE = 1 << 4,
/** Do not remap library override pointers. */
ID_REMAP_SKIP_OVERRIDE_LIBRARY = 1 << 5,
/** Don't touch the user count (use for low level actions such as swapping pointers). */
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 910b13b9b95..a05ed67063a 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -245,10 +245,6 @@ typedef struct ModifierTypeInfo {
const struct ModifierEvalContext *ctx,
struct Mesh *mesh);
- struct Hair *(*modifyHair)(struct ModifierData *md,
- const struct ModifierEvalContext *ctx,
- struct Hair *hair);
-
/**
* The modifier has to change the geometry set in-place. The geometry set can contain zero or
* more geometry components. This callback can be used by modifiers that don't work on any
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 16d8ba2e6dd..d583b5f0648 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1291,6 +1291,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define CMP_NODE_POSTERIZE 327
#define CMP_NODE_CONVERT_COLOR_SPACE 328
#define CMP_NODE_SCENE_TIME 329
+#define CMP_NODE_SEPARATE_XYZ 330
+#define CMP_NODE_COMBINE_XYZ 331
/* channel toggles */
#define CMP_CHAN_RGB 1
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 99758f4ad78..96ed7942067 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -144,18 +144,6 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr
void BKE_object_free_modifiers(struct Object *ob, int flag);
void BKE_object_free_shaderfx(struct Object *ob, int flag);
-/**
- * Proxy rule:
- * - `lib_object->proxy_from` == the one we borrow from, set temporally while object_update.
- * - `local_object->proxy` == pointer to library object, saved in files and read.
- * - `local_object->proxy_group` == pointer to collection dupli-object, saved in files and read.
- */
-void BKE_object_make_proxy(struct Main *bmain,
- struct Object *ob,
- struct Object *target,
- struct Object *cob);
-void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
-
bool BKE_object_exists_check(struct Main *bmain, const struct Object *obtest);
/**
* Actual check for internal data, not context or flags.
@@ -444,7 +432,6 @@ void BKE_object_eval_constraints(struct Depsgraph *depsgraph,
struct Object *ob);
void BKE_object_eval_transform_final(struct Depsgraph *depsgraph, struct Object *ob);
-bool BKE_object_eval_proxy_copy(struct Depsgraph *depsgraph, struct Object *object);
void BKE_object_eval_uber_transform(struct Depsgraph *depsgraph, struct Object *ob);
void BKE_object_eval_uber_data(struct Depsgraph *depsgraph,
struct Scene *scene,
@@ -486,12 +473,6 @@ void BKE_object_handle_data_update(struct Depsgraph *depsgraph,
*/
void BKE_object_handle_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
/**
- * Proxy rule:
- * - lib_object->proxy_from == the one we borrow from, only set temporal and cleared here.
- * - local_object->proxy == pointer to library object, saved in files and read.
- *
- * Function below is polluted with proxy exceptions, cleanup will follow!
- *
* The main object update call, for object matrix, constraints, keys and #DispList (modifiers)
* requires flags to be set!
*
@@ -501,8 +482,7 @@ void BKE_object_handle_update(struct Depsgraph *depsgraph, struct Scene *scene,
void BKE_object_handle_update_ex(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
- struct RigidBodyWorld *rbw,
- bool do_proxy_update);
+ struct RigidBodyWorld *rbw);
void BKE_object_sculpt_data_create(struct Object *ob);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 220d4673075..55a68c1c5a0 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -182,6 +182,7 @@ set(SRC
intern/lib_id_eval.c
intern/lib_id_remapper.cc
intern/lib_override.c
+ intern/lib_override_proxy_conversion.c
intern/lib_query.c
intern/lib_remap.c
intern/library.c
@@ -719,10 +720,6 @@ if(WITH_FFTW3)
add_definitions(-DFFTW3=1)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index b9372ceed08..2e779d6fad7 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -127,30 +127,6 @@ static MEdge *dm_getEdgeArray(DerivedMesh *dm)
return medge;
}
-static MFace *dm_getTessFaceArray(DerivedMesh *dm)
-{
- MFace *mface = (MFace *)CustomData_get_layer(&dm->faceData, CD_MFACE);
-
- if (!mface) {
- int numTessFaces = dm->getNumTessFaces(dm);
-
- if (!numTessFaces) {
- /* Do not add layer if there's no elements in it, this leads to issues later when
- * this layer is needed with non-zero size, but currently CD stuff does not check
- * for requested layer size on creation and just returns layer which was previously
- * added (sergey) */
- return nullptr;
- }
-
- mface = (MFace *)CustomData_add_layer(
- &dm->faceData, CD_MFACE, CD_CALLOC, nullptr, numTessFaces);
- CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY);
- dm->copyTessFaceArray(dm, mface);
- }
-
- return mface;
-}
-
static MLoop *dm_getLoopArray(DerivedMesh *dm)
{
MLoop *mloop = (MLoop *)CustomData_get_layer(&dm->loopData, CD_MLOOP);
@@ -203,18 +179,6 @@ static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
return tmp;
}
-static MFace *dm_dupFaceArray(DerivedMesh *dm)
-{
- MFace *tmp = (MFace *)MEM_malloc_arrayN(
- dm->getNumTessFaces(dm), sizeof(*tmp), "dm_dupFaceArray tmp");
-
- if (tmp) {
- dm->copyTessFaceArray(dm, tmp);
- }
-
- return tmp;
-}
-
static MLoop *dm_dupLoopArray(DerivedMesh *dm)
{
MLoop *tmp = (MLoop *)MEM_malloc_arrayN(
@@ -270,42 +234,15 @@ static const MLoopTri *dm_getLoopTriArray(DerivedMesh *dm)
return looptri;
}
-static CustomData *dm_getVertCData(DerivedMesh *dm)
-{
- return &dm->vertData;
-}
-
-static CustomData *dm_getEdgeCData(DerivedMesh *dm)
-{
- return &dm->edgeData;
-}
-
-static CustomData *dm_getTessFaceCData(DerivedMesh *dm)
-{
- return &dm->faceData;
-}
-
-static CustomData *dm_getLoopCData(DerivedMesh *dm)
-{
- return &dm->loopData;
-}
-
-static CustomData *dm_getPolyCData(DerivedMesh *dm)
-{
- return &dm->polyData;
-}
-
void DM_init_funcs(DerivedMesh *dm)
{
/* default function implementations */
dm->getVertArray = dm_getVertArray;
dm->getEdgeArray = dm_getEdgeArray;
- dm->getTessFaceArray = dm_getTessFaceArray;
dm->getLoopArray = dm_getLoopArray;
dm->getPolyArray = dm_getPolyArray;
dm->dupVertArray = dm_dupVertArray;
dm->dupEdgeArray = dm_dupEdgeArray;
- dm->dupTessFaceArray = dm_dupFaceArray;
dm->dupLoopArray = dm_dupLoopArray;
dm->dupPolyArray = dm_dupPolyArray;
@@ -314,19 +251,8 @@ void DM_init_funcs(DerivedMesh *dm)
/* subtypes handle getting actual data */
dm->getNumLoopTri = dm_getNumLoopTri;
- dm->getVertDataLayout = dm_getVertCData;
- dm->getEdgeDataLayout = dm_getEdgeCData;
- dm->getTessFaceDataLayout = dm_getTessFaceCData;
- dm->getLoopDataLayout = dm_getLoopCData;
- dm->getPolyDataLayout = dm_getPolyCData;
-
- dm->getVertData = DM_get_vert_data;
- dm->getEdgeData = DM_get_edge_data;
- dm->getTessFaceData = DM_get_tessface_data;
- dm->getPolyData = DM_get_poly_data;
dm->getVertDataArray = DM_get_vert_data_layer;
dm->getEdgeDataArray = DM_get_edge_data_layer;
- dm->getTessFaceDataArray = DM_get_tessface_data_layer;
dm->getPolyDataArray = DM_get_poly_data_layer;
dm->getLoopDataArray = DM_get_loop_data_layer;
}
@@ -349,7 +275,6 @@ void DM_init(DerivedMesh *dm,
DM_init_funcs(dm);
dm->needsFree = 1;
- dm->dirty = (DMDirtyFlag)0;
/* Don't use #CustomData_reset because we don't want to touch custom-data. */
copy_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1);
@@ -359,16 +284,16 @@ void DM_init(DerivedMesh *dm,
copy_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1);
}
-void DM_from_template_ex(DerivedMesh *dm,
- DerivedMesh *source,
- DerivedMeshType type,
- int numVerts,
- int numEdges,
- int numTessFaces,
- int numLoops,
- int numPolys,
- const CustomData_MeshMasks *mask)
+void DM_from_template(DerivedMesh *dm,
+ DerivedMesh *source,
+ DerivedMeshType type,
+ int numVerts,
+ int numEdges,
+ int numTessFaces,
+ int numLoops,
+ int numPolys)
{
+ const CustomData_MeshMasks *mask = &CD_MASK_DERIVEDMESH;
CustomData_copy(&source->vertData, &dm->vertData, mask->vmask, CD_CALLOC, numVerts);
CustomData_copy(&source->edgeData, &dm->edgeData, mask->emask, CD_CALLOC, numEdges);
CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_CALLOC, numTessFaces);
@@ -387,26 +312,6 @@ void DM_from_template_ex(DerivedMesh *dm,
DM_init_funcs(dm);
dm->needsFree = 1;
- dm->dirty = (DMDirtyFlag)0;
-}
-void DM_from_template(DerivedMesh *dm,
- DerivedMesh *source,
- DerivedMeshType type,
- int numVerts,
- int numEdges,
- int numTessFaces,
- int numLoops,
- int numPolys)
-{
- DM_from_template_ex(dm,
- source,
- type,
- numVerts,
- numEdges,
- numTessFaces,
- numLoops,
- numPolys,
- &CD_MASK_DERIVEDMESH);
}
bool DM_release(DerivedMesh *dm)
@@ -464,14 +369,6 @@ void DM_DupPolys(DerivedMesh *source, DerivedMesh *target)
}
}
-void DM_ensure_normals(DerivedMesh *dm)
-{
- if (dm->dirty & DM_DIRTY_NORMALS) {
- dm->calcNormals(dm);
- }
- BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0);
-}
-
void DM_ensure_looptri_data(DerivedMesh *dm)
{
const unsigned int totpoly = dm->numPolyData;
@@ -524,7 +421,7 @@ void DM_set_only_copy(DerivedMesh *dm, const CustomData_MeshMasks *mask)
* see replies to r50969, Campbell */
#if 0
CustomData_set_only_copy(&dm->loopData, mask->lmask);
- CustomData_set_only_copy(&dm->polyData, mask->pmask);
+ Custom(&dm->polyData, mask->pmask);
#endif
}
@@ -552,45 +449,11 @@ void DM_add_edge_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *
CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData);
}
-void DM_add_tessface_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
-{
- CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numTessFaceData);
-}
-
-void DM_add_loop_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
-{
- CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData);
-}
-
void DM_add_poly_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
{
CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData);
}
-void *DM_get_vert_data(DerivedMesh *dm, int index, int type)
-{
- BLI_assert(index >= 0 && index < dm->getNumVerts(dm));
- return CustomData_get(&dm->vertData, index, type);
-}
-
-void *DM_get_edge_data(DerivedMesh *dm, int index, int type)
-{
- BLI_assert(index >= 0 && index < dm->getNumEdges(dm));
- return CustomData_get(&dm->edgeData, index, type);
-}
-
-void *DM_get_tessface_data(DerivedMesh *dm, int index, int type)
-{
- BLI_assert(index >= 0 && index < dm->getNumTessFaces(dm));
- return CustomData_get(&dm->faceData, index, type);
-}
-
-void *DM_get_poly_data(DerivedMesh *dm, int index, int type)
-{
- BLI_assert(index >= 0 && index < dm->getNumPolys(dm));
- return CustomData_get(&dm->polyData, index, type);
-}
-
void *DM_get_vert_data_layer(DerivedMesh *dm, int type)
{
if (type == CD_MVERT) {
@@ -609,15 +472,6 @@ void *DM_get_edge_data_layer(DerivedMesh *dm, int type)
return CustomData_get_layer(&dm->edgeData, type);
}
-void *DM_get_tessface_data_layer(DerivedMesh *dm, int type)
-{
- if (type == CD_MFACE) {
- return dm->getTessFaceArray(dm);
- }
-
- return CustomData_get_layer(&dm->faceData, type);
-}
-
void *DM_get_poly_data_layer(DerivedMesh *dm, int type)
{
return CustomData_get_layer(&dm->polyData, type);
@@ -2137,32 +1991,6 @@ void mesh_get_mapped_verts_coords(Mesh *me_eval, float (*r_cos)[3], const int to
}
}
-void DM_calc_loop_tangents(DerivedMesh *dm,
- bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME],
- int tangent_names_len)
-{
- BKE_mesh_calc_loop_tangent_ex(
- dm->getVertArray(dm),
- dm->getPolyArray(dm),
- dm->getNumPolys(dm),
- dm->getLoopArray(dm),
- dm->getLoopTriArray(dm),
- dm->getNumLoopTri(dm),
- &dm->loopData,
- calc_active_tangent,
- tangent_names,
- tangent_names_len,
- (const float(*)[3])CustomData_get_layer(&dm->vertData, CD_NORMAL),
- (const float(*)[3])CustomData_get_layer(&dm->polyData, CD_NORMAL),
- (const float(*)[3])dm->getLoopDataArray(dm, CD_NORMAL),
- (const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* may be nullptr */
- /* result */
- &dm->loopData,
- dm->getNumLoops(dm),
- &dm->tangent_mask);
-}
-
static void mesh_init_origspace(Mesh *mesh)
{
const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index fde42304185..8426f6f4676 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -1956,30 +1956,15 @@ void BKE_pose_blend_read_lib(BlendLibReader *reader, Object *ob, bPose *pose)
return;
}
- /* always rebuild to match proxy or lib changes, but on Undo */
+ /* Always rebuild to match library changes, except on Undo. */
bool rebuild = false;
if (!BLO_read_lib_is_undo(reader)) {
- if (ob->proxy || ob->id.lib != arm->id.lib) {
+ if (ob->id.lib != arm->id.lib) {
rebuild = true;
}
}
- if (ob->proxy) {
- /* sync proxy layer */
- if (pose->proxy_layer) {
- arm->layer = pose->proxy_layer;
- }
-
- /* sync proxy active bone */
- if (pose->proxy_act_bone[0]) {
- Bone *bone = BKE_armature_find_bone_name(arm, pose->proxy_act_bone);
- if (bone) {
- arm->act_bone = bone;
- }
- }
- }
-
LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
BKE_constraint_blend_read_lib(reader, (ID *)ob, &pchan->constraints);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 5704ef6e42f..7feb9d08915 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -69,8 +69,6 @@
#include "CLG_log.h"
-static CLG_LogRef LOG = {"bke.armature"};
-
/* -------------------------------------------------------------------- */
/** \name Prototypes
* \{ */
@@ -2296,161 +2294,6 @@ void BKE_armature_where_is(bArmature *arm)
/** \name Pose Rebuild
* \{ */
-/* if bone layer is protected, copy the data from from->pose
- * when used with linked libraries this copies from the linked pose into the local pose */
-static void pose_proxy_sync(Object *ob, Object *from, int layer_protected)
-{
- bPose *pose = ob->pose, *frompose = from->pose;
- bPoseChannel *pchan, *pchanp;
- bConstraint *con;
- int error = 0;
-
- if (frompose == NULL) {
- return;
- }
-
- /* in some cases when rigs change, we can't synchronize
- * to avoid crashing check for possible errors here */
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->layer & layer_protected) {
- if (BKE_pose_channel_find_name(frompose, pchan->name) == NULL) {
- CLOG_ERROR(&LOG,
- "failed to sync proxy armature because '%s' is missing pose channel '%s'",
- from->id.name,
- pchan->name);
- error = 1;
- }
- }
- }
-
- if (error) {
- return;
- }
-
- /* clear all transformation values from library */
- BKE_pose_rest(frompose, false);
-
- /* copy over all of the proxy's bone groups */
- /* TODO: for later
- * - implement 'local' bone groups as for constraints
- * NOTE: this isn't trivial, as bones reference groups by index not by pointer,
- * so syncing things correctly needs careful attention */
- BLI_freelistN(&pose->agroups);
- BLI_duplicatelist(&pose->agroups, &frompose->agroups);
- pose->active_group = frompose->active_group;
-
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- pchanp = BKE_pose_channel_find_name(frompose, pchan->name);
-
- if (UNLIKELY(pchanp == NULL)) {
- /* happens for proxies that become invalid because of a missing link
- * for regular cases it shouldn't happen at all */
- }
- else if (pchan->bone->layer & layer_protected) {
- ListBase proxylocal_constraints = {NULL, NULL};
- bPoseChannel pchanw;
-
- /* copy posechannel to temp, but restore important pointers */
- pchanw = *pchanp;
- pchanw.bone = pchan->bone;
- pchanw.prev = pchan->prev;
- pchanw.next = pchan->next;
- pchanw.parent = pchan->parent;
- pchanw.child = pchan->child;
- pchanw.custom_tx = pchan->custom_tx;
- pchanw.bbone_prev = pchan->bbone_prev;
- pchanw.bbone_next = pchan->bbone_next;
-
- pchanw.mpath = pchan->mpath;
- pchan->mpath = NULL;
-
- /* Reset runtime data, we don't want to share that with the proxy. */
- BKE_pose_channel_runtime_reset_on_copy(&pchanw.runtime);
-
- /* this is freed so copy a copy, else undo crashes */
- if (pchanw.prop) {
- pchanw.prop = IDP_CopyProperty(pchanw.prop);
-
- /* use the values from the existing props */
- if (pchan->prop) {
- IDP_SyncGroupValues(pchanw.prop, pchan->prop);
- }
- }
-
- /* Constraints - proxy constraints are flushed... local ones are added after
- * 1: extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints.
- * 2: copy proxy-pchan's constraints on-to new.
- * 3: add extracted local constraints back on top.
- *
- * Note for BKE_constraints_copy:
- * When copying constraints, disable 'do_extern' otherwise
- * we get the libs direct linked in this blend.
- */
- BKE_constraints_proxylocal_extract(&proxylocal_constraints, &pchan->constraints);
- BKE_constraints_copy(&pchanw.constraints, &pchanp->constraints, false);
- BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints);
-
- /* constraints - set target ob pointer to own object */
- for (con = pchanw.constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == from) {
- ct->tar = ob;
- }
- }
-
- if (cti->flush_constraint_targets) {
- cti->flush_constraint_targets(con, &targets, 0);
- }
- }
- }
-
- /* free stuff from current channel */
- BKE_pose_channel_free(pchan);
-
- /* copy data in temp back over to the cleaned-out (but still allocated) original channel */
- *pchan = pchanw;
- if (pchan->custom) {
- id_us_plus(&pchan->custom->id);
- }
- }
- else {
- /* always copy custom shape */
- pchan->custom = pchanp->custom;
- if (pchan->custom) {
- id_us_plus(&pchan->custom->id);
- }
- if (pchanp->custom_tx) {
- pchan->custom_tx = BKE_pose_channel_find_name(pose, pchanp->custom_tx->name);
- }
-
- /* ID-Property Syncing */
- {
- IDProperty *prop_orig = pchan->prop;
- if (pchanp->prop) {
- pchan->prop = IDP_CopyProperty(pchanp->prop);
- if (prop_orig) {
- /* copy existing values across when types match */
- IDP_SyncGroupValues(pchan->prop, prop_orig);
- }
- }
- else {
- pchan->prop = NULL;
- }
- if (prop_orig) {
- IDP_FreeProperty(prop_orig);
- }
- }
- }
- }
-}
-
/**
* \param r_last_visited_bone_p: The last bone handled by the last call to this function.
*/
@@ -2579,16 +2422,6 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
// printf("rebuild pose %s, %d bones\n", ob->id.name, counter);
- /* synchronize protected layers with proxy */
- /* HACK! To preserve 2.7x behavior that you always can pose even locked bones,
- * do not do any restoration if this is a COW temp copy! */
- /* Switched back to just NO_MAIN tag, for some reasons (c)
- * using COW tag was working this morning, but not anymore... */
- if (ob->proxy != NULL && (ob->id.tag & LIB_TAG_NO_MAIN) == 0) {
- BKE_object_copy_proxy_drivers(ob, ob->proxy);
- pose_proxy_sync(ob, ob->proxy, arm->layer_protected);
- }
-
BKE_pose_update_constraint_flags(pose); /* for IK detection for example */
pose->flag &= ~POSE_RECALC;
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 05c318663e9..73a396b2cdd 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -850,10 +850,6 @@ 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)
@@ -1070,57 +1066,3 @@ void BKE_pose_eval_cleanup(struct Depsgraph *depsgraph, Scene *scene, Object *ob
BIK_release_tree(scene, object, ctime);
pose_eval_cleanup_common(object);
}
-
-void BKE_pose_eval_proxy_init(struct Depsgraph *depsgraph, Object *object)
-{
- BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
- DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
-
- BLI_assert(object->pose->chan_array != NULL || BLI_listbase_is_empty(&object->pose->chanbase));
-}
-
-void BKE_pose_eval_proxy_done(struct Depsgraph *depsgraph, Object *object)
-{
- BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
- DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
-}
-
-void BKE_pose_eval_proxy_cleanup(struct Depsgraph *depsgraph, Object *object)
-{
- BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
- DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
- pose_eval_cleanup_common(object);
-}
-
-void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph, Object *object, int pchan_index)
-{
- const bArmature *armature = (bArmature *)object->data;
- if (armature->edbo != NULL) {
- return;
- }
- BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
- bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index);
- BLI_assert(pchan != NULL);
- DEG_debug_print_eval_subdata(
- depsgraph, __func__, object->id.name, object, "pchan", pchan->name, pchan);
- /* TODO(sergey): Use indexed lookup, once it's guaranteed to be kept
- * around for the time while proxies are evaluating.
- */
-#if 0
- bPoseChannel *pchan_from = pose_pchan_get_indexed(object->proxy_from, pchan_index);
-#else
- bPoseChannel *pchan_from = BKE_pose_channel_find_name(object->proxy_from->pose, pchan->name);
-#endif
- if (pchan_from == NULL) {
- printf(
- "WARNING: Could not find bone %s in linked ID anymore... "
- "You should delete and re-generate your proxy.\n",
- pchan->name);
- return;
- }
- 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);
-
- pose_channel_flush_to_orig_if_needed(depsgraph, object, pchan);
-}
diff --git a/source/blender/blenkernel/intern/attribute.c b/source/blender/blenkernel/intern/attribute.c
index ee8ef5e97f7..73e00398084 100644
--- a/source/blender/blenkernel/intern/attribute.c
+++ b/source/blender/blenkernel/intern/attribute.c
@@ -90,10 +90,10 @@ static void get_domains(const ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
}
case ID_HA: {
Hair *hair = (Hair *)id;
- info[ATTR_DOMAIN_POINT].customdata = &hair->pdata;
- info[ATTR_DOMAIN_POINT].length = hair->totpoint;
- info[ATTR_DOMAIN_CURVE].customdata = &hair->cdata;
- info[ATTR_DOMAIN_CURVE].length = hair->totcurve;
+ info[ATTR_DOMAIN_POINT].customdata = &hair->geometry.point_data;
+ info[ATTR_DOMAIN_POINT].length = hair->geometry.point_size;
+ info[ATTR_DOMAIN_CURVE].customdata = &hair->geometry.curve_data;
+ info[ATTR_DOMAIN_CURVE].length = hair->geometry.curve_size;
break;
}
default:
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index cc43a3e26a8..68ab11a013b 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -83,6 +83,8 @@ const blender::fn::CPPType *custom_data_type_to_cpp_type(const CustomDataType ty
return &CPPType::get<ColorGeometry4f>();
case CD_PROP_BOOL:
return &CPPType::get<bool>();
+ case CD_PROP_INT8:
+ return &CPPType::get<int8_t>();
default:
return nullptr;
}
@@ -109,6 +111,9 @@ CustomDataType cpp_type_to_custom_data_type(const blender::fn::CPPType &type)
if (type.is<bool>()) {
return CD_PROP_BOOL;
}
+ if (type.is<int8_t>()) {
+ return CD_PROP_INT8;
+ }
return static_cast<CustomDataType>(-1);
}
@@ -117,16 +122,18 @@ static int attribute_data_type_complexity(const CustomDataType data_type)
switch (data_type) {
case CD_PROP_BOOL:
return 0;
- case CD_PROP_INT32:
+ case CD_PROP_INT8:
return 1;
- case CD_PROP_FLOAT:
+ case CD_PROP_INT32:
return 2;
- case CD_PROP_FLOAT2:
+ case CD_PROP_FLOAT:
return 3;
- case CD_PROP_FLOAT3:
+ case CD_PROP_FLOAT2:
return 4;
- case CD_PROP_COLOR:
+ case CD_PROP_FLOAT3:
return 5;
+ case CD_PROP_COLOR:
+ return 6;
#if 0 /* These attribute types are not supported yet. */
case CD_MLOOPCOL:
return 3;
diff --git a/source/blender/blenkernel/intern/attribute_access_intern.hh b/source/blender/blenkernel/intern/attribute_access_intern.hh
index 2cd128081eb..5341266e182 100644
--- a/source/blender/blenkernel/intern/attribute_access_intern.hh
+++ b/source/blender/blenkernel/intern/attribute_access_intern.hh
@@ -140,7 +140,8 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
private:
static constexpr uint64_t supported_types_mask = CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 |
CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 |
- CD_MASK_PROP_COLOR | CD_MASK_PROP_BOOL;
+ CD_MASK_PROP_COLOR | CD_MASK_PROP_BOOL |
+ CD_MASK_PROP_INT8;
const AttributeDomain domain_;
const CustomDataAccessInfo custom_data_access_;
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 53c9fe49fb7..86c2593e2e6 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -78,6 +78,23 @@
/** \name High Level `.blend` file read/write.
* \{ */
+static bool blendfile_or_libraries_versions_atleast(Main *bmain,
+ const short versionfile,
+ const short subversionfile)
+{
+ if (!MAIN_VERSION_ATLEAST(bmain, versionfile, subversionfile)) {
+ return false;
+ }
+
+ LISTBASE_FOREACH (Library *, library, &bmain->libraries) {
+ if (!MAIN_VERSION_ATLEAST(library, versionfile, subversionfile)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
static bool foreach_path_clean_cb(BPathForeachPathData *UNUSED(bpath_data),
char *path_dst,
const char *path_src)
@@ -349,10 +366,11 @@ static void setup_app_data(bContext *C,
do_versions_ipos_to_animato(bmain);
}
- /* FIXME: Same as above, readfile's `do_version` do not allow to create new IDs. */
- /* TODO: Once this is definitively validated for 3.0 and option to not do it is removed, add a
- * version bump and check here. */
- if (mode != LOAD_UNDO && !USER_EXPERIMENTAL_TEST(&U, no_proxy_to_override_conversion)) {
+ /* NOTE: readfile's `do_version` does not allow to create new IDs, and only operates on a single
+ * library at a time. This code needs to operate on the whole Main at once. */
+ /* NOTE: Check bmain version (i.e. current blend file version), AND the versions of all the
+ * linked libraries. */
+ if (mode != LOAD_UNDO && !blendfile_or_libraries_versions_atleast(bmain, 302, 1)) {
BKE_lib_override_library_main_proxy_convert(bmain, reports);
}
diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c
index 9b3f4c2fae8..025d16007d8 100644
--- a/source/blender/blenkernel/intern/blendfile_link_append.c
+++ b/source/blender/blenkernel/intern/blendfile_link_append.c
@@ -993,6 +993,27 @@ static int foreach_libblock_link_append_callback(LibraryIDLinkCallbackData *cb_d
/** \name Library link/append code.
* \{ */
+static void blendfile_link_append_proxies_convert(Main *bmain, ReportList *reports)
+{
+ /* NOTE: Do not bother checking file versions here, if there are no proxies to convert this code
+ * is quite fast anyway. */
+
+ BlendFileReadReport bf_reports = {.reports = reports};
+ BKE_lib_override_library_main_proxy_convert(bmain, &bf_reports);
+
+ if (bf_reports.count.proxies_to_lib_overrides_success != 0 ||
+ bf_reports.count.proxies_to_lib_overrides_failures != 0) {
+ BKE_reportf(
+ bf_reports.reports,
+ RPT_WARNING,
+ "Proxies have been removed from Blender (%d proxies were automatically converted "
+ "to library overrides, %d proxies could not be converted and were cleared). "
+ "Please consider re-saving any library .blend file with the newest Blender version.",
+ bf_reports.count.proxies_to_lib_overrides_success,
+ bf_reports.count.proxies_to_lib_overrides_failures);
+ }
+}
+
void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
{
if (lapp_context->num_items == 0) {
@@ -1040,10 +1061,6 @@ void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *
if (item->action != LINK_APPEND_ACT_UNSET) {
/* Already set, pass. */
}
- if (GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) {
- CLOG_INFO(&LOG, 3, "Appended ID '%s' is proxified, keeping it linked...", id->name);
- item->action = LINK_APPEND_ACT_KEEP_LINKED;
- }
else if (do_reuse_local_id && existing_local_id != NULL) {
CLOG_INFO(&LOG, 3, "Appended ID '%s' as a matching local one, re-using it...", id->name);
item->action = LINK_APPEND_ACT_REUSE_LOCAL;
@@ -1098,10 +1115,7 @@ void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *
local_appended_new_id = id->newid;
break;
case LINK_APPEND_ACT_MAKE_LOCAL:
- BKE_lib_id_make_local(bmain,
- id,
- make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_LOCAL |
- LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING);
+ BKE_lib_id_make_local(bmain, id, make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_LOCAL);
BLI_assert(id->newid == NULL);
local_appended_new_id = id;
break;
@@ -1210,55 +1224,11 @@ void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *
continue;
}
BLI_assert(ID_IS_LINKED(id));
-
- /* Attempt to re-link copied proxy objects. This allows appending of an entire scene
- * from another blend file into this one, even when that blend file contains proxified
- * armatures that have local references. Since the proxified object needs to be linked
- * (not local), this will only work when the "Localize all" checkbox is disabled.
- * TL;DR: this is a dirty hack on top of an already weak feature (proxies). */
- if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) {
- Object *ob = (Object *)id;
- Object *ob_new = (Object *)id->newid;
- bool is_local = false, is_lib = false;
-
- /* Proxies only work when the proxified object is linked-in from a library. */
- if (!ID_IS_LINKED(ob->proxy)) {
- CLOG_WARN(&LOG,
- "Proxy object %s will lose its link to %s, because the "
- "proxified object is local",
- id->newid->name,
- ob->proxy->id.name);
- continue;
- }
-
- BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
-
- /* We can only switch the proxy'ing to a made-local proxy if it is no longer
- * referred to from a library. Not checking for local use; if new local proxy
- * was not used locally would be a nasty bug! */
- if (is_local || is_lib) {
- CLOG_WARN(&LOG,
- "Made-local proxy object %s will lose its link to %s, "
- "because the linked-in proxy is referenced (is_local=%i, is_lib=%i)",
- id->newid->name,
- ob->proxy->id.name,
- is_local,
- is_lib);
- }
- else {
- /* we can switch the proxy'ing from the linked-in to the made-local proxy.
- * BKE_object_make_proxy() shouldn't be used here, as it allocates memory that
- * was already allocated by object_make_local() (which called BKE_object_copy). */
- ob_new->proxy = ob->proxy;
- ob_new->proxy_group = ob->proxy_group;
- ob_new->proxy_from = ob->proxy_from;
- ob_new->proxy->proxy_from = ob_new;
- ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
- }
- }
}
BKE_main_id_newptr_and_tag_clear(bmain);
+
+ blendfile_link_append_proxies_convert(bmain, reports);
}
void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
@@ -1361,6 +1331,10 @@ void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *re
.active_collection = NULL};
loose_data_instantiate(&instantiate_context);
}
+
+ if ((lapp_context->params->flag & FILE_LINK) != 0) {
+ blendfile_link_append_proxies_convert(lapp_context->params->bmain, reports);
+ }
}
/** \} */
@@ -1541,7 +1515,6 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
/* Note that in reload case, we also want to replace indirect usages. */
const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE |
- ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE |
(do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
for (item_idx = 0, itemlink = lapp_context->items.list; itemlink;
item_idx++, itemlink = itemlink->next) {
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index a4f3e84a2bf..275500ba2f6 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -116,12 +116,6 @@ static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
memcpy(r_edge, cddm->medge, sizeof(*r_edge) * dm->numEdgeData);
}
-static void cdDM_copyTessFaceArray(DerivedMesh *dm, MFace *r_face)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- memcpy(r_face, cddm->mface, sizeof(*r_face) * dm->numTessFaceData);
-}
-
static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@ -147,20 +141,6 @@ static void cdDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
copy_v3_v3(r_no, cddm->vert_normals[index]);
}
-static const MeshElemMap *cdDM_getPolyMap(Object *ob, DerivedMesh *dm)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
-
- if (!cddm->pmap && ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- BKE_mesh_vert_poly_map_create(
- &cddm->pmap, &cddm->pmap_mem, me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop);
- }
-
- return cddm->pmap;
-}
-
static void cdDM_recalc_looptri(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@ -216,24 +196,17 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->copyVertArray = cdDM_copyVertArray;
dm->copyEdgeArray = cdDM_copyEdgeArray;
- dm->copyTessFaceArray = cdDM_copyTessFaceArray;
dm->copyLoopArray = cdDM_copyLoopArray;
dm->copyPolyArray = cdDM_copyPolyArray;
- dm->getVertData = DM_get_vert_data;
- dm->getEdgeData = DM_get_edge_data;
- dm->getTessFaceData = DM_get_tessface_data;
dm->getVertDataArray = DM_get_vert_data_layer;
dm->getEdgeDataArray = DM_get_edge_data_layer;
- dm->getTessFaceDataArray = DM_get_tessface_data_layer;
dm->recalcLoopTri = cdDM_recalc_looptri;
dm->getVertCo = cdDM_getVertCo;
dm->getVertNo = cdDM_getVertNo;
- dm->getPolyMap = cdDM_getPolyMap;
-
dm->release = cdDM_release;
return cddm;
@@ -265,12 +238,6 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
dm->deformedOnly = 1;
dm->cd_flag = mesh->cd_flag;
- if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
- dm->dirty |= DM_DIRTY_NORMALS;
- }
- /* TODO: DM_DIRTY_TESS_CDLAYERS ? Maybe not though,
- * since we probably want to switch to looptris? */
-
CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, alloctype, mesh->totvert);
CustomData_merge(&mesh->edata, &dm->edgeData, cddata_masks.emask, alloctype, mesh->totedge);
CustomData_merge(&mesh->fdata,
@@ -282,7 +249,9 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, alloctype, mesh->totpoly);
cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
- cddm->vert_normals = CustomData_get_layer(&dm->vertData, CD_NORMAL);
+ /* Though this may be an unnecessary calculation, simply retrieving the layer may return nothing
+ * or dirty normals. */
+ cddm->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
@@ -327,12 +296,6 @@ DerivedMesh *CDDM_copy(DerivedMesh *source)
DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys);
dm->deformedOnly = source->deformedOnly;
dm->cd_flag = source->cd_flag;
- dm->dirty = source->dirty;
-
- /* Tessellation data is never copied, so tag it here.
- * Only tag dirty layers if we really ignored tessellation faces.
- */
- dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index f013ef99dde..3b7f91b93c0 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -5850,14 +5850,6 @@ static void add_new_constraint_to_list(Object *ob, bPoseChannel *pchan, bConstra
BLI_addtail(list, con);
BKE_constraint_unique_name(con, list);
- /* if the target list is a list on some PoseChannel belonging to a proxy-protected
- * Armature layer, we must tag newly added constraints with a flag which allows them
- * to persist after proxy syncing has been done
- */
- if (BKE_constraints_proxylocked_owner(ob, pchan)) {
- con->flag |= CONSTRAINT_PROXY_LOCAL;
- }
-
/* make this constraint the active one */
BKE_constraints_active_set(list, con);
}
@@ -6213,45 +6205,6 @@ bool BKE_constraint_is_nonlocal_in_liboverride(const Object *ob, const bConstrai
(con == NULL || (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) == 0));
}
-/* -------- Constraints and Proxies ------- */
-
-void BKE_constraints_proxylocal_extract(ListBase *dst, ListBase *src)
-{
- bConstraint *con, *next;
-
- /* for each tagged constraint, remove from src and move to dst */
- for (con = src->first; con; con = next) {
- next = con->next;
-
- /* check if tagged */
- if (con->flag & CONSTRAINT_PROXY_LOCAL) {
- BLI_remlink(src, con);
- BLI_addtail(dst, con);
- }
- }
-}
-
-bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan)
-{
- /* Currently, constraints can only be on object or bone level */
- if (ob && ob->proxy) {
- if (ob->pose && pchan) {
- bArmature *arm = ob->data;
-
- /* On bone-level, check if bone is on proxy-protected layer */
- if ((pchan->bone) && (pchan->bone->layer & arm->layer_protected)) {
- return true;
- }
- }
- else {
- /* FIXME: constraints on object-level are not handled well yet */
- return true;
- }
- }
-
- return false;
-}
-
/* -------- Target-Matrix Stuff ------- */
void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph,
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 573595b6f90..0bf83ed5036 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -194,13 +194,10 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
float (*mappedcos)[3],
float (*quats)[4])
{
- MVert *mvert = me->mvert;
- for (int i = 0; i < me->totvert; i++, mvert++) {
- mvert->flag &= ~ME_VERT_TMP_TAG;
- }
+ BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__);
/* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
- mvert = me->mvert;
+ MVert *mvert = me->mvert;
MPoly *mp = me->mpoly;
MLoop *mloop = me->mloop;
@@ -210,7 +207,7 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
MLoop *ml_prev = &ml_next[mp->totloop - 2];
for (int j = 0; j < mp->totloop; j++) {
- if ((mvert[ml_curr->v].flag & ME_VERT_TMP_TAG) == 0) {
+ if (!BLI_BITMAP_TEST(vert_tag, ml_curr->v)) {
const float *co_prev, *co_curr, *co_next; /* orig */
const float *vd_prev, *vd_curr, *vd_next; /* deform */
@@ -233,7 +230,7 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
set_crazy_vertex_quat(
quats[ml_curr->v], co_curr, co_next, co_prev, vd_curr, vd_next, vd_prev);
- mvert[ml_curr->v].flag |= ME_VERT_TMP_TAG;
+ BLI_BITMAP_ENABLE(vert_tag, ml_curr->v);
}
ml_prev = ml_curr;
@@ -241,6 +238,8 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
ml_next++;
}
}
+
+ MEM_freeN(vert_tag);
}
int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgraph,
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index e4c18325d76..36d511422aa 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -1793,10 +1793,10 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(float[3]), "vec3f", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 44: CD_RADIUS */
{sizeof(float), "MFloatProperty", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
- /* 45: CD_HAIRCURVE */
- {sizeof(HairCurve), "HairCurve", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
- /* 46: CD_HAIRMAPPING */
- {sizeof(HairMapping), "HairMapping", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
+ /* 45: CD_PROP_INT8 */
+ {sizeof(int8_t), "MInt8Property", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
+ /* 46: CD_HAIRMAPPING */ /* UNUSED */
+ {-1, "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 47: CD_PROP_COLOR */
{sizeof(MPropCol),
"MPropCol",
@@ -1914,7 +1914,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDCustomLoopNormal",
"CDSculptFaceGroups",
/* 43-46 */ "CDHairPoint",
- "CDHairCurve",
+ "CDPropInt8",
"CDHairMapping",
"CDPoint",
"CDPropCol",
@@ -2431,7 +2431,7 @@ const char *CustomData_get_active_layer_name(const struct CustomData *data, cons
{
/* Get the layer index of the active layer of this type. */
const int layer_index = CustomData_get_active_layer_index(data, type);
- return layer_index < 0 ? NULL : data->layers[layer_index].name;
+ return layer_index < 0 ? nullptr : data->layers[layer_index].name;
}
void CustomData_set_layer_active(CustomData *data, int type, int n)
@@ -2786,7 +2786,7 @@ void CustomData_free_layers_anonymous(struct CustomData *data, int totelem)
bool found_anonymous_layer = false;
for (int i = 0; i < data->totlayer; i++) {
const CustomDataLayer *layer = &data->layers[i];
- if (layer->anonymous_id != NULL) {
+ if (layer->anonymous_id != nullptr) {
CustomData_free_layer(data, layer->type, totelem, i);
found_anonymous_layer = true;
break;
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index ef789d3e39b..bc5a0ed1538 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -1985,9 +1985,6 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
}
MEM_freeN(fcolor);
-
- /* Mark tessellated CD layers as dirty. */
- // result->dirty |= DM_DIRTY_TESS_CDLAYERS;
}
/* vertex group paint */
else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c
index ce30f80ba65..e71217fea9e 100644
--- a/source/blender/blenkernel/intern/fcurve_driver.c
+++ b/source/blender/blenkernel/intern/fcurve_driver.c
@@ -88,14 +88,6 @@ typedef struct DriverVarTypeInfo {
/** \name Driver Target Utilities
* \{ */
-static ID *dtar_id_ensure_proxy_from(ID *id)
-{
- if (id && GS(id->name) == ID_OB && ((Object *)id)->proxy_from) {
- return (ID *)(((Object *)id)->proxy_from);
- }
- return id;
-}
-
/**
* Helper function to obtain a value using RNA from the specified source
* (for evaluating drivers).
@@ -113,7 +105,7 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
return 0.0f;
}
- id = dtar_id_ensure_proxy_from(dtar->id);
+ id = dtar->id;
/* Error check for missing pointer. */
if (id == NULL) {
@@ -217,7 +209,7 @@ bool driver_get_variable_property(ChannelDriver *driver,
return false;
}
- id = dtar_id_ensure_proxy_from(dtar->id);
+ id = dtar->id;
/* Error check for missing pointer. */
if (id == NULL) {
@@ -273,7 +265,7 @@ static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar)
short valid_targets = 0;
DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
- Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+ Object *ob = (Object *)dtar->id;
/* Check if this target has valid data. */
if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
@@ -328,7 +320,7 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
for (int i = 0; i < 2; i++) {
/* Get pointer to loc values to store in. */
DriverTarget *dtar = &dvar->targets[i];
- Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+ Object *ob = (Object *)dtar->id;
bPoseChannel *pchan;
/* After the checks above, the targets should be valid here. */
@@ -389,7 +381,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
/* NOTE: for now, these are all just world-space */
DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
/* Get pointer to loc values to store in. */
- Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+ Object *ob = (Object *)dtar->id;
bPoseChannel *pchan;
float tmp_loc[3];
@@ -472,7 +464,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
{
DriverTarget *dtar = &dvar->targets[0];
- Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+ Object *ob = (Object *)dtar->id;
bPoseChannel *pchan;
float mat[4][4];
float oldEul[3] = {0.0f, 0.0f, 0.0f};
diff --git a/source/blender/blenkernel/intern/hair.cc b/source/blender/blenkernel/intern/hair.cc
index b7ba159f631..bddadc3bcfd 100644
--- a/source/blender/blenkernel/intern/hair.cc
+++ b/source/blender/blenkernel/intern/hair.cc
@@ -28,10 +28,11 @@
#include "DNA_material_types.h"
#include "DNA_object_types.h"
+#include "BLI_index_range.hh"
#include "BLI_listbase.h"
#include "BLI_math_base.h"
#include "BLI_math_vec_types.hh"
-#include "BLI_rand.h"
+#include "BLI_rand.hh"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -54,6 +55,9 @@
#include "BLO_read_write.h"
using blender::float3;
+using blender::IndexRange;
+using blender::MutableSpan;
+using blender::RandomNumberGenerator;
static const char *HAIR_ATTR_POSITION = "position";
static const char *HAIR_ATTR_RADIUS = "radius";
@@ -69,14 +73,22 @@ static void hair_init_data(ID *id)
MEMCPY_STRUCT_AFTER(hair, DNA_struct_default_get(Hair), id);
- CustomData_reset(&hair->pdata);
- CustomData_reset(&hair->cdata);
+ CustomData_reset(&hair->geometry.point_data);
+ CustomData_reset(&hair->geometry.curve_data);
+
+ CustomData_add_layer_named(&hair->geometry.point_data,
+ CD_PROP_FLOAT3,
+ CD_CALLOC,
+ nullptr,
+ hair->geometry.point_size,
+ HAIR_ATTR_POSITION);
+ CustomData_add_layer_named(&hair->geometry.point_data,
+ CD_PROP_FLOAT,
+ CD_CALLOC,
+ nullptr,
+ hair->geometry.point_size,
+ HAIR_ATTR_RADIUS);
- CustomData_add_layer_named(
- &hair->pdata, CD_PROP_FLOAT3, CD_CALLOC, nullptr, hair->totpoint, HAIR_ATTR_POSITION);
- CustomData_add_layer_named(
- &hair->pdata, CD_PROP_FLOAT, CD_CALLOC, nullptr, hair->totpoint, HAIR_ATTR_RADIUS);
- CustomData_add_layer(&hair->cdata, CD_HAIRCURVE, CD_CALLOC, nullptr, hair->totcurve);
BKE_hair_update_customdata_pointers(hair);
hair_random(hair);
@@ -88,11 +100,24 @@ static void hair_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, co
const Hair *hair_src = (const Hair *)id_src;
hair_dst->mat = static_cast<Material **>(MEM_dupallocN(hair_src->mat));
+ hair_dst->geometry.point_size = hair_src->geometry.point_size;
+ hair_dst->geometry.curve_size = hair_src->geometry.curve_size;
+
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
- CustomData_copy(&hair_src->pdata, &hair_dst->pdata, CD_MASK_ALL, alloc_type, hair_dst->totpoint);
- CustomData_copy(&hair_src->cdata, &hair_dst->cdata, CD_MASK_ALL, alloc_type, hair_dst->totcurve);
+ CustomData_copy(&hair_src->geometry.point_data,
+ &hair_dst->geometry.point_data,
+ CD_MASK_ALL,
+ alloc_type,
+ hair_dst->geometry.point_size);
+ CustomData_copy(&hair_src->geometry.curve_data,
+ &hair_dst->geometry.curve_data,
+ CD_MASK_ALL,
+ alloc_type,
+ hair_dst->geometry.curve_size);
BKE_hair_update_customdata_pointers(hair_dst);
+ hair_dst->geometry.offsets = static_cast<int *>(MEM_dupallocN(hair_src->geometry.offsets));
+
hair_dst->batch_cache = nullptr;
}
@@ -103,8 +128,10 @@ static void hair_free_data(ID *id)
BKE_hair_batch_cache_free(hair);
- CustomData_free(&hair->pdata, hair->totpoint);
- CustomData_free(&hair->cdata, hair->totcurve);
+ CustomData_free(&hair->geometry.point_data, hair->geometry.point_size);
+ CustomData_free(&hair->geometry.curve_data, hair->geometry.curve_size);
+
+ MEM_SAFE_FREE(hair->geometry.offsets);
MEM_SAFE_FREE(hair->mat);
}
@@ -123,16 +150,30 @@ static void hair_blend_write(BlendWriter *writer, ID *id, const void *id_address
CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE];
CustomDataLayer *clayers = nullptr, clayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomData_blend_write_prepare(&hair->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
- CustomData_blend_write_prepare(&hair->cdata, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
+ CustomData_blend_write_prepare(
+ &hair->geometry.point_data, &players, players_buff, ARRAY_SIZE(players_buff));
+ CustomData_blend_write_prepare(
+ &hair->geometry.curve_data, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
/* Write LibData */
BLO_write_id_struct(writer, Hair, id_address, &hair->id);
BKE_id_blend_write(writer, &hair->id);
/* Direct data */
- CustomData_blend_write(writer, &hair->pdata, players, hair->totpoint, CD_MASK_ALL, &hair->id);
- CustomData_blend_write(writer, &hair->cdata, clayers, hair->totcurve, CD_MASK_ALL, &hair->id);
+ CustomData_blend_write(writer,
+ &hair->geometry.point_data,
+ players,
+ hair->geometry.point_size,
+ CD_MASK_ALL,
+ &hair->id);
+ CustomData_blend_write(writer,
+ &hair->geometry.curve_data,
+ clayers,
+ hair->geometry.curve_size,
+ CD_MASK_ALL,
+ &hair->id);
+
+ BLO_write_int32_array(writer, hair->geometry.curve_size + 1, hair->geometry.offsets);
BLO_write_pointer_array(writer, hair->totcol, hair->mat);
if (hair->adt) {
@@ -155,10 +196,12 @@ static void hair_blend_read_data(BlendDataReader *reader, ID *id)
BKE_animdata_blend_read_data(reader, hair->adt);
/* Geometry */
- CustomData_blend_read(reader, &hair->pdata, hair->totpoint);
- CustomData_blend_read(reader, &hair->cdata, hair->totcurve);
+ CustomData_blend_read(reader, &hair->geometry.point_data, hair->geometry.point_size);
+ CustomData_blend_read(reader, &hair->geometry.curve_data, hair->geometry.point_size);
BKE_hair_update_customdata_pointers(hair);
+ BLO_read_int32_array(reader, hair->geometry.curve_size + 1, &hair->geometry.offsets);
+
/* Materials */
BLO_read_pointer_array(reader, (void **)&hair->mat);
}
@@ -211,47 +254,51 @@ IDTypeInfo IDType_ID_HA = {
static void hair_random(Hair *hair)
{
+ CurvesGeometry &geometry = hair->geometry;
const int numpoints = 8;
- hair->totcurve = 500;
- hair->totpoint = hair->totcurve * numpoints;
+ geometry.curve_size = 500;
+
+ geometry.curve_size = 500;
+ geometry.point_size = geometry.curve_size * numpoints;
- CustomData_realloc(&hair->pdata, hair->totpoint);
- CustomData_realloc(&hair->cdata, hair->totcurve);
+ hair->geometry.offsets = (int *)MEM_calloc_arrayN(
+ hair->geometry.curve_size + 1, sizeof(int), __func__);
+ CustomData_realloc(&geometry.point_data, geometry.point_size);
+ CustomData_realloc(&geometry.curve_data, geometry.curve_size);
BKE_hair_update_customdata_pointers(hair);
- RNG *rng = BLI_rng_new(0);
+ MutableSpan<int> offsets{geometry.offsets, geometry.curve_size + 1};
+ MutableSpan<float3> positions{(float3 *)geometry.position, geometry.point_size};
+ MutableSpan<float> radii{geometry.radius, geometry.point_size};
- for (int i = 0; i < hair->totcurve; i++) {
- HairCurve *curve = &hair->curves[i];
- curve->firstpoint = i * numpoints;
- curve->numpoints = numpoints;
+ for (const int i : offsets.index_range()) {
+ geometry.offsets[i] = numpoints * i;
+ }
+
+ RandomNumberGenerator rng;
- float theta = 2.0f * M_PI * BLI_rng_get_float(rng);
- float phi = saacosf(2.0f * BLI_rng_get_float(rng) - 1.0f);
+ for (int i = 0; i < geometry.curve_size; i++) {
+ const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
+ MutableSpan<float3> curve_positions = positions.slice(curve_range);
+ MutableSpan<float> curve_radii = radii.slice(curve_range);
- float no[3] = {sinf(theta) * sinf(phi), cosf(theta) * sinf(phi), cosf(phi)};
- normalize_v3(no);
+ const float theta = 2.0f * M_PI * rng.get_float();
+ const float phi = saacosf(2.0f * rng.get_float() - 1.0f);
- float co[3];
- copy_v3_v3(co, no);
+ float3 no = {std::sin(theta) * std::sin(phi), std::cos(theta) * std::sin(phi), std::cos(phi)};
+ no = blender::math::normalize(no);
- float(*curve_co)[3] = hair->co + curve->firstpoint;
- float *curve_radius = hair->radius + curve->firstpoint;
+ float3 co = no;
for (int key = 0; key < numpoints; key++) {
float t = key / (float)(numpoints - 1);
- copy_v3_v3(curve_co[key], co);
- curve_radius[key] = 0.02f * (1.0f - t);
-
- float offset[3] = {2.0f * BLI_rng_get_float(rng) - 1.0f,
- 2.0f * BLI_rng_get_float(rng) - 1.0f,
- 2.0f * BLI_rng_get_float(rng) - 1.0f};
- add_v3_v3(offset, no);
- madd_v3_v3fl(co, offset, 1.0f / numpoints);
+ curve_positions[key] = co;
+ curve_radii[key] = 0.02f * (1.0f - t);
+
+ float3 offset = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f;
+ co += (offset + no) / numpoints;
}
}
-
- BLI_rng_free(rng);
}
void *BKE_hair_add(Main *bmain, const char *name)
@@ -276,9 +323,9 @@ BoundBox *BKE_hair_boundbox_get(Object *ob)
float min[3], max[3];
INIT_MINMAX(min, max);
- float(*hair_co)[3] = hair->co;
- float *hair_radius = hair->radius;
- for (int a = 0; a < hair->totpoint; a++) {
+ float(*hair_co)[3] = hair->geometry.position;
+ float *hair_radius = hair->geometry.radius;
+ for (int a = 0; a < hair->geometry.point_size; a++) {
float *co = hair_co[a];
float radius = (hair_radius) ? hair_radius[a] : 0.0f;
const float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius};
@@ -295,12 +342,10 @@ BoundBox *BKE_hair_boundbox_get(Object *ob)
void BKE_hair_update_customdata_pointers(Hair *hair)
{
- hair->co = (float(*)[3])CustomData_get_layer_named(
- &hair->pdata, CD_PROP_FLOAT3, HAIR_ATTR_POSITION);
- hair->radius = (float *)CustomData_get_layer_named(
- &hair->pdata, CD_PROP_FLOAT, HAIR_ATTR_RADIUS);
- hair->curves = (HairCurve *)CustomData_get_layer(&hair->cdata, CD_HAIRCURVE);
- hair->mapping = (HairMaping *)CustomData_get_layer(&hair->cdata, CD_HAIRMAPPING);
+ hair->geometry.position = (float(*)[3])CustomData_get_layer_named(
+ &hair->geometry.point_data, CD_PROP_FLOAT3, HAIR_ATTR_POSITION);
+ hair->geometry.radius = (float *)CustomData_get_layer_named(
+ &hair->geometry.point_data, CD_PROP_FLOAT, HAIR_ATTR_RADIUS);
}
bool BKE_hair_customdata_required(Hair *UNUSED(hair), CustomDataLayer *layer)
@@ -318,10 +363,18 @@ Hair *BKE_hair_new_for_eval(const Hair *hair_src, int totpoint, int totcurve)
hair_dst->mat = static_cast<Material **>(MEM_dupallocN(hair_src->mat));
hair_dst->totcol = hair_src->totcol;
- hair_dst->totpoint = totpoint;
- hair_dst->totcurve = totcurve;
- CustomData_copy(&hair_src->pdata, &hair_dst->pdata, CD_MASK_ALL, CD_CALLOC, totpoint);
- CustomData_copy(&hair_src->cdata, &hair_dst->cdata, CD_MASK_ALL, CD_CALLOC, totcurve);
+ hair_dst->geometry.point_size = totpoint;
+ hair_dst->geometry.curve_size = totcurve;
+ CustomData_copy(&hair_src->geometry.point_data,
+ &hair_dst->geometry.point_data,
+ CD_MASK_ALL,
+ CD_CALLOC,
+ totpoint);
+ CustomData_copy(&hair_src->geometry.curve_data,
+ &hair_dst->geometry.curve_data,
+ CD_MASK_ALL,
+ CD_CALLOC,
+ totcurve);
BKE_hair_update_customdata_pointers(hair_dst);
return hair_dst;
@@ -373,28 +426,14 @@ static Hair *hair_evaluate_modifiers(struct Depsgraph *depsgraph,
}
/* Ensure we are not overwriting referenced data. */
- CustomData_duplicate_referenced_layer_named(
- &hair->pdata, CD_PROP_FLOAT3, HAIR_ATTR_POSITION, hair->totpoint);
+ CustomData_duplicate_referenced_layer_named(&hair->geometry.point_data,
+ CD_PROP_FLOAT3,
+ HAIR_ATTR_POSITION,
+ hair->geometry.point_size);
BKE_hair_update_customdata_pointers(hair);
/* Created deformed coordinates array on demand. */
- mti->deformVerts(md, &mectx, nullptr, hair->co, hair->totpoint);
- }
- else if (mti->modifyHair) {
- /* Ensure we are not modifying the input. */
- if (hair == hair_input) {
- hair = BKE_hair_copy_for_eval(hair, true);
- }
-
- Hair *hair_next = mti->modifyHair(md, &mectx, hair);
-
- if (hair_next && hair_next != hair) {
- /* If the modifier returned a new hair, release the old one. */
- if (hair != hair_input) {
- BKE_id_free(nullptr, hair);
- }
- hair = hair_next;
- }
+ mti->deformVerts(md, &mectx, nullptr, hair->geometry.position, hair->geometry.point_size);
}
}
diff --git a/source/blender/blenkernel/intern/image_partial_update.cc b/source/blender/blenkernel/intern/image_partial_update.cc
index 7e187c2014e..876e5276e5a 100644
--- a/source/blender/blenkernel/intern/image_partial_update.cc
+++ b/source/blender/blenkernel/intern/image_partial_update.cc
@@ -23,8 +23,8 @@
* image that are changed. These areas are organized in chunks. Changes that happen over time are
* organized in changesets.
*
- * A common usecase is to update GPUTexture for drawing where only that part is uploaded that only
- * changed.
+ * A common use case is to update #GPUTexture for drawing where only that part is uploaded that
+ * only changed.
*
* Usage:
*
@@ -273,7 +273,8 @@ struct TileChangeset {
const int previous_chunk_len = chunk_dirty_flags_.size();
chunk_dirty_flags_.resize(chunk_len);
- /* Fast exit. When the changeset was already empty no need to re-init the chunk_validity. */
+ /* Fast exit. When the changeset was already empty no need to
+ * re-initialize the chunk_validity. */
if (!has_dirty_chunks()) {
return;
}
diff --git a/source/blender/blenkernel/intern/image_partial_update_test.cc b/source/blender/blenkernel/intern/image_partial_update_test.cc
index 70aa51f7c98..bf12c27241e 100644
--- a/source/blender/blenkernel/intern/image_partial_update_test.cc
+++ b/source/blender/blenkernel/intern/image_partial_update_test.cc
@@ -70,7 +70,7 @@ class ImagePartialUpdateTest : public testing::Test {
IMB_init();
bmain = BKE_main_new();
- /* Creating an image generates a mem-leak during tests. */
+ /* Creating an image generates a memory-leak during tests. */
image = create_test_image(1024, 1024);
image_tile = BKE_image_get_tile(image, 0);
image_buffer = BKE_image_acquire_ibuf(image, nullptr, nullptr);
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 49a518607f1..6c19c7a328b 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1918,7 +1918,6 @@ void BKE_library_make_local(Main *bmain,
* but complicates slightly the pre-processing of relations between IDs at step 2... */
else if (!do_skip && id->tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW) &&
ELEM(lib, NULL, id->lib) &&
- !(GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) &&
((untagged_only == false) || !(id->tag & LIB_TAG_PRE_EXISTING))) {
BLI_linklist_prepend_arena(&todo_ids, id, linklist_mem);
id->tag |= LIB_TAG_DOIT;
@@ -1982,12 +1981,8 @@ void BKE_library_make_local(Main *bmain,
}
}
else {
- /* In this specific case, we do want to make ID local even if it has no local usage yet...
- * Note that for objects, we don't want proxy pointers to be cleared yet. This will happen
- * down the road in this function.
- */
- BKE_lib_id_make_local(
- bmain, id, LIB_ID_MAKELOCAL_FULL_LIBRARY | LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING);
+ /* In this specific case, we do want to make ID local even if it has no local usage yet... */
+ BKE_lib_id_make_local(bmain, id, LIB_ID_MAKELOCAL_FULL_LIBRARY);
if (id->newid) {
if (GS(id->newid->name) == ID_OB) {
@@ -2049,62 +2044,6 @@ void BKE_library_make_local(Main *bmain,
TIMEIT_VALUE_PRINT(make_local);
#endif
- /* Step 5: proxy 'remapping' hack. */
- for (LinkNode *it = copied_ids; it; it = it->next) {
- ID *id = it->link;
-
- /* Attempt to re-link copied proxy objects. This allows appending of an entire scene
- * from another blend file into this one, even when that blend file contains proxified
- * armatures that have local references. Since the proxified object needs to be linked
- * (not local), this will only work when the "Localize all" checkbox is disabled.
- * TL;DR: this is a dirty hack on top of an already weak feature (proxies). */
- if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) {
- Object *ob = (Object *)id;
- Object *ob_new = (Object *)id->newid;
- bool is_local = false, is_lib = false;
-
- /* Proxies only work when the proxified object is linked-in from a library. */
- if (!ID_IS_LINKED(ob->proxy)) {
- CLOG_WARN(&LOG,
- "proxy object %s will lose its link to %s, because the "
- "proxified object is local.",
- id->newid->name,
- ob->proxy->id.name);
- continue;
- }
-
- BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
-
- /* We can only switch the proxy'ing to a made-local proxy if it is no longer
- * referred to from a library. Not checking for local use; if new local proxy
- * was not used locally would be a nasty bug! */
- if (is_local || is_lib) {
- CLOG_WARN(&LOG,
- "made-local proxy object %s will lose its link to %s, "
- "because the linked-in proxy is referenced (is_local=%i, is_lib=%i).",
- id->newid->name,
- ob->proxy->id.name,
- is_local,
- is_lib);
- }
- else {
- /* we can switch the proxy'ing from the linked-in to the made-local proxy.
- * BKE_object_make_proxy() shouldn't be used here, as it allocates memory that
- * was already allocated by object_make_local() (which called BKE_object_copy). */
- ob_new->proxy = ob->proxy;
- ob_new->proxy_group = ob->proxy_group;
- ob_new->proxy_from = ob->proxy_from;
- ob_new->proxy->proxy_from = ob_new;
- ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
- }
- }
- }
-
-#ifdef DEBUG_TIME
- printf("Step 5: Proxy 'remapping' hack: Done.\n");
- TIMEIT_VALUE_PRINT(make_local);
-#endif
-
/* This is probably more of a hack than something we should do here, but...
* Issue is, the whole copying + remapping done in complex cases above may leave pose-channels
* of armatures in complete invalid state (more precisely, the bone pointers of the
diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c
index f4dd67cac28..5db70d85e71 100644
--- a/source/blender/blenkernel/intern/lib_id_delete.c
+++ b/source/blender/blenkernel/intern/lib_id_delete.c
@@ -265,8 +265,8 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
}
for (id = last_remapped_id->next; id; id = id->next) {
/* Will tag 'never NULL' users of this ID too.
- * Note that we cannot use BKE_libblock_unlink() here,
- * since it would ignore indirect (and proxy!)
+ *
+ * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
* links, this can lead to nasty crashing here in second, actual deleting loop.
* Also, this will also flag users of deleted data that cannot be unlinked
* (object using deleted obdata, etc.), so that they also get deleted. */
@@ -315,9 +315,9 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
}
/* Will tag 'never NULL' users of this ID too.
- * Note that we cannot use BKE_libblock_unlink() here, since it would ignore indirect
- * (and proxy!) links, this can lead to nasty crashing here in second,
- * actual deleting loop.
+ *
+ * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
+ * links, this can lead to nasty crashing here in second, actual deleting loop.
* Also, this will also flag users of deleted data that cannot be unlinked
* (object using deleted obdata, etc.), so that they also get deleted. */
BKE_libblock_remap_multiple_locked(bmain,
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 649e7dab5d1..314351e4ad7 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -211,6 +211,7 @@ void BKE_lib_override_library_free(struct IDOverrideLibrary **override, const bo
}
static ID *lib_override_library_create_from(Main *bmain,
+ Library *owner_library,
ID *reference_id,
const int lib_id_copy_flags)
{
@@ -227,6 +228,12 @@ static ID *lib_override_library_create_from(Main *bmain,
}
id_us_min(local_id);
+ /* TODO: Handle this properly in LIB_NO_MAIN case as well (i.e. resync case). Or offload to
+ * generic ID copy code? */
+ if ((lib_id_copy_flags & LIB_ID_CREATE_NO_MAIN) == 0) {
+ local_id->lib = owner_library;
+ }
+
BKE_lib_override_library_init(local_id, reference_id);
/* NOTE: From liboverride perspective (and RNA one), shape keys are considered as local embedded
@@ -281,7 +288,7 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
BLI_assert(reference_id != NULL);
BLI_assert(ID_IS_LINKED(reference_id));
- ID *local_id = lib_override_library_create_from(bmain, reference_id, 0);
+ ID *local_id = lib_override_library_create_from(bmain, NULL, reference_id, 0);
/* We cannot allow automatic hierarchy resync on this ID, it is highly likely to generate a giant
* mess in case there are a lot of hidden, non-instantiated, non-properly organized dependencies.
* Ref T94650. */
@@ -320,6 +327,7 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
}
bool BKE_lib_override_library_create_from_tag(Main *bmain,
+ Library *owner_library,
const Library *reference_library,
const bool do_no_main)
{
@@ -351,7 +359,7 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
* This requires extra care further down the resync process,
* see: #BKE_lib_override_library_resync. */
reference_id->newid = lib_override_library_create_from(
- bmain, reference_id, do_no_main ? LIB_ID_CREATE_NO_MAIN : 0);
+ bmain, owner_library, reference_id, do_no_main ? LIB_ID_CREATE_NO_MAIN : 0);
if (reference_id->newid == NULL) {
success = false;
break;
@@ -835,7 +843,10 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data)
lib_override_overrides_group_tag_recursive(data);
}
-static bool lib_override_library_create_do(Main *bmain, Scene *scene, ID *id_root)
+static bool lib_override_library_create_do(Main *bmain,
+ Scene *scene,
+ Library *owner_library,
+ ID *id_root)
{
BKE_main_relations_create(bmain, 0);
LibOverrideGroupTagData data = {.bmain = bmain,
@@ -854,12 +865,13 @@ static bool lib_override_library_create_do(Main *bmain, Scene *scene, ID *id_roo
BKE_main_relations_free(bmain);
lib_override_group_tag_data_clear(&data);
- return BKE_lib_override_library_create_from_tag(bmain, id_root->lib, false);
+ return BKE_lib_override_library_create_from_tag(bmain, owner_library, id_root->lib, false);
}
static void lib_override_library_create_post_process(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
+ const Library *owner_library,
ID *id_root,
ID *id_reference,
Collection *residual_storage,
@@ -881,7 +893,8 @@ static void lib_override_library_create_post_process(Main *bmain,
/* Instantiating the root collection or object should never be needed in resync case, since the
* old override would be remapped to the new one. */
- if (!is_resync && id_root != NULL && id_root->newid != NULL && !ID_IS_LINKED(id_root->newid)) {
+ if (!is_resync && id_root != NULL && id_root->newid != NULL &&
+ (!ID_IS_LINKED(id_root->newid) || id_root->newid->lib == owner_library)) {
switch (GS(id_root->name)) {
case ID_GR: {
Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ?
@@ -926,7 +939,7 @@ static void lib_override_library_create_post_process(Main *bmain,
Collection *default_instantiating_collection = residual_storage;
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
Object *ob_new = (Object *)ob->id.newid;
- if (ob_new == NULL || ID_IS_LINKED(ob_new)) {
+ if (ob_new == NULL || (ID_IS_LINKED(ob_new) && ob_new->id.lib != owner_library)) {
continue;
}
@@ -989,6 +1002,7 @@ static void lib_override_library_create_post_process(Main *bmain,
bool BKE_lib_override_library_create(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
+ Library *owner_library,
ID *id_root,
ID *id_reference,
ID **r_id_root_override)
@@ -997,7 +1011,7 @@ bool BKE_lib_override_library_create(Main *bmain,
*r_id_root_override = NULL;
}
- const bool success = lib_override_library_create_do(bmain, scene, id_root);
+ const bool success = lib_override_library_create_do(bmain, scene, owner_library, id_root);
if (!success) {
return success;
@@ -1008,7 +1022,7 @@ bool BKE_lib_override_library_create(Main *bmain,
}
lib_override_library_create_post_process(
- bmain, scene, view_layer, id_root, id_reference, NULL, false);
+ bmain, scene, view_layer, owner_library, id_root, id_reference, NULL, false);
/* Cleanup. */
BKE_main_id_newptr_and_tag_clear(bmain);
@@ -1033,122 +1047,6 @@ bool BKE_lib_override_library_template_create(struct ID *id)
return true;
}
-bool BKE_lib_override_library_proxy_convert(Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- Object *ob_proxy)
-{
- /* `proxy_group`, if defined, is the empty instantiating the collection from which the proxy is
- * coming. */
- Object *ob_proxy_group = ob_proxy->proxy_group;
- const bool is_override_instancing_object = ob_proxy_group != NULL;
- ID *id_root = is_override_instancing_object ? &ob_proxy_group->instance_collection->id :
- &ob_proxy->proxy->id;
- ID *id_reference = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id;
-
- /* In some cases the instance collection of a proxy object may be local (see e.g. T83875). Not
- * sure this is a valid state, but for now just abort the overriding process. */
- if (!ID_IS_OVERRIDABLE_LIBRARY(id_root)) {
- return false;
- }
-
- /* We manually convert the proxy object into a library override, further override handling will
- * then be handled by `BKE_lib_override_library_create()` just as for a regular override
- * creation.
- */
- ob_proxy->proxy->id.tag |= LIB_TAG_DOIT;
- ob_proxy->proxy->id.newid = &ob_proxy->id;
- BKE_lib_override_library_init(&ob_proxy->id, &ob_proxy->proxy->id);
-
- ob_proxy->proxy->proxy_from = NULL;
- ob_proxy->proxy = ob_proxy->proxy_group = NULL;
-
- DEG_id_tag_update(&ob_proxy->id, ID_RECALC_COPY_ON_WRITE);
-
- /* In case of proxy conversion, remap all local ID usages to linked IDs to their newly created
- * overrides.
- * While this might not be 100% the desired behavior, it is likely to be the case most of the
- * time. Ref: T91711. */
- ID *id_iter;
- FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
- if (!ID_IS_LINKED(id_iter)) {
- id_iter->tag |= LIB_TAG_DOIT;
- }
- }
- FOREACH_MAIN_ID_END;
-
- return BKE_lib_override_library_create(bmain, scene, view_layer, id_root, id_reference, NULL);
-}
-
-static void lib_override_library_proxy_convert_do(Main *bmain,
- Scene *scene,
- Object *ob_proxy,
- BlendFileReadReport *reports)
-{
- Object *ob_proxy_group = ob_proxy->proxy_group;
- const bool is_override_instancing_object = ob_proxy_group != NULL;
-
- const bool success = BKE_lib_override_library_proxy_convert(bmain, scene, NULL, ob_proxy);
-
- if (success) {
- CLOG_INFO(&LOG,
- 4,
- "Proxy object '%s' successfully converted to library overrides",
- ob_proxy->id.name);
- /* Remove the instance empty from this scene, the items now have an overridden collection
- * instead. */
- if (is_override_instancing_object) {
- BKE_scene_collections_object_remove(bmain, scene, ob_proxy_group, true);
- }
- reports->count.proxies_to_lib_overrides_success++;
- }
-}
-
-void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadReport *reports)
-{
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- LinkNodePair proxy_objects = {NULL};
-
- FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
- if (object->proxy_group != NULL) {
- BLI_linklist_append(&proxy_objects, object);
- }
- }
- FOREACH_SCENE_OBJECT_END;
-
- FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
- if (object->proxy != NULL && object->proxy_group == NULL) {
- BLI_linklist_append(&proxy_objects, object);
- }
- }
- FOREACH_SCENE_OBJECT_END;
-
- for (LinkNode *proxy_object_iter = proxy_objects.list; proxy_object_iter != NULL;
- proxy_object_iter = proxy_object_iter->next) {
- Object *proxy_object = proxy_object_iter->link;
- lib_override_library_proxy_convert_do(bmain, scene, proxy_object, reports);
- }
-
- BLI_linklist_free(proxy_objects.list, NULL);
- }
-
- LISTBASE_FOREACH (Object *, object, &bmain->objects) {
- if (ID_IS_LINKED(object)) {
- if (object->proxy != NULL) {
- CLOG_WARN(&LOG, "Did not try to convert linked proxy object '%s'", object->id.name);
- reports->count.linked_proxies++;
- }
- continue;
- }
-
- if (object->proxy_group != NULL || object->proxy != NULL) {
- CLOG_WARN(
- &LOG, "Proxy object '%s' failed to be converted to library override", object->id.name);
- reports->count.proxies_to_lib_overrides_failures++;
- }
- }
-}
-
static void lib_override_library_remap(Main *bmain,
const ID *id_root_reference,
GHash *linkedref_to_old_override)
@@ -1316,7 +1214,7 @@ static bool lib_override_library_resync(Main *bmain,
* override IDs (including within the old overrides themselves, since those are tagged too
* above). */
const bool success = BKE_lib_override_library_create_from_tag(
- bmain, id_root_reference->lib, true);
+ bmain, NULL, id_root_reference->lib, true);
if (!success) {
return success;
@@ -1530,6 +1428,7 @@ static bool lib_override_library_resync(Main *bmain,
lib_override_library_create_post_process(bmain,
scene,
view_layer,
+ NULL,
id_root_reference,
id_root,
override_resync_residual_storage,
@@ -1954,7 +1853,7 @@ void BKE_lib_override_library_main_resync(Main *bmain,
/* Essentially ensures that potentially new overrides of new objects will be instantiated. */
lib_override_library_create_post_process(
- bmain, scene, view_layer, NULL, NULL, override_resync_residual_storage, true);
+ bmain, scene, view_layer, NULL, NULL, NULL, override_resync_residual_storage, true);
if (BKE_collection_is_empty(override_resync_residual_storage)) {
BKE_collection_delete(bmain, override_resync_residual_storage, true);
diff --git a/source/blender/blenkernel/intern/lib_override_proxy_conversion.c b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c
new file mode 100644
index 00000000000..d99a9b57a6e
--- /dev/null
+++ b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c
@@ -0,0 +1,176 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "CLG_log.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_linklist.h"
+
+/* Required for proxy to liboverrides conversion code. */
+#define DNA_DEPRECATED_ALLOW
+
+#include "DNA_ID.h"
+#include "DNA_collection_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "DEG_depsgraph.h"
+
+#include "BKE_collection.h"
+#include "BKE_idtype.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
+#include "BKE_main.h"
+
+#include "BLO_readfile.h"
+
+static CLG_LogRef LOG = {"bke.liboverride_proxy_conversion"};
+
+bool BKE_lib_override_library_proxy_convert(Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer,
+ Object *ob_proxy)
+{
+ /* `proxy_group`, if defined, is the empty instantiating the collection from which the proxy is
+ * coming. */
+ Object *ob_proxy_group = ob_proxy->proxy_group;
+ const bool is_override_instancing_object = ob_proxy_group != NULL;
+ ID *id_root = is_override_instancing_object ? &ob_proxy_group->instance_collection->id :
+ &ob_proxy->proxy->id;
+ ID *id_reference = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id;
+
+ /* In some cases the instance collection of a proxy object may be local (see e.g. T83875). Not
+ * sure this is a valid state, but for now just abort the overriding process. */
+ if (!ID_IS_OVERRIDABLE_LIBRARY_HIERARCHY(id_root)) {
+ if (ob_proxy->proxy != NULL) {
+ ob_proxy->proxy->proxy_from = NULL;
+ }
+ id_us_min((ID *)ob_proxy->proxy);
+ ob_proxy->proxy = ob_proxy->proxy_group = NULL;
+ return false;
+ }
+
+ /* We manually convert the proxy object into a library override, further override handling will
+ * then be handled by `BKE_lib_override_library_create()` just as for a regular override
+ * creation.
+ */
+ ob_proxy->proxy->id.tag |= LIB_TAG_DOIT;
+ ob_proxy->proxy->id.newid = &ob_proxy->id;
+ BKE_lib_override_library_init(&ob_proxy->id, &ob_proxy->proxy->id);
+
+ ob_proxy->proxy->proxy_from = NULL;
+ ob_proxy->proxy = ob_proxy->proxy_group = NULL;
+
+ DEG_id_tag_update(&ob_proxy->id, ID_RECALC_COPY_ON_WRITE);
+
+ /* In case of proxy conversion, remap all local ID usages to linked IDs to their newly created
+ * overrides. Also do that for the IDs from the same lib as the proxy in case it is linked.
+ * While this might not be 100% the desired behavior, it is likely to be the case most of the
+ * time. Ref: T91711. */
+ ID *id_iter;
+ FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
+ if (!ID_IS_LINKED(id_iter) || id_iter->lib == ob_proxy->id.lib) {
+ id_iter->tag |= LIB_TAG_DOIT;
+ }
+ }
+ FOREACH_MAIN_ID_END;
+
+ return BKE_lib_override_library_create(
+ bmain, scene, view_layer, ob_proxy->id.lib, id_root, id_reference, NULL);
+}
+
+static void lib_override_library_proxy_convert_do(Main *bmain,
+ Scene *scene,
+ Object *ob_proxy,
+ BlendFileReadReport *reports)
+{
+ Object *ob_proxy_group = ob_proxy->proxy_group;
+ const bool is_override_instancing_object = ob_proxy_group != NULL;
+
+ const bool success = BKE_lib_override_library_proxy_convert(bmain, scene, NULL, ob_proxy);
+
+ if (success) {
+ CLOG_INFO(&LOG,
+ 4,
+ "Proxy object '%s' successfully converted to library overrides",
+ ob_proxy->id.name);
+ /* Remove the instance empty from this scene, the items now have an overridden collection
+ * instead. */
+ if (is_override_instancing_object) {
+ BKE_scene_collections_object_remove(bmain, scene, ob_proxy_group, true);
+ }
+ reports->count.proxies_to_lib_overrides_success++;
+ }
+}
+
+void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadReport *reports)
+{
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ LinkNodePair proxy_objects = {NULL};
+
+ FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
+ if (object->proxy_group != NULL) {
+ BLI_linklist_append(&proxy_objects, object);
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+
+ FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
+ if (object->proxy != NULL && object->proxy_group == NULL) {
+ BLI_linklist_append(&proxy_objects, object);
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+
+ for (LinkNode *proxy_object_iter = proxy_objects.list; proxy_object_iter != NULL;
+ proxy_object_iter = proxy_object_iter->next) {
+ Object *proxy_object = proxy_object_iter->link;
+ lib_override_library_proxy_convert_do(bmain, scene, proxy_object, reports);
+ }
+
+ BLI_linklist_free(proxy_objects.list, NULL);
+ }
+
+ LISTBASE_FOREACH (Object *, object, &bmain->objects) {
+ if (object->proxy_group != NULL || object->proxy != NULL) {
+ if (ID_IS_LINKED(object)) {
+ CLOG_WARN(&LOG,
+ "Linked proxy object '%s' from '%s' failed to be converted to library override",
+ object->id.name + 2,
+ object->id.lib->filepath);
+ }
+ else {
+ CLOG_WARN(&LOG,
+ "Proxy object '%s' failed to be converted to library override",
+ object->id.name + 2);
+ }
+ reports->count.proxies_to_lib_overrides_failures++;
+ if (object->proxy != NULL) {
+ object->proxy->proxy_from = NULL;
+ }
+ id_us_min((ID *)object->proxy);
+ object->proxy = object->proxy_group = NULL;
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c
index 1f20a84098c..e73b53c4bf8 100644
--- a/source/blender/blenkernel/intern/lib_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -517,7 +517,7 @@ static int foreach_libblock_id_users_callback(LibraryIDLinkCallbackData *cb_data
IDUsersIter *iter = cb_data->user_data;
if (*id_p) {
- /* 'Loopback' ID pointers (the ugly 'from' ones, Object->proxy_from and Key->from).
+ /* 'Loopback' ID pointers (the ugly 'from' ones, like Key->from).
* Those are not actually ID usage, we can ignore them here.
*/
if (cb_flag & IDWALK_CB_LOOPBACK) {
@@ -768,7 +768,7 @@ static int foreach_libblock_used_linked_data_tag_clear_cb(LibraryIDLinkCallbackD
bool *is_changed = cb_data->user_data;
if (*id_p) {
- /* The infamous 'from' pointers (Key.from, Object.proxy_from, ...).
+ /* The infamous 'from' pointers (Key.from, ...).
* those are not actually ID usage, so we ignore them here. */
if (cb_flag & IDWALK_CB_LOOPBACK) {
return IDWALK_RET_NOP;
diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c
index c3ccedb9608..e4e0466416a 100644
--- a/source/blender/blenkernel/intern/lib_remap.c
+++ b/source/blender/blenkernel/intern/lib_remap.c
@@ -91,26 +91,18 @@ enum {
ID_REMAP_IS_USER_ONE_SKIPPED = 1 << 1, /* There was some skipped 'user_one' usages of old_id. */
};
-static void foreach_libblock_remap_callback_skip(const ID *id_owner,
- ID **id_ptr,
+static void foreach_libblock_remap_callback_skip(const ID *UNUSED(id_owner),
+ ID **UNUSED(id_ptr),
IDRemap *id_remap_data,
const int cb_flag,
const bool is_indirect,
const bool is_reference,
const bool is_never_null,
- const bool is_obj,
+ const bool UNUSED(is_obj),
const bool is_obj_editmode)
{
if (is_indirect) {
id_remap_data->skipped_indirect++;
- if (is_obj) {
- Object *ob = (Object *)id_owner;
- if (ob->data == *id_ptr && ob->proxy != NULL) {
- /* And another 'Proudly brought to you by Proxy Hell' hack!
- * This will allow us to avoid clearing 'LIB_EXTERN' flag of obdata of proxies... */
- id_remap_data->skipped_direct++;
- }
- }
}
else if (is_never_null || is_obj_editmode || is_reference) {
id_remap_data->skipped_direct++;
@@ -136,8 +128,7 @@ static void foreach_libblock_remap_callback_apply(ID *id_owner,
const int cb_flag,
const bool is_indirect,
const bool is_never_null,
- const bool force_user_refcount,
- const bool is_obj_proxy)
+ const bool force_user_refcount)
{
if (!is_never_null) {
*id_ptr = new_id;
@@ -170,16 +161,9 @@ static void foreach_libblock_remap_callback_apply(ID *id_owner,
/* We cannot affect old_id->us directly, LIB_TAG_EXTRAUSER(_SET)
* are assumed to be set as needed, that extra user is processed in final handling. */
}
- if (!is_indirect || is_obj_proxy) {
+ if (!is_indirect) {
id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
- /* We need to remap proxy_from pointer of remapped proxy... sigh. */
- if (is_obj_proxy && new_id != NULL) {
- Object *ob = (Object *)id_owner;
- if (ob->proxy == (Object *)new_id) {
- ob->proxy->proxy_from = ob;
- }
- }
}
static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
@@ -221,12 +205,9 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
const bool is_reference = (cb_flag & IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE) != 0;
const bool is_indirect = (cb_flag & IDWALK_CB_INDIRECT_USAGE) != 0;
const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
- /* NOTE: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct,
- * on the other hand since they get reset to lib data on file open/reload it is indirect too.
- * Edit Mode is also a 'skip direct' case. */
const bool is_obj = (GS(id_owner->name) == ID_OB);
- const bool is_obj_proxy = (is_obj &&
- (((Object *)id_owner)->proxy || ((Object *)id_owner)->proxy_group));
+ /* NOTE: Edit Mode is a 'skip direct' case, unless specifically requested, obdata should not be
+ * remapped in this situation. */
const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id_owner) &&
(id_remap_data->flag & ID_REMAP_FORCE_OBDATA_IN_EDITMODE) == 0);
const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) &&
@@ -281,8 +262,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
cb_flag,
is_indirect,
is_never_null,
- force_user_refcount,
- is_obj_proxy);
+ force_user_refcount);
}
return IDWALK_RET_NOP;
@@ -430,10 +410,7 @@ static void libblock_remap_data(
Main *bmain, ID *id, ID *old_id, ID *new_id, const short remap_flags, IDRemap *r_id_remap_data)
{
IDRemap id_remap_data;
- const int foreach_id_flags = ((remap_flags & ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE) != 0 ?
- IDWALK_NO_INDIRECT_PROXY_DATA_USAGE :
- IDWALK_NOP) |
- ((remap_flags & ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS) != 0 ?
+ const int foreach_id_flags = ((remap_flags & ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS) != 0 ?
IDWALK_DO_INTERNAL_RUNTIME_POINTERS :
IDWALK_NOP);
diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc
index 73fe279552d..c1b1f62a881 100644
--- a/source/blender/blenkernel/intern/mesh.cc
+++ b/source/blender/blenkernel/intern/mesh.cc
@@ -685,6 +685,17 @@ static int customdata_compare(
}
break;
}
+ case CD_PROP_INT8: {
+ const int8_t *l1_data = (int8_t *)l1->data;
+ const int8_t *l2_data = (int8_t *)l2->data;
+
+ for (int i = 0; i < total_length; i++) {
+ if (l1_data[i] != l2_data[i]) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
+ }
+ break;
+ }
case CD_PROP_BOOL: {
const bool *l1_data = (bool *)l1->data;
const bool *l2_data = (bool *)l2->data;
diff --git a/source/blender/blenkernel/intern/mesh_iterators.c b/source/blender/blenkernel/intern/mesh_iterators.c
index 3f2d81b6dc2..4fb03c7b329 100644
--- a/source/blender/blenkernel/intern/mesh_iterators.c
+++ b/source/blender/blenkernel/intern/mesh_iterators.c
@@ -34,7 +34,7 @@
#include "MEM_guardedalloc.h"
-/* General note on iterating vers/loops/edges/polys and end mode.
+/* General note on iterating verts/loops/edges/polys and end mode.
*
* The edit mesh pointer is set for both final and cage meshes in both cases when there are
* modifiers applied and not. This helps consistency of checks in the draw manager, where the
diff --git a/source/blender/blenkernel/intern/mesh_merge.c b/source/blender/blenkernel/intern/mesh_merge.c
index 134a1344f83..3c01d5a4a50 100644
--- a/source/blender/blenkernel/intern/mesh_merge.c
+++ b/source/blender/blenkernel/intern/mesh_merge.c
@@ -27,6 +27,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "BLI_bitmap.h"
#include "BLI_edgehash.h"
#include "BLI_ghash.h"
#include "BLI_utildefines.h"
@@ -351,6 +352,8 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh,
&poly_map, &poly_map_mem, mesh->mpoly, mesh->mloop, totvert, totpoly, totloop);
} /* done preparing for fast poly compare */
+ BLI_bitmap *vert_tag = BLI_BITMAP_NEW(mesh->totvert, __func__);
+
mp = mesh->mpoly;
mv = mesh->mvert;
for (i = 0; i < totpoly; i++, mp++) {
@@ -365,11 +368,11 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh,
if (vtargetmap[ml->v] == -1) {
all_vertices_merged = false;
/* This will be used to check for poly using several time the same vert. */
- mv[ml->v].flag &= ~ME_VERT_TMP_TAG;
+ BLI_BITMAP_DISABLE(vert_tag, ml->v);
}
else {
/* This will be used to check for poly using several time the same vert. */
- mv[vtargetmap[ml->v]].flag &= ~ME_VERT_TMP_TAG;
+ BLI_BITMAP_DISABLE(vert_tag, vtargetmap[ml->v]);
}
}
@@ -457,8 +460,8 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh,
#endif
/* A loop is only valid if its matching edge is,
* and it's not reusing a vertex already used by this poly. */
- if (LIKELY((newe[ml->e] != -1) && ((mv[mlv].flag & ME_VERT_TMP_TAG) == 0))) {
- mv[mlv].flag |= ME_VERT_TMP_TAG;
+ if (LIKELY((newe[ml->e] != -1) && !BLI_BITMAP_TEST(vert_tag, mlv))) {
+ BLI_BITMAP_ENABLE(vert_tag, mlv);
if (UNLIKELY(last_valid_ml != NULL && need_edge_from_last_valid_ml)) {
/* We need to create a new edge between last valid loop and this one! */
@@ -644,6 +647,8 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh,
MEM_freeN(oldl);
MEM_freeN(oldp);
+ MEM_freeN(vert_tag);
+
BLI_edgehash_free(ehash, NULL);
if (poly_map != NULL) {
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 005c916b4e0..a5ba2767301 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -28,6 +28,7 @@
#include "CLG_log.h"
+#include "BLI_bitmap.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -560,6 +561,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
* so be sure to leave at most one poly per loop!
*/
{
+ BLI_bitmap *vert_tag = BLI_BITMAP_NEW(mesh->totvert, __func__);
+
SortPoly *sort_polys = MEM_callocN(sizeof(SortPoly) * totpoly, "mesh validate's sort_polys");
SortPoly *prev_sp, *sp = sort_polys;
int prev_end;
@@ -608,7 +611,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
* so we have to ensure here all verts of current poly are cleared. */
for (j = 0, ml = &mloops[sp->loopstart]; j < mp->totloop; j++, ml++) {
if (ml->v < totvert) {
- mverts[ml->v].flag &= ~ME_VERT_TMP_TAG;
+ BLI_BITMAP_DISABLE(vert_tag, ml->v);
}
}
@@ -619,12 +622,12 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
PRINT_ERR("\tLoop %u has invalid vert reference (%u)", sp->loopstart + j, ml->v);
sp->invalid = true;
}
- else if (mverts[ml->v].flag & ME_VERT_TMP_TAG) {
+ else if (BLI_BITMAP_TEST(vert_tag, ml->v)) {
PRINT_ERR("\tPoly %u has duplicated vert reference at corner (%u)", i, j);
sp->invalid = true;
}
else {
- mverts[ml->v].flag |= ME_VERT_TMP_TAG;
+ BLI_BITMAP_ENABLE(vert_tag, ml->v);
}
*v = ml->v;
}
@@ -698,6 +701,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
}
}
+ MEM_freeN(vert_tag);
+
/* Second check pass, testing polys using the same verts. */
qsort(sort_polys, totpoly, sizeof(SortPoly), search_poly_cmp);
sp = prev_sp = sort_polys;
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 4f170535d18..829ef08a8fb 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -1188,8 +1188,8 @@ void BKE_modifier_blend_write(BlendWriter *writer, ListBase *modbase)
#if 0
CollisionModifierData *collmd = (CollisionModifierData *)md;
- // TODO: CollisionModifier should use pointcache
- // + have proper reset events before enabling this
+ /* TODO: CollisionModifier should use pointcache
+ * + have proper reset events before enabling this. */
writestruct(wd, DATA, MVert, collmd->numverts, collmd->x);
writestruct(wd, DATA, MVert, collmd->numverts, collmd->xnew);
writestruct(wd, DATA, MFace, collmd->numfaces, collmd->mfaces);
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 40d0c24c9af..a1c10a733ce 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -648,7 +648,6 @@ static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_addres
bNodeTree *ntree = (bNodeTree *)id;
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
- ntree->init = 0; /* to set callbacks and force setting types */
ntree->is_updating = false;
ntree->typeinfo = nullptr;
ntree->interface_type = nullptr;
@@ -677,7 +676,6 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
{
/* NOTE: writing and reading goes in sync, for speed. */
- ntree->init = 0; /* to set callbacks and force setting types */
ntree->is_updating = false;
ntree->typeinfo = nullptr;
ntree->interface_type = nullptr;
@@ -1145,8 +1143,6 @@ static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo)
}
else {
ntree->typeinfo = &NodeTreeTypeUndefined;
-
- ntree->init &= ~NTREE_TYPE_INIT;
}
/* Deprecated integer type. */
@@ -1177,8 +1173,6 @@ static void node_set_typeinfo(const struct bContext *C,
}
else {
node->typeinfo = &NodeTypeUndefined;
-
- ntree->init &= ~NTREE_TYPE_INIT;
}
}
@@ -1199,8 +1193,6 @@ static void node_socket_set_typeinfo(bNodeTree *ntree,
}
else {
sock->typeinfo = &NodeSocketTypeUndefined;
-
- ntree->init &= ~NTREE_TYPE_INIT;
}
BKE_ntree_update_tag_socket_type(ntree, sock);
}
@@ -1218,8 +1210,6 @@ static void update_typeinfo(Main *bmain,
}
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
- ntree->init |= NTREE_TYPE_INIT;
-
if (treetype && STREQ(ntree->idname, treetype->idname)) {
ntree_set_typeinfo(ntree, unregister ? nullptr : treetype);
}
@@ -1260,8 +1250,6 @@ static void update_typeinfo(Main *bmain,
void ntreeSetTypes(const struct bContext *C, bNodeTree *ntree)
{
- ntree->init |= NTREE_TYPE_INIT;
-
ntree_set_typeinfo(ntree, ntreeTypeFind(ntree->idname));
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
@@ -2674,11 +2662,6 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
ntree->id.flag |= LIB_EMBEDDED_DATA;
}
- /* Types are fully initialized at this point,
- * if an undefined node is added later this will be reset.
- */
- ntree->init |= NTREE_TYPE_INIT;
-
BLI_strncpy(ntree->idname, idname, sizeof(ntree->idname));
ntree_set_typeinfo(ntree, ntreeTypeFind(idname));
@@ -4503,6 +4486,8 @@ static void registerCompositNodes()
register_node_type_cmp_sepycca();
register_node_type_cmp_combycca();
register_node_type_cmp_premulkey();
+ register_node_type_cmp_separate_xyz();
+ register_node_type_cmp_combine_xyz();
register_node_type_cmp_diff_matte();
register_node_type_cmp_distance_matte();
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index f9484205ef6..04d60c096f2 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -325,45 +325,6 @@ static void object_free_data(ID *id)
BKE_previewimg_free(&ob->preview);
}
-static void object_make_local(Main *bmain, ID *id, const int flags)
-{
- if (!ID_IS_LINKED(id)) {
- return;
- }
-
- Object *ob = (Object *)id;
- const bool lib_local = (flags & LIB_ID_MAKELOCAL_FULL_LIBRARY) != 0;
- const bool clear_proxy = (flags & LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING) == 0;
-
- bool force_local, force_copy;
- BKE_lib_id_make_local_generic_action_define(bmain, id, flags, &force_local, &force_copy);
-
- if (force_local) {
- BKE_lib_id_clear_library_data(bmain, &ob->id, flags);
- BKE_lib_id_expand_local(bmain, &ob->id, flags);
- if (clear_proxy) {
- if (ob->proxy_from != nullptr) {
- ob->proxy_from->proxy = nullptr;
- ob->proxy_from->proxy_group = nullptr;
- }
- ob->proxy = ob->proxy_from = ob->proxy_group = nullptr;
- }
- }
- else if (force_copy) {
- Object *ob_new = (Object *)BKE_id_copy(bmain, &ob->id);
- id_us_min(&ob_new->id);
-
- ob_new->proxy = ob_new->proxy_from = ob_new->proxy_group = nullptr;
-
- /* setting newid is mandatory for complex make_lib_local logic... */
- ID_NEW_SET(ob, ob_new);
-
- if (!lib_local) {
- BKE_libblock_remap(bmain, ob, ob_new, ID_REMAP_SKIP_INDIRECT_USAGE);
- }
- }
-}
-
static void library_foreach_modifiersForeachIDLink(void *user_data,
Object *UNUSED(object),
ID **id_pointer,
@@ -419,51 +380,25 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
{
Object *object = (Object *)id;
- /* Object is special, proxies make things hard... */
- const int proxy_cb_flag = ((BKE_lib_query_foreachid_process_flags_get(data) &
- IDWALK_NO_INDIRECT_PROXY_DATA_USAGE) == 0 &&
- (object->proxy || object->proxy_group)) ?
- IDWALK_CB_INDIRECT_USAGE :
- 0;
-
/* object data special case */
if (object->type == OB_EMPTY) {
/* empty can have nullptr or Image */
- BKE_LIB_FOREACHID_PROCESS_ID(data, object->data, proxy_cb_flag | IDWALK_CB_USER);
+ BKE_LIB_FOREACHID_PROCESS_ID(data, object->data, IDWALK_CB_USER);
}
else {
/* when set, this can't be nullptr */
if (object->data) {
- BKE_LIB_FOREACHID_PROCESS_ID(
- data, object->data, proxy_cb_flag | IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
+ BKE_LIB_FOREACHID_PROCESS_ID(data, object->data, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
}
}
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->parent, IDWALK_CB_NEVER_SELF);
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->track, IDWALK_CB_NEVER_SELF);
- /* object->proxy is refcounted, but not object->proxy_group... *sigh* */
- BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->proxy, IDWALK_CB_USER | IDWALK_CB_NEVER_SELF);
- BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->proxy_group, IDWALK_CB_NOP);
-
- /* Special case!
- * Since this field is set/owned by 'user' of this ID (and not ID itself),
- * it is only indirect usage if proxy object is linked... Twisted. */
- {
- const int cb_flag_orig = BKE_lib_query_foreachid_process_callback_flag_override(
- data,
- (object->proxy_from != nullptr && ID_IS_LINKED(object->proxy_from)) ?
- IDWALK_CB_INDIRECT_USAGE :
- 0,
- true);
- BKE_LIB_FOREACHID_PROCESS_IDSUPER(
- data, object->proxy_from, IDWALK_CB_LOOPBACK | IDWALK_CB_NEVER_SELF);
- BKE_lib_query_foreachid_process_callback_flag_override(data, cb_flag_orig, true);
- }
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->poselib, IDWALK_CB_USER);
for (int i = 0; i < object->totcol; i++) {
- BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->mat[i], proxy_cb_flag | IDWALK_CB_USER);
+ BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->mat[i], IDWALK_CB_USER);
}
/* Note that ob->gpd is deprecated, so no need to handle it here. */
@@ -476,8 +411,6 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
/* Note that ob->effect is deprecated, so no need to handle it here. */
if (object->pose) {
- const int cb_flag_orig = BKE_lib_query_foreachid_process_callback_flag_override(
- data, proxy_cb_flag, false);
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
data,
@@ -492,7 +425,6 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
BKE_constraints_id_loop(
&pchan->constraints, library_foreach_constraintObjectLooper, data));
}
- BKE_lib_query_foreachid_process_callback_flag_override(data, cb_flag_orig, true);
}
if (object->rigidbody_constraint) {
@@ -627,9 +559,6 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
bArmature *arm = nullptr;
if (ob->type == OB_ARMATURE) {
arm = (bArmature *)ob->data;
- if (arm && ob->pose && arm->act_bone) {
- BLI_strncpy(ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone));
- }
}
BKE_pose_blend_write(writer, ob->pose, arm);
@@ -1305,7 +1234,7 @@ IDTypeInfo IDType_ID_OB = {
/* init_data */ object_init_data,
/* copy_data */ object_copy_data,
/* free_data */ object_free_data,
- /* make_local */ object_make_local,
+ /* make_local */ nullptr,
/* foreach_id */ object_foreach_id,
/* foreach_cache */ nullptr,
/* foreach_path */ object_foreach_path,
@@ -1486,10 +1415,7 @@ bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
}
/* Only geometry objects should be able to get modifiers T25291. */
- if (ob->type == OB_HAIR) {
- return (mti->modifyHair != nullptr) || (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly);
- }
- if (ELEM(ob->type, OB_POINTCLOUD, OB_VOLUME)) {
+ if (ELEM(ob->type, OB_POINTCLOUD, OB_VOLUME, OB_HAIR)) {
return (mti->modifyGeometrySet != nullptr);
}
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
@@ -2876,161 +2802,6 @@ bool BKE_object_obdata_is_libdata(const Object *ob)
return (ob && ob->data && ID_IS_LINKED(ob->data));
}
-/* -------------------------------------------------------------------- */
-/** \name Object Proxy API
- * \{ */
-
-/* when you make proxy, ensure the exposed layers are extern */
-static void armature_set_id_extern(Object *ob)
-{
- bArmature *arm = (bArmature *)ob->data;
- unsigned int lay = arm->layer_protected;
-
- LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- if (!(pchan->bone->layer & lay)) {
- id_lib_extern((ID *)pchan->custom);
- }
- }
-}
-
-void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
-{
- if ((target->adt) && (target->adt->drivers.first)) {
-
- /* add new animdata block */
- if (!ob->adt) {
- ob->adt = BKE_animdata_ensure_id(&ob->id);
- }
-
- /* make a copy of all the drivers (for now), then correct any links that need fixing */
- BKE_fcurves_free(&ob->adt->drivers);
- BKE_fcurves_copy(&ob->adt->drivers, &target->adt->drivers);
-
- LISTBASE_FOREACH (FCurve *, fcu, &ob->adt->drivers) {
- ChannelDriver *driver = fcu->driver;
-
- LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
- /* all drivers */
- DRIVER_TARGETS_LOOPER_BEGIN (dvar) {
- if (dtar->id) {
- if ((Object *)dtar->id == target) {
- dtar->id = (ID *)ob;
- }
- else {
- /* only on local objects because this causes indirect links
- * 'a -> b -> c', blend to point directly to a.blend
- * when a.blend has a proxy that's linked into `c.blend`. */
- if (!ID_IS_LINKED(ob)) {
- id_lib_extern((ID *)dtar->id);
- }
- }
- }
- }
- DRIVER_TARGETS_LOOPER_END;
- }
- }
- }
-}
-
-void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob)
-{
- /* paranoia checks */
- if (ID_IS_LINKED(ob) || !ID_IS_LINKED(target)) {
- CLOG_ERROR(&LOG, "cannot make proxy");
- return;
- }
-
- ob->proxy = target;
- id_us_plus(&target->id);
- ob->proxy_group = cob;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- DEG_id_tag_update(&target->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- /* copy transform
- * - cob means this proxy comes from a collection, just apply the matrix
- * so the object won't move from its dupli-transform.
- *
- * - no cob means this is being made from a linked object,
- * this is closer to making a copy of the object - in-place. */
- if (cob) {
- ob->rotmode = target->rotmode;
- mul_m4_m4m4(ob->obmat, cob->obmat, target->obmat);
- if (cob->instance_collection) { /* should always be true */
- float tvec[3];
- mul_v3_mat3_m4v3(tvec, ob->obmat, cob->instance_collection->instance_offset);
- sub_v3_v3(ob->obmat[3], tvec);
- }
- BKE_object_apply_mat4(ob, ob->obmat, false, true);
- }
- else {
- BKE_object_transform_copy(ob, target);
- ob->parent = target->parent; /* libdata */
- copy_m4_m4(ob->parentinv, target->parentinv);
- }
-
- /* copy animdata stuff - drivers only for now... */
- BKE_object_copy_proxy_drivers(ob, target);
-
- /* skip constraints? */
- /* FIXME: this is considered by many as a bug */
-
- /* set object type and link to data */
- ob->type = target->type;
- ob->data = target->data;
- id_us_plus((ID *)ob->data); /* ensures lib data becomes LIB_TAG_EXTERN */
-
- /* copy material and index information */
- ob->actcol = ob->totcol = 0;
- if (ob->mat) {
- MEM_freeN(ob->mat);
- }
- if (ob->matbits) {
- MEM_freeN(ob->matbits);
- }
- ob->mat = nullptr;
- ob->matbits = nullptr;
- if ((target->totcol) && (target->mat) && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
- int i;
-
- ob->actcol = target->actcol;
- ob->totcol = target->totcol;
-
- ob->mat = (Material **)MEM_dupallocN(target->mat);
- ob->matbits = (char *)MEM_dupallocN(target->matbits);
- for (i = 0; i < target->totcol; i++) {
- /* don't need to run BKE_object_materials_test
- * since we know this object is new and not used elsewhere */
- id_us_plus((ID *)ob->mat[i]);
- }
- }
-
- /* type conversions */
- if (target->type == OB_ARMATURE) {
- copy_object_pose(ob, target, 0); /* data copy, object pointers in constraints */
- BKE_pose_rest(ob->pose, false); /* clear all transforms in channels */
- BKE_pose_rebuild(bmain, ob, (bArmature *)ob->data, true); /* set all internal links */
-
- armature_set_id_extern(ob);
- }
- else if (target->type == OB_EMPTY) {
- ob->empty_drawtype = target->empty_drawtype;
- ob->empty_drawsize = target->empty_drawsize;
- }
-
- /* copy IDProperties */
- if (ob->id.properties) {
- IDP_FreeProperty(ob->id.properties);
- ob->id.properties = nullptr;
- }
- if (target->id.properties) {
- ob->id.properties = IDP_CopyProperty(target->id.properties);
- }
-
- /* copy drawtype info */
- ob->dt = target->dt;
-}
-
void BKE_object_obdata_size_init(struct Object *ob, const float size)
{
/* apply radius as a scale to types that support it */
@@ -3072,8 +2843,6 @@ void BKE_object_obdata_size_init(struct Object *ob, const float size)
}
}
-/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Object Matrix Get/Set API
* \{ */
@@ -4365,33 +4134,10 @@ void BKE_object_tfm_restore(Object *ob, void *obtfm_pt)
/** \name Object Evaluation/Update API
* \{ */
-static void object_handle_update_proxy(Depsgraph *depsgraph,
- Scene *scene,
- Object *object,
- const bool do_proxy_update)
-{
- /* The case when this is a collection proxy, object_update is called in collection.c */
- if (object->proxy == nullptr) {
- return;
- }
- /* set pointer in library proxy target, for copying, but restore it */
- object->proxy->proxy_from = object;
- // printf("set proxy pointer for later collection stuff %s\n", ob->id.name);
-
- /* the no-group proxy case, we call update */
- if (object->proxy_group == nullptr) {
- if (do_proxy_update) {
- // printf("call update, lib ob %s proxy %s\n", ob->proxy->id.name, ob->id.name);
- BKE_object_handle_update(depsgraph, scene, object->proxy);
- }
- }
-}
-
void BKE_object_handle_update_ex(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
- RigidBodyWorld *rbw,
- const bool do_proxy_update)
+ RigidBodyWorld *rbw)
{
const ID *object_data = (ID *)ob->data;
const bool recalc_object = (ob->id.recalc & ID_RECALC_ALL) != 0;
@@ -4399,7 +4145,6 @@ void BKE_object_handle_update_ex(Depsgraph *depsgraph,
((object_data->recalc & ID_RECALC_ALL) != 0) :
false;
if (!recalc_object && !recalc_data) {
- object_handle_update_proxy(depsgraph, scene, ob, do_proxy_update);
return;
}
/* Speed optimization for animation lookups. */
@@ -4428,22 +4173,17 @@ void BKE_object_handle_update_ex(Depsgraph *depsgraph,
if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) {
printf("recalcob %s\n", ob->id.name + 2);
}
- /* Handle proxy copy for target. */
- if (!BKE_object_eval_proxy_copy(depsgraph, ob)) {
- BKE_object_where_is_calc_ex(depsgraph, scene, rbw, ob, nullptr);
- }
+ BKE_object_where_is_calc_ex(depsgraph, scene, rbw, ob, nullptr);
}
if (recalc_data) {
BKE_object_handle_data_update(depsgraph, scene, ob);
}
-
- object_handle_update_proxy(depsgraph, scene, ob, do_proxy_update);
}
void BKE_object_handle_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- BKE_object_handle_update_ex(depsgraph, scene, ob, nullptr, true);
+ BKE_object_handle_update_ex(depsgraph, scene, ob, nullptr);
}
void BKE_object_sculpt_data_create(Object *ob)
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 1a208355870..9c2b48303b2 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -190,16 +190,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
break;
}
case OB_ARMATURE:
- if (ID_IS_LINKED(ob) && ob->proxy_from) {
- if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
- printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
- ob->id.name + 2,
- ob->proxy_from->id.name + 2);
- }
- }
- else {
- BKE_pose_where_is(depsgraph, scene, ob);
- }
+ BKE_pose_where_is(depsgraph, scene, ob);
break;
case OB_MBALL:
@@ -311,33 +302,9 @@ void BKE_object_sync_to_original(Depsgraph *depsgraph, Object *object)
object_sync_boundbox_to_original(object_orig, object);
}
-bool BKE_object_eval_proxy_copy(Depsgraph *depsgraph, Object *object)
-{
- /* Handle proxy copy for target, */
- if (ID_IS_LINKED(object) && object->proxy_from) {
- DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
- if (object->proxy_from->proxy_group) {
- /* Transform proxy into group space. */
- Object *obg = object->proxy_from->proxy_group;
- float imat[4][4];
- invert_m4_m4(imat, obg->obmat);
- mul_m4_m4m4(object->obmat, imat, object->proxy_from->obmat);
- /* Should always be true. */
- if (obg->instance_collection) {
- add_v3_v3(object->obmat[3], obg->instance_collection->instance_offset);
- }
- }
- else {
- copy_m4_m4(object->obmat, object->proxy_from->obmat);
- }
- return true;
- }
- return false;
-}
-
-void BKE_object_eval_uber_transform(Depsgraph *depsgraph, Object *object)
+void BKE_object_eval_uber_transform(Depsgraph *UNUSED(depsgraph), Object *UNUSED(object))
{
- BKE_object_eval_proxy_copy(depsgraph, object);
+ return;
}
void BKE_object_data_batch_cache_dirty_tag(ID *object_data)
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 4dba13ce4c2..aa08a6494d1 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -4640,7 +4640,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
* account when subdividing for instance. */
pind.mesh = psys_in_edit_mode(sim->depsgraph, psys) ?
NULL :
- psys->hair_out_mesh; /* XXX(@sybren) EEK. */
+ psys->hair_out_mesh; /* XXX(@sybren): EEK. */
init_particle_interpolation(sim->ob, psys, pa, &pind);
do_particle_interpolation(psys, p, pa, t, &pind, state);
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 9d66c354b54..2f63edebb67 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -580,7 +580,6 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
#endif
MVert *mvert = dm->getVertArray(dm);
MEdge *medge = dm->getEdgeArray(dm);
- // MFace *mface = dm->getTessFaceArray(dm); /* UNUSED */
MVert *mv;
MEdge *me;
MLoop *mloop = dm->getLoopArray(dm), *ml;
@@ -1129,44 +1128,6 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
}
}
-static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
- CCGSubSurf *ss = ccgdm->ss;
- int index;
- int totface;
- int gridSize = ccgSubSurf_getGridSize(ss);
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
- int i = 0;
- DMFlagMat *faceFlags = ccgdm->faceFlags;
-
- totface = dm->getNumTessFaces(dm);
- for (index = 0; index < totface; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
- int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
- /* keep types in sync with MFace, avoid many conversions */
- char flag = (faceFlags) ? faceFlags[index].flag : ME_SMOOTH;
- short mat_nr = (faceFlags) ? faceFlags[index].mat_nr : 0;
-
- for (S = 0; S < numVerts; S++) {
- for (y = 0; y < gridSize - 1; y++) {
- for (x = 0; x < gridSize - 1; x++) {
- MFace *mf = &mface[i];
- mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0, edgeSize, gridSize);
- mf->v2 = getFaceIndex(ss, f, S, x + 0, y + 1, edgeSize, gridSize);
- mf->v3 = getFaceIndex(ss, f, S, x + 1, y + 1, edgeSize, gridSize);
- mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edgeSize, gridSize);
- mf->mat_nr = mat_nr;
- mf->flag = flag;
- mf->edcode = 0;
-
- i++;
- }
- }
- }
- }
-}
-
typedef struct CopyFinalLoopArrayData {
CCGDerivedMesh *ccgdm;
MLoop *mloop;
@@ -1457,63 +1418,6 @@ static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type)
return DM_get_edge_data_layer(dm, type);
}
-static void *ccgDM_get_tessface_data_layer(DerivedMesh *dm, int type)
-{
- if (type == CD_ORIGINDEX) {
- /* create origindex on demand to save memory */
- int *origindex;
-
- /* Avoid re-creation if the layer exists already */
- origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
- if (origindex) {
- return origindex;
- }
-
- DM_add_tessface_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
- origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
-
- /* silly loop counting up */
- range_vn_i(origindex, dm->getNumTessFaces(dm), 0);
-
- return origindex;
- }
-
- if (type == CD_TESSLOOPNORMAL) {
- /* Create tessloopnormal on demand to save memory. */
- /* Note that since tessellated face corners are the same a loops in CCGDM,
- * and since all faces have four loops/corners, we can simplify the code
- * here by converting tessloopnormals from 'short (*)[4][3]' to 'short (*)[3]'. */
- short(*tlnors)[3];
-
- /* Avoid re-creation if the layer exists already */
- tlnors = DM_get_tessface_data_layer(dm, CD_TESSLOOPNORMAL);
- if (!tlnors) {
- float(*lnors)[3];
- short(*tlnors_it)[3];
- const int numLoops = ccgDM_getNumLoops(dm);
- int i;
-
- lnors = dm->getLoopDataArray(dm, CD_NORMAL);
- if (!lnors) {
- return NULL;
- }
-
- DM_add_tessface_layer(dm, CD_TESSLOOPNORMAL, CD_CALLOC, NULL);
- tlnors = tlnors_it = (short(*)[3])DM_get_tessface_data_layer(dm, CD_TESSLOOPNORMAL);
-
- /* With ccgdm, we have a simple one to one mapping between loops
- * and tessellated face corners. */
- for (i = 0; i < numLoops; i++, tlnors_it++, lnors++) {
- normal_float_to_short_v3(*tlnors_it, *lnors);
- }
- }
-
- return tlnors;
- }
-
- return DM_get_tessface_data_layer(dm, type);
-}
-
static void *ccgDM_get_poly_data_layer(DerivedMesh *dm, int type)
{
if (type == CD_ORIGINDEX) {
@@ -1551,46 +1455,6 @@ static void *ccgDM_get_poly_data_layer(DerivedMesh *dm, int type)
return DM_get_poly_data_layer(dm, type);
}
-static void *ccgDM_get_vert_data(DerivedMesh *dm, int index, int type)
-{
- if (type == CD_ORIGINDEX) {
- /* ensure creation of CD_ORIGINDEX layer */
- ccgDM_get_vert_data_layer(dm, type);
- }
-
- return DM_get_vert_data(dm, index, type);
-}
-
-static void *ccgDM_get_edge_data(DerivedMesh *dm, int index, int type)
-{
- if (type == CD_ORIGINDEX) {
- /* ensure creation of CD_ORIGINDEX layer */
- ccgDM_get_edge_data_layer(dm, type);
- }
-
- return DM_get_edge_data(dm, index, type);
-}
-
-static void *ccgDM_get_tessface_data(DerivedMesh *dm, int index, int type)
-{
- if (ELEM(type, CD_ORIGINDEX, CD_TESSLOOPNORMAL)) {
- /* ensure creation of CD_ORIGINDEX/CD_TESSLOOPNORMAL layers */
- ccgDM_get_tessface_data_layer(dm, type);
- }
-
- return DM_get_tessface_data(dm, index, type);
-}
-
-static void *ccgDM_get_poly_data(DerivedMesh *dm, int index, int type)
-{
- if (type == CD_ORIGINDEX) {
- /* ensure creation of CD_ORIGINDEX layer */
- ccgDM_get_tessface_data_layer(dm, type);
- }
-
- return DM_get_poly_data(dm, index, type);
-}
-
static int ccgDM_getNumGrids(DerivedMesh *dm)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
@@ -1705,25 +1569,6 @@ static BLI_bitmap **ccgDM_getGridHidden(DerivedMesh *dm)
return ccgdm->gridHidden;
}
-static const MeshElemMap *ccgDM_getPolyMap(Object *ob, DerivedMesh *dm)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
-
- if (!ccgdm->multires.mmd && !ccgdm->pmap && ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- BKE_mesh_vert_poly_map_create(&ccgdm->pmap,
- &ccgdm->pmap_mem,
- me->mpoly,
- me->mloop,
- me->totvert,
- me->totpoly,
- me->totloop);
- }
-
- return ccgdm->pmap;
-}
-
/* WARNING! *MUST* be called in an 'loops_cache_rwlock' protected thread context! */
static void ccgDM_recalcLoopTri(DerivedMesh *dm)
{
@@ -1773,17 +1618,11 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
- ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray;
ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray;
- ccgdm->dm.getVertData = ccgDM_get_vert_data;
- ccgdm->dm.getEdgeData = ccgDM_get_edge_data;
- ccgdm->dm.getTessFaceData = ccgDM_get_tessface_data;
- ccgdm->dm.getPolyData = ccgDM_get_poly_data;
ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer;
- ccgdm->dm.getTessFaceDataArray = ccgDM_get_tessface_data_layer;
ccgdm->dm.getPolyDataArray = ccgDM_get_poly_data_layer;
ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
ccgdm->dm.getGridSize = ccgDM_getGridSize;
@@ -1792,7 +1631,6 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
ccgdm->dm.getGridKey = ccgDM_getGridKey;
ccgdm->dm.getGridFlagMats = ccgDM_getGridFlagMats;
ccgdm->dm.getGridHidden = ccgDM_getGridHidden;
- ccgdm->dm.getPolyMap = ccgDM_getPolyMap;
ccgdm->dm.recalcLoopTri = ccgDM_recalcLoopTri;
@@ -1848,7 +1686,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
int index;
int i;
int vertNum = 0, edgeNum = 0, faceNum = 0;
- int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex, *base_polyOrigIndex, *edgeOrigIndex;
+ int *vertOrigIndex, *polyOrigIndex, *base_polyOrigIndex, *edgeOrigIndex;
short *edgeFlags = ccgdm->edgeFlags;
DMFlagMat *faceFlags = ccgdm->faceFlags;
int *polyidx = NULL;
@@ -1884,7 +1722,6 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);
- faceOrigIndex = DM_get_tessface_data_layer(&ccgdm->dm, CD_ORIGINDEX);
polyOrigIndex = DM_get_poly_data_layer(&ccgdm->dm, CD_ORIGINDEX);
has_edge_cd = ((ccgdm->dm.edgeData.totlayer - (edgeOrigIndex ? 1 : 0)) != 0);
@@ -2006,12 +1843,6 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
/* Copy over poly data, e.g. #CD_FACEMAP. */
CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
- /* Set original index data. */
- if (faceOrigIndex) {
- /* reference the index in 'polyOrigIndex' */
- *faceOrigIndex = faceNum;
- faceOrigIndex++;
- }
if (polyOrigIndex) {
*polyOrigIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex;
polyOrigIndex++;
diff --git a/source/blender/blenkernel/intern/type_conversions.cc b/source/blender/blenkernel/intern/type_conversions.cc
index cb05337ef2a..b2011d2baf7 100644
--- a/source/blender/blenkernel/intern/type_conversions.cc
+++ b/source/blender/blenkernel/intern/type_conversions.cc
@@ -62,6 +62,11 @@ static bool float_to_bool(const float &a)
{
return a > 0.0f;
}
+static int8_t float_to_int8(const float &a)
+{
+ return std::clamp(
+ a, float(std::numeric_limits<int8_t>::min()), float(std::numeric_limits<int8_t>::max()));
+}
static ColorGeometry4f float_to_color(const float &a)
{
return ColorGeometry4f(a, a, a, 1.0f);
@@ -83,6 +88,10 @@ static bool float2_to_bool(const float2 &a)
{
return !is_zero_v2(a);
}
+static int8_t float2_to_int8(const float2 &a)
+{
+ return float_to_int8((a.x + a.y) / 2.0f);
+}
static ColorGeometry4f float2_to_color(const float2 &a)
{
return ColorGeometry4f(a.x, a.y, 0.0f, 1.0f);
@@ -92,6 +101,10 @@ static bool float3_to_bool(const float3 &a)
{
return !is_zero_v3(a);
}
+static int8_t float3_to_int8(const float3 &a)
+{
+ return float_to_int8((a.x + a.y + a.z) / 3.0f);
+}
static float float3_to_float(const float3 &a)
{
return (a.x + a.y + a.z) / 3.0f;
@@ -113,6 +126,11 @@ static bool int_to_bool(const int32_t &a)
{
return a > 0;
}
+static int8_t int_to_int8(const int32_t &a)
+{
+ return std::clamp(
+ a, int(std::numeric_limits<int8_t>::min()), int(std::numeric_limits<int8_t>::max()));
+}
static float int_to_float(const int32_t &a)
{
return (float)a;
@@ -130,10 +148,39 @@ static ColorGeometry4f int_to_color(const int32_t &a)
return ColorGeometry4f((float)a, (float)a, (float)a, 1.0f);
}
+static bool int8_to_bool(const int8_t &a)
+{
+ return a > 0;
+}
+static int int8_to_int(const int8_t &a)
+{
+ return static_cast<int>(a);
+}
+static float int8_to_float(const int8_t &a)
+{
+ return (float)a;
+}
+static float2 int8_to_float2(const int8_t &a)
+{
+ return float2((float)a);
+}
+static float3 int8_to_float3(const int8_t &a)
+{
+ return float3((float)a);
+}
+static ColorGeometry4f int8_to_color(const int8_t &a)
+{
+ return ColorGeometry4f((float)a, (float)a, (float)a, 1.0f);
+}
+
static float bool_to_float(const bool &a)
{
return (bool)a;
}
+static int8_t bool_to_int8(const bool &a)
+{
+ return static_cast<int8_t>(a);
+}
static int32_t bool_to_int(const bool &a)
{
return (int32_t)a;
@@ -163,6 +210,10 @@ static int32_t color_to_int(const ColorGeometry4f &a)
{
return (int)rgb_to_grayscale(a);
}
+static int8_t color_to_int8(const ColorGeometry4f &a)
+{
+ return int_to_int8(color_to_int(a));
+}
static float2 color_to_float2(const ColorGeometry4f &a)
{
return float2(a.r, a.g);
@@ -180,33 +231,46 @@ static DataTypeConversions create_implicit_conversions()
add_implicit_conversion<float, float3, float_to_float3>(conversions);
add_implicit_conversion<float, int32_t, float_to_int>(conversions);
add_implicit_conversion<float, bool, float_to_bool>(conversions);
+ add_implicit_conversion<float, int8_t, float_to_int8>(conversions);
add_implicit_conversion<float, ColorGeometry4f, float_to_color>(conversions);
add_implicit_conversion<float2, float3, float2_to_float3>(conversions);
add_implicit_conversion<float2, float, float2_to_float>(conversions);
add_implicit_conversion<float2, int32_t, float2_to_int>(conversions);
add_implicit_conversion<float2, bool, float2_to_bool>(conversions);
+ add_implicit_conversion<float2, int8_t, float2_to_int8>(conversions);
add_implicit_conversion<float2, ColorGeometry4f, float2_to_color>(conversions);
add_implicit_conversion<float3, bool, float3_to_bool>(conversions);
+ add_implicit_conversion<float3, int8_t, float3_to_int8>(conversions);
add_implicit_conversion<float3, float, float3_to_float>(conversions);
add_implicit_conversion<float3, int32_t, float3_to_int>(conversions);
add_implicit_conversion<float3, float2, float3_to_float2>(conversions);
add_implicit_conversion<float3, ColorGeometry4f, float3_to_color>(conversions);
add_implicit_conversion<int32_t, bool, int_to_bool>(conversions);
+ add_implicit_conversion<int32_t, int8_t, int_to_int8>(conversions);
add_implicit_conversion<int32_t, float, int_to_float>(conversions);
add_implicit_conversion<int32_t, float2, int_to_float2>(conversions);
add_implicit_conversion<int32_t, float3, int_to_float3>(conversions);
add_implicit_conversion<int32_t, ColorGeometry4f, int_to_color>(conversions);
+ add_implicit_conversion<int8_t, bool, int8_to_bool>(conversions);
+ add_implicit_conversion<int8_t, int32_t, int8_to_int>(conversions);
+ add_implicit_conversion<int8_t, float, int8_to_float>(conversions);
+ add_implicit_conversion<int8_t, float2, int8_to_float2>(conversions);
+ add_implicit_conversion<int8_t, float3, int8_to_float3>(conversions);
+ add_implicit_conversion<int8_t, ColorGeometry4f, int8_to_color>(conversions);
+
add_implicit_conversion<bool, float, bool_to_float>(conversions);
+ add_implicit_conversion<bool, int8_t, bool_to_int8>(conversions);
add_implicit_conversion<bool, int32_t, bool_to_int>(conversions);
add_implicit_conversion<bool, float2, bool_to_float2>(conversions);
add_implicit_conversion<bool, float3, bool_to_float3>(conversions);
add_implicit_conversion<bool, ColorGeometry4f, bool_to_color>(conversions);
add_implicit_conversion<ColorGeometry4f, bool, color_to_bool>(conversions);
+ add_implicit_conversion<ColorGeometry4f, int8_t, color_to_int8>(conversions);
add_implicit_conversion<ColorGeometry4f, float, color_to_float>(conversions);
add_implicit_conversion<ColorGeometry4f, int32_t, color_to_int>(conversions);
add_implicit_conversion<ColorGeometry4f, float2, color_to_float2>(conversions);
diff --git a/source/blender/blenlib/BLI_enumerable_thread_specific.hh b/source/blender/blenlib/BLI_enumerable_thread_specific.hh
index b5981028893..ce7df1ff4b9 100644
--- a/source/blender/blenlib/BLI_enumerable_thread_specific.hh
+++ b/source/blender/blenlib/BLI_enumerable_thread_specific.hh
@@ -28,10 +28,12 @@
namespace blender::threading {
+#ifndef WITH_TBB
namespace enumerable_thread_specific_utils {
inline std::atomic<int> next_id = 0;
inline thread_local int thread_id = next_id.fetch_add(1, std::memory_order_relaxed);
} // namespace enumerable_thread_specific_utils
+#endif
/**
* This is mainly a wrapper for `tbb::enumerable_thread_specific`. The wrapper is needed because we
diff --git a/source/blender/blenlib/BLI_string_ref.hh b/source/blender/blenlib/BLI_string_ref.hh
index e3dd8afd588..f72106aa961 100644
--- a/source/blender/blenlib/BLI_string_ref.hh
+++ b/source/blender/blenlib/BLI_string_ref.hh
@@ -358,7 +358,9 @@ constexpr int64_t StringRefBase::find_first_of(StringRef chars, int64_t pos) con
constexpr int64_t StringRefBase::find_first_of(char c, int64_t pos) const
{
- return this->find_first_of(StringRef(&c, 1), pos);
+ BLI_assert(pos >= 0);
+ return index_or_npos_to_int64(
+ std::string_view(*this).find_first_of(c, static_cast<size_t>(pos)));
}
constexpr int64_t StringRefBase::find_last_of(StringRef chars, int64_t pos) const
@@ -370,7 +372,9 @@ constexpr int64_t StringRefBase::find_last_of(StringRef chars, int64_t pos) cons
constexpr int64_t StringRefBase::find_last_of(char c, int64_t pos) const
{
- return this->find_last_of(StringRef(&c, 1), pos);
+ BLI_assert(pos >= 0);
+ return index_or_npos_to_int64(
+ std::string_view(*this).find_last_of(c, static_cast<size_t>(pos)));
}
constexpr int64_t StringRefBase::find_first_not_of(StringRef chars, int64_t pos) const
@@ -382,7 +386,9 @@ constexpr int64_t StringRefBase::find_first_not_of(StringRef chars, int64_t pos)
constexpr int64_t StringRefBase::find_first_not_of(char c, int64_t pos) const
{
- return this->find_first_not_of(StringRef(&c, 1), pos);
+ BLI_assert(pos >= 0);
+ return index_or_npos_to_int64(
+ std::string_view(*this).find_first_not_of(c, static_cast<size_t>(pos)));
}
constexpr int64_t StringRefBase::find_last_not_of(StringRef chars, int64_t pos) const
@@ -394,7 +400,9 @@ constexpr int64_t StringRefBase::find_last_not_of(StringRef chars, int64_t pos)
constexpr int64_t StringRefBase::find_last_not_of(char c, int64_t pos) const
{
- return this->find_last_not_of(StringRef(&c, 1), pos);
+ BLI_assert(pos >= 0);
+ return index_or_npos_to_int64(
+ std::string_view(*this).find_last_not_of(c, static_cast<size_t>(pos)));
}
constexpr StringRef StringRefBase::trim() const
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 3800fc58a5b..d61c6c015f6 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -3299,8 +3299,8 @@ static bool point_in_slice(const float p[3],
return (h >= 0.0f && h <= 1.0f);
}
-/* adult sister defining the slice planes by the origin and the normal
- * NOTE |normal| may not be 1 but defining the thickness of the slice */
+/* Adult sister defining the slice planes by the origin and the normal.
+ * NOTE: |normal| may not be 1 but defining the thickness of the slice. */
static bool point_in_slice_as(const float p[3], const float origin[3], const float normal[3])
{
float h, rp[3];
diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c
index 7225ca5fc94..fed330aa2f0 100644
--- a/source/blender/blenlib/intern/math_interp.c
+++ b/source/blender/blenlib/intern/math_interp.c
@@ -706,9 +706,9 @@ void BLI_ewa_filter(const int width,
}
}
- /* d should hopefully never be zero anymore */
+ /* `d` should hopefully never be zero anymore. */
d = 1.0f / d;
mul_v3_fl(result, d);
- /* clipping can be ignored if alpha used, texr->trgba[3] already includes filtered edge */
+ /* Clipping can be ignored if alpha used, `texr->trgba[3]` already includes filtered edge. */
result[3] = use_alpha ? result[3] * d : 1.0f;
}
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index c4c3b42cb63..066b180dcc9 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -117,8 +117,6 @@ typedef struct BlendFileReadReport {
/* Number of root override IDs that were resynced. */
int resynced_lib_overrides;
- /* Number of (non-converted) linked proxies. */
- int linked_proxies;
/* Number of proxies converted to library overrides. */
int proxies_to_lib_overrides_success;
/* Number of proxies that failed to convert to library overrides. */
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 245514d4977..1ff713160df 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -86,10 +86,6 @@ if(WITH_BUILDINFO)
add_definitions(-DWITH_BUILDINFO)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_CODEC_FFMPEG)
add_definitions(-DWITH_FFMPEG)
endif()
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index f3c92aec338..a334d70819d 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -419,9 +419,6 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain,
fd->skip_flags = params->skip_flags;
BLI_strncpy(fd->relabase, filename, sizeof(fd->relabase));
- /* clear ob->proxy_from pointers in old main */
- blo_clear_proxy_pointers_from_lib(oldmain);
-
/* separate libraries from old main */
blo_split_main(&old_mainlist, oldmain);
/* add the library pointers in oldmap lookup */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 38f2d8bb22c..2ba66657499 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1580,15 +1580,6 @@ static void change_link_placeholder_to_real_ID_pointer(ListBase *mainlist,
}
}
-void blo_clear_proxy_pointers_from_lib(Main *oldmain)
-{
- LISTBASE_FOREACH (Object *, ob, &oldmain->objects) {
- if (ID_IS_LINKED(ob) && ob->proxy_from != NULL && !ID_IS_LINKED(ob->proxy_from)) {
- ob->proxy_from = NULL;
- }
- }
-}
-
/* XXX disabled this feature - packed files also belong in temp saves and quit.blend,
* to make restore work. */
@@ -3207,18 +3198,8 @@ static void read_libblock_undo_restore_identical(
id_old->recalc |= direct_link_id_restore_recalc_exceptions(id_old);
id_old->recalc_after_undo_push = 0;
- /* As usual, proxies require some special love...
- * In `blo_clear_proxy_pointers_from_lib()` we clear all `proxy_from` pointers to local IDs, for
- * undo. This is required since we do not re-read linked data in that case, so we also do not
- * re-'lib_link' their pointers.
- * Those `proxy_from` pointers are then re-defined properly when lib_linking the newly read local
- * object. However, in case of re-used data 'as-is', we never lib_link it again, so we have to
- * fix those backward pointers here. */
if (GS(id_old->name) == ID_OB) {
Object *ob = (Object *)id_old;
- if (ob->proxy != NULL) {
- ob->proxy->proxy_from = ob;
- }
/* For undo we stay in object mode during undo presses, so keep editmode disabled for re-used
* data-blocks too. */
ob->mode &= ~OB_MODE_EDIT;
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index 21b0354b097..44045cf99dd 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -144,14 +144,6 @@ FileData *blo_filedata_from_memfile(struct MemFile *memfile,
const struct BlendFileReadParams *params,
struct BlendFileReadReport *reports);
-/**
- * Lib linked proxy objects point to our local data, we need
- * to clear that pointer before reading the undo memfile since
- * the object might be removed, it is set again in reading
- * if the local object still exists.
- * This is only valid for local proxy objects though, linked ones should not be affected here.
- */
-void blo_clear_proxy_pointers_from_lib(struct Main *oldmain);
void blo_make_packed_pointer_map(FileData *fd, struct Main *oldmain);
/**
* Set old main packed data to zero if it has been restored
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 888bd244007..ef146606ff0 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -1122,7 +1122,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
/* Hair and PointCloud attributes. */
for (Hair *hair = bmain->hairs.first; hair != NULL; hair = hair->id.next) {
- do_versions_point_attributes(&hair->pdata);
+ do_versions_point_attributes(&hair->geometry.point_data);
}
for (PointCloud *pointcloud = bmain->pointclouds.first; pointcloud != NULL;
pointcloud = pointcloud->id.next) {
@@ -1424,7 +1424,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
/* Hair and PointCloud attributes names. */
LISTBASE_FOREACH (Hair *, hair, &bmain->hairs) {
- do_versions_point_attribute_names(&hair->pdata);
+ do_versions_point_attribute_names(&hair->geometry.point_data);
}
LISTBASE_FOREACH (PointCloud *, pointcloud, &bmain->pointclouds) {
do_versions_point_attribute_names(&pointcloud->pdata);
diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h
index 21296143226..8785eadf5f1 100644
--- a/source/blender/blentranslation/BLT_translation.h
+++ b/source/blender/blentranslation/BLT_translation.h
@@ -55,24 +55,14 @@ bool BLT_lang_is_ime_supported(void);
#define N_(msgid) msgid
#define CTX_N_(context, msgid) msgid
-/* Those macros should be used everywhere in UI code. */
-#ifdef WITH_INTERNATIONAL
+/* These macros should be used everywhere in UI code. */
/*# define _(msgid) BLT_gettext(msgid) */
-# define IFACE_(msgid) BLT_translate_do_iface(NULL, msgid)
-# define TIP_(msgid) BLT_translate_do_tooltip(NULL, msgid)
-# define DATA_(msgid) BLT_translate_do_new_dataname(NULL, msgid)
-# define CTX_IFACE_(context, msgid) BLT_translate_do_iface(context, msgid)
-# define CTX_TIP_(context, msgid) BLT_translate_do_tooltip(context, msgid)
-# define CTX_DATA_(context, msgid) BLT_translate_do_new_dataname(context, msgid)
-#else
-/*# define _(msgid) msgid */
-# define IFACE_(msgid) msgid
-# define TIP_(msgid) msgid
-# define DATA_(msgid) msgid
-# define CTX_IFACE_(context, msgid) ((void)(0 ? (context) : 0), msgid)
-# define CTX_TIP_(context, msgid) ((void)(0 ? (context) : 0), msgid)
-# define CTX_DATA_(context, msgid) ((void)(0 ? (context) : 0), msgid)
-#endif
+#define IFACE_(msgid) BLT_translate_do_iface(NULL, msgid)
+#define TIP_(msgid) BLT_translate_do_tooltip(NULL, msgid)
+#define DATA_(msgid) BLT_translate_do_new_dataname(NULL, msgid)
+#define CTX_IFACE_(context, msgid) BLT_translate_do_iface(context, msgid)
+#define CTX_TIP_(context, msgid) BLT_translate_do_tooltip(context, msgid)
+#define CTX_DATA_(context, msgid) BLT_translate_do_new_dataname(context, msgid)
/* Helper macro, when we want to define a same msgid for multiple msgctxt...
* Does nothing in C, but is "parsed" by our i18n py tools.
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index e2ed005cf9e..a61327238fe 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -207,10 +207,6 @@ if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
diff --git a/source/blender/bmesh/tools/bmesh_boolean.cc b/source/blender/bmesh/tools/bmesh_boolean.cc
index e244bc377db..91883b0adee 100644
--- a/source/blender/bmesh/tools/bmesh_boolean.cc
+++ b/source/blender/bmesh/tools/bmesh_boolean.cc
@@ -192,12 +192,12 @@ static bool apply_mesh_output_to_bmesh(BMesh *bm, IMesh &m_out, bool keep_hidden
BM_elem_flag_enable(bmv, KEEP_FLAG);
}
else {
- new_bmvs[v] = NULL;
+ new_bmvs[v] = nullptr;
}
}
for (int v : m_out.vert_index_range()) {
const Vert *vertp = m_out.vert(v);
- if (new_bmvs[v] == NULL) {
+ if (new_bmvs[v] == nullptr) {
float co[3];
const double3 &d_co = vertp->co;
for (int i = 0; i < 3; ++i) {
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index b9b365a3175..2f473ef2945 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -274,10 +274,14 @@ set(SRC
# converter nodes
nodes/COM_CombineColorNode.cc
nodes/COM_CombineColorNode.h
+ nodes/COM_CombineXYZNode.cc
+ nodes/COM_CombineXYZNode.h
nodes/COM_IDMaskNode.cc
nodes/COM_IDMaskNode.h
nodes/COM_SeparateColorNode.cc
nodes/COM_SeparateColorNode.h
+ nodes/COM_SeparateXYZNode.cc
+ nodes/COM_SeparateXYZNode.h
nodes/COM_MapRangeNode.cc
nodes/COM_MapRangeNode.h
@@ -631,10 +635,6 @@ list(APPEND SRC
unset(GENSRC)
unset(GENSRC_DIR)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_OPENIMAGEDENOISE)
add_definitions(-DWITH_OPENIMAGEDENOISE)
add_definitions(-DOIDN_STATIC_LIB)
diff --git a/source/blender/compositor/intern/COM_Converter.cc b/source/blender/compositor/intern/COM_Converter.cc
index 6cf6c698a2f..d0b3ae74446 100644
--- a/source/blender/compositor/intern/COM_Converter.cc
+++ b/source/blender/compositor/intern/COM_Converter.cc
@@ -44,6 +44,7 @@
#include "COM_ColorSpillNode.h"
#include "COM_ColorToBWNode.h"
#include "COM_CombineColorNode.h"
+#include "COM_CombineXYZNode.h"
#include "COM_CompositorNode.h"
#include "COM_ConvertAlphaNode.h"
#include "COM_ConvertColorSpaceNode.h"
@@ -96,6 +97,7 @@
#include "COM_ScaleOperation.h"
#include "COM_SceneTimeNode.h"
#include "COM_SeparateColorNode.h"
+#include "COM_SeparateXYZNode.h"
#include "COM_SetAlphaNode.h"
#include "COM_SetValueOperation.h"
#include "COM_SplitViewerNode.h"
@@ -434,6 +436,12 @@ Node *COM_convert_bnode(bNode *b_node)
case CMP_NODE_CONVERT_COLOR_SPACE:
node = new ConvertColorSpaceNode(b_node);
break;
+ case CMP_NODE_SEPARATE_XYZ:
+ node = new SeparateXYZNode(b_node);
+ break;
+ case CMP_NODE_COMBINE_XYZ:
+ node = new CombineXYZNode(b_node);
+ break;
}
return node;
}
diff --git a/source/blender/compositor/nodes/COM_CombineXYZNode.cc b/source/blender/compositor/nodes/COM_CombineXYZNode.cc
new file mode 100644
index 00000000000..2b71b94e192
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_CombineXYZNode.cc
@@ -0,0 +1,55 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#include "COM_CombineXYZNode.h"
+
+#include "COM_ConvertOperation.h"
+
+namespace blender::compositor {
+
+CombineXYZNode::CombineXYZNode(bNode *editor_node) : Node(editor_node)
+{
+}
+
+void CombineXYZNode::convert_to_operations(NodeConverter &converter,
+ const CompositorContext &UNUSED(context)) const
+{
+ NodeInput *input_x_socket = this->get_input_socket(0);
+ NodeInput *input_y_socket = this->get_input_socket(1);
+ NodeInput *input_z_socket = this->get_input_socket(2);
+ NodeOutput *output_socket = this->get_output_socket(0);
+
+ CombineChannelsOperation *operation = new CombineChannelsOperation();
+ if (input_x_socket->is_linked()) {
+ operation->set_canvas_input_index(0);
+ }
+ else if (input_y_socket->is_linked()) {
+ operation->set_canvas_input_index(1);
+ }
+ else {
+ operation->set_canvas_input_index(2);
+ }
+ converter.add_operation(operation);
+
+ converter.map_input_socket(input_x_socket, operation->get_input_socket(0));
+ converter.map_input_socket(input_y_socket, operation->get_input_socket(1));
+ converter.map_input_socket(input_z_socket, operation->get_input_socket(2));
+ converter.map_output_socket(output_socket, operation->get_output_socket());
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CombineXYZNode.h b/source/blender/compositor/nodes/COM_CombineXYZNode.h
new file mode 100644
index 00000000000..c3bb69b03ed
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_CombineXYZNode.h
@@ -0,0 +1,36 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#pragma once
+
+#include "COM_Node.h"
+
+namespace blender::compositor {
+
+/**
+ * \brief SeparateXYZNode
+ * \ingroup Node
+ */
+class CombineXYZNode : public Node {
+ public:
+ CombineXYZNode(bNode *editor_node);
+ void convert_to_operations(NodeConverter &converter,
+ const CompositorContext &context) const override;
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SeparateXYZNode.cc b/source/blender/compositor/nodes/COM_SeparateXYZNode.cc
new file mode 100644
index 00000000000..749116d6217
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_SeparateXYZNode.cc
@@ -0,0 +1,63 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#include "COM_SeparateXYZNode.h"
+
+#include "COM_ConvertOperation.h"
+
+namespace blender::compositor {
+
+SeparateXYZNode::SeparateXYZNode(bNode *editor_node) : Node(editor_node)
+{
+ /* pass */
+}
+
+void SeparateXYZNode::convert_to_operations(NodeConverter &converter,
+ const CompositorContext &UNUSED(context)) const
+{
+ NodeInput *vector_socket = this->get_input_socket(0);
+ NodeOutput *output_x_socket = this->get_output_socket(0);
+ NodeOutput *output_y_socket = this->get_output_socket(1);
+ NodeOutput *output_z_socket = this->get_output_socket(2);
+
+ {
+ SeparateChannelOperation *operation = new SeparateChannelOperation();
+ operation->set_channel(0);
+ converter.add_operation(operation);
+ converter.map_input_socket(vector_socket, operation->get_input_socket(0));
+ converter.map_output_socket(output_x_socket, operation->get_output_socket(0));
+ }
+
+ {
+ SeparateChannelOperation *operation = new SeparateChannelOperation();
+ operation->set_channel(1);
+ converter.add_operation(operation);
+ converter.map_input_socket(vector_socket, operation->get_input_socket(0));
+ converter.map_output_socket(output_y_socket, operation->get_output_socket(0));
+ }
+
+ {
+ SeparateChannelOperation *operation = new SeparateChannelOperation();
+ operation->set_channel(2);
+ converter.add_operation(operation);
+ converter.map_input_socket(vector_socket, operation->get_input_socket(0));
+ converter.map_output_socket(output_z_socket, operation->get_output_socket(0));
+ }
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SeparateXYZNode.h b/source/blender/compositor/nodes/COM_SeparateXYZNode.h
new file mode 100644
index 00000000000..1efa017d9e3
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_SeparateXYZNode.h
@@ -0,0 +1,36 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#pragma once
+
+#include "COM_Node.h"
+
+namespace blender::compositor {
+
+/**
+ * \brief SeparateXYZNode
+ * \ingroup Node
+ */
+class SeparateXYZNode : public Node {
+ public:
+ SeparateXYZNode(bNode *editor_node);
+ void convert_to_operations(NodeConverter &converter,
+ const CompositorContext &context) const override;
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
index 0461d8b63fd..8e4a7dafcd6 100644
--- a/source/blender/depsgraph/DEG_depsgraph_build.h
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -111,9 +111,6 @@ typedef enum eDepsObjectComponentType {
/* Parameters Component - Default when nothing else fits
* (i.e. just SDNA property setting). */
DEG_OB_COMP_PARAMETERS,
- /* Generic "Proxy-Inherit" Component.
- * TODO(sergey): Also for instancing of subgraphs? */
- DEG_OB_COMP_PROXY,
/* Animation Component.
*
* TODO(sergey): merge in with parameters? */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index b2e136c3d3b..990021dc29b 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -125,10 +125,6 @@ bool DepsgraphBuilder::check_pchan_has_bbone(Object *object, const bPoseChannel
bool DepsgraphBuilder::check_pchan_has_bbone_segments(Object *object, const bPoseChannel *pchan)
{
- /* Proxies don't have BONE_SEGMENTS */
- if (ID_IS_LINKED(object) && object->proxy_from != nullptr) {
- return false;
- }
return check_pchan_has_bbone(object, pchan);
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 79d674e8415..b886d5a5b9a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -726,9 +726,6 @@ void DepsgraphNodeBuilder::build_object(int base_index,
eDepsNode_LinkedState_Type linked_state,
bool is_visible)
{
- if (object->proxy != nullptr) {
- object->proxy->proxy_from = object;
- }
const bool has_object = built_map_.checkIsBuiltAndTag(object);
/* When there is already object in the dependency graph accumulate visibility an linked state
@@ -819,9 +816,6 @@ void DepsgraphNodeBuilder::build_object(int base_index,
(object->pd->tex != nullptr)) {
build_texture(object->pd->tex);
}
- /* Proxy object to copy from. */
- build_object_proxy_from(object, is_visible);
- build_object_proxy_group(object, is_visible);
/* Object dupligroup. */
if (object->instance_collection != nullptr) {
build_object_instance_collection(object, is_visible);
@@ -875,22 +869,6 @@ void DepsgraphNodeBuilder::build_object_flags(int base_index,
});
}
-void DepsgraphNodeBuilder::build_object_proxy_from(Object *object, bool is_object_visible)
-{
- if (object->proxy_from == nullptr) {
- return;
- }
- build_object(-1, object->proxy_from, DEG_ID_LINKED_INDIRECTLY, is_object_visible);
-}
-
-void DepsgraphNodeBuilder::build_object_proxy_group(Object *object, bool is_object_visible)
-{
- if (object->proxy_group == nullptr) {
- return;
- }
- build_object(-1, object->proxy_group, DEG_ID_LINKED_INDIRECTLY, is_object_visible);
-}
-
void DepsgraphNodeBuilder::build_object_instance_collection(Object *object, bool is_object_visible)
{
if (object->instance_collection == nullptr) {
@@ -922,12 +900,7 @@ void DepsgraphNodeBuilder::build_object_data(Object *object)
build_object_data_geometry(object);
break;
case OB_ARMATURE:
- if (ID_IS_LINKED(object) && object->proxy_from != nullptr) {
- build_proxy_rig(object);
- }
- else {
- build_rig(object);
- }
+ build_rig(object);
break;
case OB_LAMP:
build_object_data_light(object);
@@ -1183,12 +1156,6 @@ void DepsgraphNodeBuilder::build_driver_variables(ID *id, FCurve *fcurve)
}
build_id(dtar->id);
build_driver_id_property(dtar->id, dtar->rna_path);
- /* Corresponds to dtar_id_ensure_proxy_from(). */
- if ((GS(dtar->id->name) == ID_OB) && (((Object *)dtar->id)->proxy_from != nullptr)) {
- Object *proxy_from = ((Object *)dtar->id)->proxy_from;
- build_id(&proxy_from->id);
- build_driver_id_property(&proxy_from->id, dtar->rna_path);
- }
}
DRIVER_TARGETS_LOOPER_END;
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index a1db4aaf693..6e319383478 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -184,8 +184,6 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
Object *object,
eDepsNode_LinkedState_Type linked_state,
bool is_visible);
- virtual void build_object_proxy_from(Object *object, bool is_object_visible);
- virtual void build_object_proxy_group(Object *object, bool is_object_visible);
virtual void build_object_instance_collection(Object *object, bool is_object_visible);
virtual void build_object_from_layer(int base_index,
Object *object,
@@ -232,7 +230,6 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
virtual void build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con);
virtual void build_splineik_pose(Object *object, bPoseChannel *pchan, bConstraint *con);
virtual void build_rig(Object *object);
- virtual void build_proxy_rig(Object *object);
virtual void build_armature(bArmature *armature);
virtual void build_armature_bones(ListBase *bones);
virtual void build_shapekeys(Key *key);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
index e8dda7b8de4..0e196450f60 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
@@ -306,72 +306,4 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
}
}
-void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
-{
- bArmature *armature = (bArmature *)object->data;
- OperationNode *op_node;
- Object *object_cow = get_cow_datablock(object);
- /* Sanity check. */
- BLI_assert(object->pose != nullptr);
- /* Armature. */
- build_armature(armature);
- /* speed optimization for animation lookups */
- BKE_pose_channels_hash_ensure(object->pose);
- if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
- BKE_pose_update_constraint_flags(object->pose);
- }
- op_node = add_operation_node(
- &object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_INIT,
- [object_cow](::Depsgraph *depsgraph) { BKE_pose_eval_proxy_init(depsgraph, object_cow); });
- op_node->set_as_entry();
-
- int pchan_index = 0;
- LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- op_node = add_operation_node(
- &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
- op_node->set_as_entry();
- /* Bone is ready for solvers. */
- add_operation_node(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
- /* Bone is fully evaluated. */
- op_node = add_operation_node(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_DONE,
- [object_cow, pchan_index](::Depsgraph *depsgraph) {
- BKE_pose_eval_proxy_copy_bone(
- depsgraph, object_cow, pchan_index);
- });
- op_node->set_as_exit();
-
- /* Custom properties. */
- if (pchan->prop != nullptr) {
- build_idproperties(pchan->prop);
- add_operation_node(
- &object->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, nullptr, pchan->name);
- }
-
- /* Custom shape. */
- if (pchan->custom != nullptr) {
- /* NOTE: The relation builder will ensure visibility of the custom shape object. */
- build_object(-1, pchan->custom, DEG_ID_LINKED_INDIRECTLY, false);
- }
-
- pchan_index++;
- }
- op_node = add_operation_node(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_CLEANUP,
- [object_cow](::Depsgraph *depsgraph) {
- BKE_pose_eval_proxy_cleanup(depsgraph, object_cow);
- });
- op_node = add_operation_node(
- &object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_DONE,
- [object_cow](::Depsgraph *depsgraph) { BKE_pose_eval_proxy_done(depsgraph, object_cow); });
- op_node->set_as_exit();
-}
-
} // namespace blender::deg
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index cb43ef685d4..97dae46c75f 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -787,9 +787,6 @@ void DepsgraphRelationBuilder::build_object(Object *object)
(object->pd->tex != nullptr)) {
build_texture(object->pd->tex);
}
- /* Proxy object to copy from. */
- build_object_proxy_from(object);
- build_object_proxy_group(object);
/* Object dupligroup. */
if (object->instance_collection != nullptr) {
build_collection(nullptr, object, object->instance_collection);
@@ -804,31 +801,6 @@ void DepsgraphRelationBuilder::build_object(Object *object)
build_parameters(&object->id);
}
-void DepsgraphRelationBuilder::build_object_proxy_from(Object *object)
-{
- if (object->proxy_from == nullptr) {
- return;
- }
- /* Object is linked here (comes from the library). */
- build_object(object->proxy_from);
- ComponentKey ob_transform_key(&object->proxy_from->id, NodeType::TRANSFORM);
- ComponentKey proxy_transform_key(&object->id, NodeType::TRANSFORM);
- add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform");
-}
-
-void DepsgraphRelationBuilder::build_object_proxy_group(Object *object)
-{
- if (ELEM(object->proxy_group, nullptr, object->proxy)) {
- return;
- }
- /* Object is local here (local in .blend file, users interacts with it). */
- build_object(object->proxy_group);
- OperationKey proxy_group_eval_key(
- &object->proxy_group->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
- OperationKey transform_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
- add_relation(proxy_group_eval_key, transform_eval_key, "Proxy Group Transform");
-}
-
void DepsgraphRelationBuilder::build_object_from_layer_relations(Object *object)
{
OperationKey object_from_layer_entry_key(
@@ -895,12 +867,7 @@ void DepsgraphRelationBuilder::build_object_data(Object *object)
break;
}
case OB_ARMATURE:
- if (ID_IS_LINKED(object) && object->proxy_from != nullptr) {
- build_proxy_rig(object);
- }
- else {
- build_rig(object);
- }
+ build_rig(object);
break;
case OB_LAMP:
build_object_data_light(object);
@@ -1663,18 +1630,9 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
}
build_id(target_id);
build_driver_id_property(target_id, dtar->rna_path);
- /* Look up the proxy - matches dtar_id_ensure_proxy_from during evaluation. */
Object *object = nullptr;
if (GS(target_id->name) == ID_OB) {
object = (Object *)target_id;
- if (object->proxy_from != nullptr) {
- /* Redirect the target to the proxy, like in evaluation. */
- object = object->proxy_from;
- target_id = &object->id;
- /* Prepare the redirected target. */
- build_id(target_id);
- build_driver_id_property(target_id, dtar->rna_path);
- }
}
/* Special handling for directly-named bones. */
if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (object && object->type == OB_ARMATURE) &&
@@ -2034,7 +1992,7 @@ void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part)
"Particle Texture -> Particle Reset",
RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
add_relation(texture_key, particle_settings_eval_key, "Particle Texture -> Particle Eval");
- /* TODO(sergey): Consider moving texture space handling to an own
+ /* TODO(sergey): Consider moving texture space handling to its own
* function. */
if (mtex->texco == TEXCO_OBJECT && mtex->object != nullptr) {
ComponentKey object_key(&mtex->object->id, NodeType::TRANSFORM);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index d699c799e40..df315176a92 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -216,8 +216,6 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
Object *object,
Collection *collection);
virtual void build_object(Object *object);
- virtual void build_object_proxy_from(Object *object);
- virtual void build_object_proxy_group(Object *object);
virtual void build_object_from_layer_relations(Object *object);
virtual void build_object_data(Object *object);
virtual void build_object_data_camera(Object *object);
@@ -273,7 +271,6 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
const bPoseChannel *rootchan,
const RootPChanMap *root_map);
virtual void build_rig(Object *object);
- virtual void build_proxy_rig(Object *object);
virtual void build_shapekeys(Key *key);
virtual void build_armature(bArmature *armature);
virtual void build_armature_bones(ListBase *bones);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
index 856e37ee473..377ef9fc357 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
@@ -471,65 +471,4 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
}
}
-void DepsgraphRelationBuilder::build_proxy_rig(Object *object)
-{
- bArmature *armature = (bArmature *)object->data;
- Object *proxy_from = object->proxy_from;
- build_armature(armature);
- OperationKey pose_init_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT);
- OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
- OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
- LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- build_idproperties(pchan->prop);
- OperationKey bone_local_key(
- &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
- OperationKey bone_ready_key(
- &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
- OperationKey bone_done_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
- OperationKey from_bone_done_key(
- &proxy_from->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
- add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local");
- add_relation(bone_local_key, bone_ready_key, "Local -> Ready");
- add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
- add_relation(bone_done_key, pose_cleanup_key, "Bone Done -> Pose Cleanup");
- add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done", RELATION_FLAG_GODMODE);
- /* Make sure bone in the proxy is not done before its FROM is done. */
- if (check_pchan_has_bbone(object, pchan)) {
- OperationKey from_bone_segments_key(
- &proxy_from->id, NodeType::BONE, pchan->name, OperationCode::BONE_SEGMENTS);
- add_relation(from_bone_segments_key,
- bone_done_key,
- "Bone Segments -> Bone Done",
- RELATION_FLAG_GODMODE);
- }
- else {
- add_relation(from_bone_done_key, bone_done_key, "Bone Done -> Bone Done");
- }
-
- /* Parent relation: even though the proxy bone itself doesn't need
- * the parent bone, some users expect the parent to be ready if the
- * bone itself is (e.g. for computing the local space matrix).
- */
- if (pchan->parent != nullptr) {
- OperationKey parent_key(
- &object->id, NodeType::BONE, pchan->parent->name, OperationCode::BONE_DONE);
- add_relation(parent_key, bone_done_key, "Parent Bone -> Child Bone");
- }
-
- if (pchan->prop != nullptr) {
- OperationKey bone_parameters(
- &object->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, pchan->name);
- OperationKey from_bone_parameters(
- &proxy_from->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, pchan->name);
- add_relation(from_bone_parameters, bone_parameters, "Proxy Bone Parameters");
- }
-
- /* Custom shape. */
- if (pchan->custom != nullptr) {
- build_object(pchan->custom);
- add_visibility_relation(&pchan->custom->id, &armature->id);
- }
- }
-}
-
} // namespace blender::deg
diff --git a/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc b/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc
index 9e62432ea54..b77b935b9f6 100644
--- a/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc
+++ b/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc
@@ -63,17 +63,6 @@ class DepsgraphFromIDsNodeBuilder : public DepsgraphNodeBuilder {
return DepsgraphNodeBuilder::need_pull_base_into_graph(base);
}
- void build_object_proxy_group(Object *object, bool is_visible) override
- {
- if (object->proxy_group == nullptr) {
- return;
- }
- if (!filter_.contains(&object->proxy_group->id)) {
- return;
- }
- DepsgraphNodeBuilder::build_object_proxy_group(object, is_visible);
- }
-
protected:
DepsgraphFromIDsFilter filter_;
};
@@ -96,17 +85,6 @@ class DepsgraphFromIDsRelationBuilder : public DepsgraphRelationBuilder {
return DepsgraphRelationBuilder::need_pull_base_into_graph(base);
}
- void build_object_proxy_group(Object *object) override
- {
- if (object->proxy_group == nullptr) {
- return;
- }
- if (!filter_.contains(&object->proxy_group->id)) {
- return;
- }
- DepsgraphRelationBuilder::build_object_proxy_group(object);
- }
-
protected:
DepsgraphFromIDsFilter filter_;
};
diff --git a/source/blender/depsgraph/intern/builder/pipeline_from_ids.h b/source/blender/depsgraph/intern/builder/pipeline_from_ids.h
index 79fcfc52446..8c89bbf1660 100644
--- a/source/blender/depsgraph/intern/builder/pipeline_from_ids.h
+++ b/source/blender/depsgraph/intern/builder/pipeline_from_ids.h
@@ -36,10 +36,7 @@ namespace deg {
* visibility and other flags assigned to the objects.
* All other bases (the ones which points to object which is outside of the set of IDs) are
* completely ignored.
- *
- * - Proxy groups pointing to objects which are outside of the IDs set are also ignored.
- * This way we avoid high-poly character body pulled into the dependency graph when it's coming
- * from a library into an animation file and the dependency graph constructed for a proxy rig. */
+ */
class FromIDsBuilderPipeline : public AbstractBuilderPipeline {
public:
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
index 36120ae76d1..ef82584d671 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
@@ -99,7 +99,6 @@ static const int deg_debug_node_type_color_map[][2] = {
/* Outer Types */
{NodeType::PARAMETERS, 2},
- {NodeType::PROXY, 3},
{NodeType::ANIMATION, 4},
{NodeType::TRANSFORM, 5},
{NodeType::GEOMETRY, 6},
@@ -404,7 +403,6 @@ static void deg_debug_graphviz_node(DotExportContext &ctx,
case NodeType::PARAMETERS:
case NodeType::ANIMATION:
case NodeType::TRANSFORM:
- case NodeType::PROXY:
case NodeType::GEOMETRY:
case NodeType::SEQUENCER:
case NodeType::EVAL_POSE:
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 11074b5bf72..d9147d88045 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -526,12 +526,6 @@ void graph_tag_ids_for_visible_update(Depsgraph *graph)
* 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 != nullptr) {
- object_orig->proxy->proxy_from = object_orig;
- }
- }
if (!id_node->visible_components_mask) {
/* ID has no components which affects anything visible.
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index c2b85caad66..b64f94568f6 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -646,8 +646,8 @@ void set_particle_system_modifiers_loaded(Object *object_cow)
void reset_particle_system_edit_eval(const Depsgraph *depsgraph, Object *object_cow)
{
- /* Inactive (and render) dependency graphs are living in own little bubble, should not care about
- * edit mode at all. */
+ /* Inactive (and render) dependency graphs are living in their own little bubble, should not care
+ * about edit mode at all. */
if (!DEG_is_active(reinterpret_cast<const ::Depsgraph *>(depsgraph))) {
return;
}
@@ -708,25 +708,6 @@ void update_animation_data_after_copy(const ID *id_orig, ID *id_cow)
update_nla_tracks_orig_pointers(&anim_data_orig->nla_tracks, &anim_data_cow->nla_tracks);
}
-/* Some builders (like motion path one) will ignore proxies from being built. This code makes it so
- * proxy and proxy_group pointers never point to an original objects, preventing evaluation code
- * from assign evaluated pointer to an original proxy->proxy_from. */
-void update_proxy_pointers_after_copy(const Depsgraph *depsgraph,
- const Object *object_orig,
- Object *object_cow)
-{
- if (object_cow->proxy != nullptr) {
- if (!deg_check_id_in_depsgraph(depsgraph, &object_orig->proxy->id)) {
- object_cow->proxy = nullptr;
- }
- }
- if (object_cow->proxy_group != nullptr) {
- if (!deg_check_id_in_depsgraph(depsgraph, &object_orig->proxy_group->id)) {
- object_cow->proxy_group = nullptr;
- }
- }
-}
-
/* Do some special treatment of data transfer from original ID to its
* CoW complementary part.
*
@@ -760,7 +741,6 @@ void update_id_after_copy(const Depsgraph *depsgraph,
BKE_gpencil_update_orig_pointers(object_orig, object_cow);
}
update_particles_after_copy(depsgraph, object_orig, object_cow);
- update_proxy_pointers_after_copy(depsgraph, object_orig, object_cow);
break;
}
case ID_SCE: {
diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc
index 075bfd35ec1..1eb76d76c22 100644
--- a/source/blender/depsgraph/intern/node/deg_node.cc
+++ b/source/blender/depsgraph/intern/node/deg_node.cc
@@ -67,8 +67,6 @@ const char *nodeTypeAsString(NodeType type)
/* **** Outer Types **** */
case NodeType::PARAMETERS:
return "PARAMETERS";
- case NodeType::PROXY:
- return "PROXY";
case NodeType::ANIMATION:
return "ANIMATION";
case NodeType::TRANSFORM:
@@ -174,7 +172,6 @@ eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type)
case NodeType::BONE:
case NodeType::SHADING:
case NodeType::CACHE:
- case NodeType::PROXY:
case NodeType::SIMULATION:
case NodeType::NTREE_OUTPUT:
return DEG_SCENE_COMP_PARAMETERS;
@@ -194,8 +191,6 @@ NodeType nodeTypeFromObjectComponent(eDepsObjectComponentType component_type)
return NodeType::UNDEFINED;
case DEG_OB_COMP_PARAMETERS:
return NodeType::PARAMETERS;
- case DEG_OB_COMP_PROXY:
- return NodeType::PROXY;
case DEG_OB_COMP_ANIMATION:
return NodeType::ANIMATION;
case DEG_OB_COMP_TRANSFORM:
@@ -219,8 +214,6 @@ eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type)
switch (type) {
case NodeType::PARAMETERS:
return DEG_OB_COMP_PARAMETERS;
- case NodeType::PROXY:
- return DEG_OB_COMP_PROXY;
case NodeType::ANIMATION:
return DEG_OB_COMP_ANIMATION;
case NodeType::TRANSFORM:
diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h
index 25bbb9a7237..72d3e375bcd 100644
--- a/source/blender/depsgraph/intern/node/deg_node.h
+++ b/source/blender/depsgraph/intern/node/deg_node.h
@@ -77,8 +77,6 @@ enum class NodeType {
/* Parameters Component - Default when nothing else fits
* (i.e. just SDNA property setting). */
PARAMETERS,
- /* Generic "Proxy-Inherit" Component. */
- PROXY,
/* Animation Component */
ANIMATION,
/* Transform Component (Parenting/Constraints) */
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc
index 4c430904e44..e14f758c739 100644
--- a/source/blender/depsgraph/intern/node/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_component.cc
@@ -339,7 +339,6 @@ DEG_COMPONENT_NODE_DEFINE(Particles, PARTICLE_SYSTEM, ID_RECALC_GEOMETRY);
DEG_COMPONENT_NODE_DEFINE(ParticleSettings, PARTICLE_SETTINGS, 0);
DEG_COMPONENT_NODE_DEFINE(PointCache, POINT_CACHE, 0);
DEG_COMPONENT_NODE_DEFINE(Pose, EVAL_POSE, ID_RECALC_GEOMETRY);
-DEG_COMPONENT_NODE_DEFINE(Proxy, PROXY, ID_RECALC_GEOMETRY);
DEG_COMPONENT_NODE_DEFINE(Sequencer, SEQUENCER, 0);
DEG_COMPONENT_NODE_DEFINE(Shading, SHADING, ID_RECALC_SHADING);
DEG_COMPONENT_NODE_DEFINE(Transform, TRANSFORM, ID_RECALC_TRANSFORM);
@@ -373,7 +372,6 @@ void deg_register_component_depsnodes()
register_node_typeinfo(&DNTI_PARTICLE_SETTINGS);
register_node_typeinfo(&DNTI_POINT_CACHE);
register_node_typeinfo(&DNTI_IMAGE_ANIMATION);
- register_node_typeinfo(&DNTI_PROXY);
register_node_typeinfo(&DNTI_EVAL_POSE);
register_node_typeinfo(&DNTI_SEQUENCER);
register_node_typeinfo(&DNTI_SHADING);
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h
index f7acd8c72c3..d45d4642937 100644
--- a/source/blender/depsgraph/intern/node/deg_node_component.h
+++ b/source/blender/depsgraph/intern/node/deg_node_component.h
@@ -192,7 +192,6 @@ DEG_COMPONENT_NODE_DECLARE_GENERIC(Particles);
DEG_COMPONENT_NODE_DECLARE_GENERIC(ParticleSettings);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Pose);
DEG_COMPONENT_NODE_DECLARE_GENERIC(PointCache);
-DEG_COMPONENT_NODE_DECLARE_GENERIC(Proxy);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Sequencer);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Shading);
DEG_COMPONENT_NODE_DECLARE_GENERIC(ShadingParameters);
diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
index 4748323d6a7..d0c0635a1fb 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -251,7 +251,7 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),
effects->dof_coc_params[1] = -aperture *
fabsf(focal_len_scaled / (focus_dist - focal_len_scaled));
- /* FIXME(fclem) This is broken for vertically fit sensor. */
+ /* FIXME(@fclem): This is broken for vertically fit sensor. */
effects->dof_coc_params[1] *= viewport_size[0] / sensor_scaled;
if ((scene_eval->eevee.flag & SCE_EEVEE_DOF_JITTER) != 0) {
@@ -625,7 +625,7 @@ static void dof_reduce_pass_init(EEVEE_FramebufferList *fbl,
}
if (txl->dof_reduced_color) {
- /* TODO(fclem) In the future, we need to check if mip_count did not change.
+ /* TODO(@fclem): In the future, we need to check if mip_count did not change.
* For now it's ok as we always define all mip level. */
if (res[0] != GPU_texture_width(txl->dof_reduced_color) ||
res[1] != GPU_texture_width(txl->dof_reduced_color)) {
@@ -642,7 +642,8 @@ static void dof_reduce_pass_init(EEVEE_FramebufferList *fbl,
txl->dof_reduced_coc = GPU_texture_create_2d(
"dof_reduced_coc", UNPACK2(res), mip_count, GPU_R16F, NULL);
- /* TODO(fclem) Remove once we have immutable storage or when mips are generated on creation. */
+ /* TODO(@fclem): Remove once we have immutable storage or when mips are generated on creation.
+ */
GPU_texture_generate_mipmap(txl->dof_reduced_color);
GPU_texture_generate_mipmap(txl->dof_reduced_coc);
}
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index c51fc18a406..c7a8d2cc001 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -1077,8 +1077,8 @@ void EEVEE_lightbake_filter_diffuse(EEVEE_ViewLayerData *sldata,
pinfo->intensity_fac = intensity;
- /* find cell position on the virtual 3D texture */
- /* NOTE : Keep in sync with load_irradiance_cell() */
+ /* Find cell position on the virtual 3D texture. */
+ /* NOTE: Keep in sync with `load_irradiance_cell()`. */
#if defined(IRRADIANCE_SH_L2)
int size[2] = {3, 3};
#elif defined(IRRADIANCE_HL2)
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 9e7a67060da..e4e7f6fa4e3 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -517,8 +517,7 @@ static void eevee_render_draw_background(EEVEE_Data *vedata)
EEVEE_PassList *psl = vedata->psl;
/* Prevent background to write to data buffers.
- * NOTE : This also make sure the textures are bound
- * to the right double buffer. */
+ * NOTE: This also make sure the textures are bound to the right double buffer. */
GPU_framebuffer_ensure_config(&fbl->main_fb,
{GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE,
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 48c24d138e6..81d9d560320 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -49,7 +49,7 @@ void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
if (effects->enabled_effects & EFFECT_SSS) {
- /* NOTE : we need another stencil because the stencil buffer is on the same texture
+ /* NOTE: we need another stencil because the stencil buffer is on the same texture
* as the depth buffer we are sampling from. This could be avoided if the stencil is
* a separate texture but that needs OpenGL 4.4 or ARB_texture_stencil8.
* OR OpenGL 4.3 / ARB_ES3_compatibility if using a render-buffer instead. */
diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
index 1061b2f91a2..1c7ef775ac2 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -56,7 +56,7 @@ vec2 get_ao_noise(void)
{
vec2 noise = texelfetch_noise_tex(gl_FragCoord.xy).xy;
/* Decorrelate noise from AA. */
- /* TODO(fclem) we should use a more general approach for more random number dimensions. */
+ /* TODO(@fclem): we should use a more general approach for more random number dimensions. */
noise = fract(noise * 6.1803402007);
return noise;
}
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
index 4f9791ac95f..5bf20fe6979 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
@@ -43,7 +43,7 @@ void closure_Diffuse_light_eval(ClosureInputDiffuse cl_in,
inout ClosureOutputDiffuse cl_out)
{
float radiance = light_diffuse(light.data, cl_in.N, cl_common.V, light.L);
- /* TODO(fclem) We could try to shadow lights that are shadowless with the ambient_occlusion
+ /* TODO(@fclem): We could try to shadow lights that are shadowless with the ambient_occlusion
* factor here. */
cl_out.radiance += light.data.l_color *
(light.data.l_diff * light.vis * light.contact_shadow * radiance);
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
index 00d265a48b0..584aacc9e19 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
@@ -63,7 +63,7 @@ ClosureEvalGlossy closure_Glossy_eval_init(inout ClosureInputGlossy cl_in,
/* The brdf split sum LUT is applied after the radiance accumulation.
* Correct the LTC so that its energy is constant. */
- /* TODO(fclem) Optimize this so that only one scale factor is stored. */
+ /* TODO(@fclem): Optimize this so that only one scale factor is stored. */
vec4 ltc_brdf = texture(utilTex, vec3(lut_uv, LTC_BRDF_LAYER)).barg;
vec2 split_sum_brdf = ltc_brdf.zw;
cl_eval.ltc_brdf_scale = (ltc_brdf.x + ltc_brdf.y) / (split_sum_brdf.x + split_sum_brdf.y);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl
index db9ae0f7034..f5c45d147e6 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl
@@ -52,7 +52,7 @@ const float unit_ring_radius = 1.0 / float(gather_ring_count);
const float unit_sample_radius = 1.0 / float(gather_ring_count + 0.5);
const float large_kernel_radius = 0.5 + float(gather_ring_count);
const float smaller_kernel_radius = 0.5 + float(gather_ring_count - gather_density_change_ring);
-/* NOTE(fclem) the bias is reducing issues with density change visible transition. */
+/* NOTE(@fclem): the bias is reducing issues with density change visible transition. */
const float radius_downscale_factor = smaller_kernel_radius / large_kernel_radius;
const int change_density_at_ring = (gather_ring_count - gather_density_change_ring + 1);
const float coc_radius_error = 2.0;
@@ -83,7 +83,7 @@ void dof_gather_init(float base_radius,
#endif
center_co = gl_FragCoord.xy + jitter_ofs * base_radius * unit_sample_radius;
- /* TODO(fclem) Seems like the default lod selection is too big. Bias to avoid blocky moving
+ /* TODO(@fclem): Seems like the default lod selection is too big. Bias to avoid blocky moving
* out of focus shapes. */
const float lod_bias = -2.0;
lod = max(floor(log2(base_radius * unit_sample_radius) + 0.5) + lod_bias, 0.0);
@@ -111,7 +111,7 @@ void dof_gather_accumulator(float base_radius,
* a ring. So we need to compensate for fast gather that does not check CoC intersection. */
base_radius += (0.5 - noise.x) * 1.5 * unit_ring_radius * base_radius;
}
- /* TODO(fclem) another seed? For now Cranly-Partterson rotation with golden ratio. */
+ /* TODO(@fclem): another seed? For now Cranly-Partterson rotation with golden ratio. */
noise.x = fract(noise.x + 0.61803398875);
float lod, isect_mul;
@@ -172,7 +172,7 @@ void dof_gather_accumulator(float base_radius,
}
#ifdef DOF_FOREGROUND_PASS /* Reduce issue with closer foreground over distant foreground. */
- /* TODO(fclem) this seems to not be completely correct as the issue remains. */
+ /* TODO(@fclem): This seems to not be completely correct as the issue remains. */
float ring_area = (sqr(float(ring) + 0.5 + coc_radius_error) -
sqr(float(ring) - 0.5 + coc_radius_error)) *
sqr(base_radius * unit_sample_radius);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl
index e5b68637563..e288e1a55ea 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl
@@ -66,7 +66,7 @@ float dof_hdr_color_weight(vec4 color)
{
/* From UE4. Very fast "luma" weighting. */
float luma = (color.g * 2.0) + (color.r + color.b);
- /* TODO(fclem) Pass correct exposure. */
+ /* TODO(@fclem): Pass correct exposure. */
const float exposure = 1.0;
return 1.0 / (luma * exposure + 4.0);
}
@@ -92,7 +92,7 @@ vec4 dof_downsample_bilateral_coc_weights(vec4 cocs)
{
float chosen_coc = dof_coc_select(cocs);
- const float scale = 4.0; /* TODO(fclem) revisit. */
+ const float scale = 4.0; /* TODO(@fclem): revisit. */
/* NOTE: The difference between the cocs should be inside a abs() function,
* but we follow UE4 implementation to improve how dithered transparency looks (see slide 19). */
return saturate(1.0 - (chosen_coc - cocs) * scale);
@@ -373,7 +373,7 @@ void dof_gather_accumulate_sample_pair(DofGatherData pair_data[2],
#if 0
const float mirroring_threshold = -layer_threshold - layer_offset;
- /* TODO(fclem) Promote to parameter? dither with Noise? */
+ /* TODO(@fclem): Promote to parameter? dither with Noise? */
const float mirroring_min_distance = 15.0;
if (pair_data[0].coc < mirroring_threshold &&
(pair_data[1].coc - mirroring_min_distance) > pair_data[0].coc) {
@@ -487,7 +487,8 @@ void dof_gather_accumulate_sample_ring(DofGatherData ring_data,
}
}
-/* FIXME(fclem) Seems to be wrong since it needs ringcount+1 as input for slightfocus gather. */
+/* FIXME(@fclem): Seems to be wrong since it needs `ringcount + 1` as input for slightfocus gather.
+ */
int dof_gather_total_sample_count(const int ring_count, const int ring_density)
{
return (ring_count * ring_count - ring_count) * ring_density + 1;
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
index f349806d37e..59564890d7e 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
@@ -25,7 +25,8 @@ flat out float spritesize;
/* Load 4 Circle of confusion values. texel_co is centered around the 4 taps. */
vec4 fetch_cocs(vec2 texel_co)
{
- /* TODO(fclem) The textureGather(sampler, co, comp) variant isn't here on some implementations.
+ /* TODO(@fclem): The `textureGather(sampler, co, comp)` variant isn't here on some
+ * implementations.
*/
#if 0 // GPU_ARB_texture_gather
vec2 uvs = texel_co / vec2(textureSize(cocBuffer, 0));
diff --git a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
index 70f1e9f1e66..85f8a12aa88 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
@@ -45,7 +45,7 @@ vec3 view_position_derivative_from_depth(vec2 uvs, vec2 ofs, vec3 vP, float dept
}
}
-/* TODO(fclem) port to a common place for other effects to use. */
+/* TODO(@fclem): port to a common place for other effects to use. */
bool reconstruct_view_position_and_normal_from_depth(vec2 uvs, out vec3 vP, out vec3 vNg)
{
vec2 texel_size = vec2(abs(dFdx(uvs.x)), abs(dFdy(uvs.y)));
diff --git a/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl
index 2f1efd588f7..f4ff28eaee4 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl
@@ -31,7 +31,7 @@ void main()
{
vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
/* Decorrelate from AA. */
- /* TODO(fclem) we should use a more general approach for more random number dimensions. */
+ /* TODO(@fclem): we should use a more general approach for more random number dimensions. */
vec2 random_px = floor(fract(rand.xy * 2.2074408460575947536) * 1.99999) - 0.5;
rand.xy = fract(rand.xy * 3.2471795724474602596);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
index ee48c468630..ba90f5ae531 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
@@ -212,7 +212,7 @@ vec3 view_position_derivative_from_depth(vec2 uvs, vec2 ofs, vec3 vP, float dept
}
}
-/* TODO(fclem) port to a common place for other effects to use. */
+/* TODO(@fclem): port to a common place for other effects to use. */
bool reconstruct_view_position_and_normal_from_depth(vec2 uvs, out vec3 vP, out vec3 vNg)
{
vec2 texel_size = vec2(abs(dFdx(uvs.x)), abs(dFdy(uvs.y)));
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
index 8aba1090b58..5a79dfc2663 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
@@ -472,7 +472,7 @@ GPENCIL_ViewLayerData *GPENCIL_view_layer_data_ensure(void)
GPENCIL_ViewLayerData **vldata = (GPENCIL_ViewLayerData **)DRW_view_layer_engine_data_ensure(
&draw_engine_gpencil_type, gpencil_view_layer_data_free);
- /* NOTE(fclem) Putting this stuff in viewlayer means it is shared by all viewports.
+ /* NOTE(&fclem): Putting this stuff in viewlayer means it is shared by all viewports.
* For now it is ok, but in the future, it could become a problem if we implement
* the caching system. */
if (*vldata == NULL) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 9bc340a2786..dfa0d350485 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -788,7 +788,7 @@ static void gpencil_draw_mask(GPENCIL_Data *vedata, GPENCIL_tObject *ob, GPENCIL
const float clear_col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
float clear_depth = ob->is_drawmode3d ? 1.0f : 0.0f;
bool inverted = false;
- /* OPTI(fclem) we could optimize by only clearing if the new mask_bits does not contain all
+ /* OPTI(@fclem): we could optimize by only clearing if the new mask_bits does not contain all
* the masks already rendered in the buffer, and drawing only the layers not already drawn. */
bool cleared = false;
diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh
index b56f3062901..cc85f1e098f 100644
--- a/source/blender/draw/engines/image/image_drawing_mode.hh
+++ b/source/blender/draw/engines/image/image_drawing_mode.hh
@@ -227,7 +227,7 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
IMAGE_InstanceData &instance_data) const
{
while (iterator.get_next_change() == ePartialUpdateIterResult::ChangeAvailable) {
- /* Quick exit when tile_buffer isn't availble. */
+ /* Quick exit when tile_buffer isn't available. */
if (iterator.tile_data.tile_buffer == nullptr) {
continue;
}
@@ -247,8 +247,7 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
GPUTexture *texture = info.texture;
const float texture_width = GPU_texture_width(texture);
const float texture_height = GPU_texture_height(texture);
- // TODO
- // early bound check.
+ /* TODO: early bound check. */
ImageTileWrapper tile_accessor(iterator.tile_data.tile);
float tile_offset_x = static_cast<float>(tile_accessor.get_tile_x_offset());
float tile_offset_y = static_cast<float>(tile_accessor.get_tile_y_offset());
@@ -274,9 +273,9 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
if (!region_overlap) {
continue;
}
- // convert the overlapping region to texel space and to ss_pixel space...
- // TODO: first convert to ss_pixel space as integer based. and from there go back to texel
- // space. But perhaps this isn't needed and we could use an extraction offset somehow.
+ /* Convert the overlapping region to texel space and to ss_pixel space...
+ * TODO: first convert to ss_pixel space as integer based. and from there go back to texel
+ * space. But perhaps this isn't needed and we could use an extraction offset somehow. */
rcti gpu_texture_region_to_update;
BLI_rcti_init(
&gpu_texture_region_to_update,
@@ -297,8 +296,8 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
ceil((changed_overlapping_region_in_uv_space.ymin - tile_offset_y) * tile_height),
ceil((changed_overlapping_region_in_uv_space.ymax - tile_offset_y) * tile_height));
- // Create an image buffer with a size
- // extract and scale into an imbuf
+ /* Create an image buffer with a size.
+ * Extract and scale into an imbuf. */
const int texture_region_width = BLI_rcti_size_x(&gpu_texture_region_to_update);
const int texture_region_height = BLI_rcti_size_y(&gpu_texture_region_to_update);
@@ -477,18 +476,18 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
instance_data->partial_update.ensure_image(image);
instance_data->clear_dirty_flag();
- // Step: Find out which screen space textures are needed to draw on the screen. Remove the
- // screen space textures that aren't needed.
+ /* Step: Find out which screen space textures are needed to draw on the screen. Remove the
+ * screen space textures that aren't needed. */
const ARegion *region = draw_ctx->region;
method.update_screen_space_bounds(region);
method.update_region_uv_bounds(region);
method.update_screen_uv_bounds();
- // Step: Update the GPU textures based on the changes in the image.
+ /* Step: Update the GPU textures based on the changes in the image. */
instance_data->update_gpu_texture_allocations();
update_textures(*instance_data, image, iuser);
- // Step: Add the GPU textures to the shgroup.
+ /* Step: Add the GPU textures to the shgroup. */
instance_data->update_batches();
add_depth_shgroups(*instance_data, image, iuser);
add_shgroups(instance_data);
diff --git a/source/blender/draw/engines/image/image_texture_info.hh b/source/blender/draw/engines/image/image_texture_info.hh
index 5cf9016a8c8..8c3b7494831 100644
--- a/source/blender/draw/engines/image/image_texture_info.hh
+++ b/source/blender/draw/engines/image/image_texture_info.hh
@@ -50,9 +50,9 @@ struct TextureInfo {
rctf clipping_uv_bounds;
/**
- * \brief Batch to draw the associated texton the screen.
+ * \brief Batch to draw the associated text on the screen.
*
- * contans a VBO with `pos` and 'uv'.
+ * Contains a VBO with `pos` and `uv`.
* `pos` (2xF32) is relative to the origin of the space.
* `uv` (2xF32) reflect the uv bounds.
*/
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index 4029f1237e8..ccf8f9e0c36 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -191,20 +191,17 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_sphere(false);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->solid.point_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_point_get());
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_state_disable(grp, DRW_STATE_WRITE_DEPTH);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", wire_alpha * 0.4f);
cb->transp.point_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_point_get());
sh = OVERLAY_shader_armature_shape(false);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->solid.custom_fill = grp;
cb->solid.box_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_box_get());
@@ -213,7 +210,6 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_state_disable(grp, DRW_STATE_WRITE_DEPTH);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", wire_alpha * 0.6f);
cb->transp.custom_fill = grp;
cb->transp.box_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_box_get());
@@ -335,7 +331,6 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_envelope(false);
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_BACK);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "isDistance", false);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->solid.envelope_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_solid_get());
@@ -371,7 +366,6 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_envelope(false);
grp = DRW_shgroup_create(sh, armature_transp_ps);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
DRW_shgroup_uniform_bool_copy(grp, "isDistance", true);
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);
@@ -2084,7 +2078,9 @@ static void draw_armature_edit(ArmatureDrawContext *ctx)
boneflag &= ~BONE_DRAW_LOCKED_WEIGHT;
- draw_bone_relations(ctx, eBone, NULL, arm, boneflag, constflag);
+ if (!is_select) {
+ draw_bone_relations(ctx, eBone, NULL, arm, boneflag, constflag);
+ }
if (arm->drawtype == ARM_ENVELOPE) {
draw_bone_update_disp_matrix_default(eBone, NULL);
@@ -2107,12 +2103,14 @@ static void draw_armature_edit(ArmatureDrawContext *ctx)
draw_bone_octahedral(ctx, eBone, NULL, arm, boneflag, constflag, select_id);
}
- if (show_text && (arm->flag & ARM_DRAWNAMES)) {
- draw_bone_name(ctx, eBone, NULL, arm, boneflag);
- }
+ if (!is_select) {
+ if (show_text && (arm->flag & ARM_DRAWNAMES)) {
+ draw_bone_name(ctx, eBone, NULL, arm, boneflag);
+ }
- if (arm->flag & ARM_DRAWAXES) {
- draw_axes(ctx, eBone, NULL, arm);
+ if (arm->flag & ARM_DRAWAXES) {
+ draw_axes(ctx, eBone, NULL, arm);
+ }
}
}
}
@@ -2221,7 +2219,9 @@ static void draw_armature_pose(ArmatureDrawContext *ctx)
boneflag &= ~BONE_DRAW_LOCKED_WEIGHT;
}
- draw_bone_relations(ctx, NULL, pchan, arm, boneflag, constflag);
+ if (!is_pose_select) {
+ draw_bone_relations(ctx, NULL, pchan, arm, boneflag, constflag);
+ }
if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) {
draw_bone_update_disp_matrix_custom(pchan);
@@ -2248,16 +2248,19 @@ static void draw_armature_pose(ArmatureDrawContext *ctx)
draw_bone_octahedral(ctx, NULL, pchan, arm, boneflag, constflag, select_id);
}
- if (draw_dofs) {
- draw_bone_degrees_of_freedom(ctx, pchan);
- }
+ /* These aren't included in the selection. */
+ if (!is_pose_select) {
+ if (draw_dofs) {
+ draw_bone_degrees_of_freedom(ctx, pchan);
+ }
- if (show_text && (arm->flag & ARM_DRAWNAMES)) {
- draw_bone_name(ctx, NULL, pchan, arm, boneflag);
- }
+ if (show_text && (arm->flag & ARM_DRAWNAMES)) {
+ draw_bone_name(ctx, NULL, pchan, arm, boneflag);
+ }
- if (arm->flag & ARM_DRAWAXES) {
- draw_axes(ctx, NULL, pchan, arm);
+ if (arm->flag & ARM_DRAWAXES) {
+ draw_axes(ctx, NULL, pchan, arm);
+ }
}
}
}
@@ -2365,9 +2368,6 @@ static bool POSE_is_driven_by_active_armature(Object *ob)
if (ob_arm) {
const DRWContextState *draw_ctx = DRW_context_state_get();
bool is_active = OVERLAY_armature_is_pose_mode(ob_arm, draw_ctx);
- if (!is_active && ob_arm->proxy_from) {
- is_active = OVERLAY_armature_is_pose_mode(ob_arm->proxy_from, draw_ctx);
- }
return is_active;
}
diff --git a/source/blender/draw/engines/overlay/overlay_fade.c b/source/blender/draw/engines/overlay/overlay_fade.c
index 0971021f1c0..557a8976ff7 100644
--- a/source/blender/draw/engines/overlay/overlay_fade.c
+++ b/source/blender/draw/engines/overlay/overlay_fade.c
@@ -43,7 +43,6 @@ void OVERLAY_fade_cache_init(OVERLAY_Data *vedata)
GPUShader *sh = OVERLAY_shader_uniform_color();
pd->fade_grp[i] = DRW_shgroup_create(sh, psl->fade_ps[i]);
- DRW_shgroup_uniform_block(pd->fade_grp[i], "globalsBlock", G_draw.block_ubo);
const DRWContextState *draw_ctx = DRW_context_state_get();
float color[4];
diff --git a/source/blender/draw/engines/overlay/overlay_volume.c b/source/blender/draw/engines/overlay/overlay_volume.c
index ad0ccf1c7c4..b13351984a3 100644
--- a/source/blender/draw/engines/overlay/overlay_volume.c
+++ b/source/blender/draw/engines/overlay/overlay_volume.c
@@ -37,7 +37,6 @@ void OVERLAY_volume_cache_init(OVERLAY_Data *vedata)
GPUShader *sh = OVERLAY_shader_depth_only();
DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->volume_ps);
pd->volume_selection_surface_grp = grp;
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
else {
psl->volume_ps = NULL;
diff --git a/source/blender/draw/engines/workbench/shaders/infos/workbench_effect_cavity_info.hh b/source/blender/draw/engines/workbench/shaders/infos/workbench_effect_cavity_info.hh
index 60d79ed50d9..29468d6002a 100644
--- a/source/blender/draw/engines/workbench/shaders/infos/workbench_effect_cavity_info.hh
+++ b/source/blender/draw/engines/workbench/shaders/infos/workbench_effect_cavity_info.hh
@@ -3,11 +3,7 @@
GPU_SHADER_CREATE_INFO(workbench_effect_cavity_common)
.fragment_out(0, Type::VEC4, "fragColor")
- .sampler(0, ImageType::DEPTH_2D, "depthBuffer")
- .sampler(1, ImageType::FLOAT_2D, "normalBuffer")
- .sampler(2, ImageType::UINT_2D, "objectIdBuffer")
- .sampler(3, ImageType::FLOAT_2D, "cavityJitter")
- .uniform_buf(3, "vec4", "samples_coords[512]")
+ .sampler(0, ImageType::FLOAT_2D, "normalBuffer")
.uniform_buf(4, "WorldData", "world_data", Frequency::PASS)
.typedef_source("workbench_shader_shared.h")
.fragment_source("workbench_effect_cavity_frag.glsl")
@@ -17,15 +13,23 @@ GPU_SHADER_CREATE_INFO(workbench_effect_cavity_common)
GPU_SHADER_CREATE_INFO(workbench_effect_cavity)
.do_static_compilation(true)
.define("USE_CAVITY")
+ .uniform_buf(3, "vec4", "samples_coords[512]")
+ .sampler(1, ImageType::DEPTH_2D, "depthBuffer")
+ .sampler(2, ImageType::FLOAT_2D, "cavityJitter")
.additional_info("workbench_effect_cavity_common");
GPU_SHADER_CREATE_INFO(workbench_effect_curvature)
.do_static_compilation(true)
.define("USE_CURVATURE")
+ .sampler(1, ImageType::UINT_2D, "objectIdBuffer")
.additional_info("workbench_effect_cavity_common");
GPU_SHADER_CREATE_INFO(workbench_effect_cavity_curvature)
.do_static_compilation(true)
.define("USE_CAVITY")
.define("USE_CURVATURE")
+ .uniform_buf(3, "vec4", "samples_coords[512]")
+ .sampler(1, ImageType::DEPTH_2D, "depthBuffer")
+ .sampler(2, ImageType::FLOAT_2D, "cavityJitter")
+ .sampler(3, ImageType::UINT_2D, "objectIdBuffer")
.additional_info("workbench_effect_cavity_common");
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
index ad83d6f39e5..880f17b0c9d 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
@@ -5,6 +5,8 @@
/* From The Alchemy screen-space ambient obscurance algorithm
* http://graphics.cs.williams.edu/papers/AlchemyHPG11/VV11AlchemyAO.pdf */
+#ifdef USE_CAVITY
+
void cavity_compute(vec2 screenco,
sampler2D depthBuffer,
sampler2D normalBuffer,
@@ -90,3 +92,5 @@ void cavity_compute(vec2 screenco,
cavities = clamp(cavities * world_data.cavity_valley_factor, 0.0, 1.0);
edges = edges * world_data.cavity_ridge_factor;
}
+
+#endif /* USE_CAVITY */
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
index 18a093275c5..a6f7a1f522a 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
@@ -1,4 +1,8 @@
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
+
+#ifdef USE_CURVATURE
+
float curvature_soft_clamp(float curvature, float control)
{
if (curvature < 0.5 / control) {
@@ -43,3 +47,5 @@ void curvature_compute(vec2 uv,
curvature = 2.0 * curvature_soft_clamp(normal_diff, world_data.curvature_ridge);
}
}
+
+#endif /* USE_CURVATURE */
diff --git a/source/blender/draw/engines/workbench/workbench_effect_cavity.c b/source/blender/draw/engines/workbench/workbench_effect_cavity.c
index 04ff2077443..e58c88c5dcc 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_cavity.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_cavity.c
@@ -164,10 +164,10 @@ void workbench_cavity_cache_init(WORKBENCH_Data *data)
grp = DRW_shgroup_create(sh, psl->cavity_ps);
DRW_shgroup_uniform_texture(grp, "normalBuffer", wpd->normal_buffer_tx);
- DRW_shgroup_uniform_block(grp, "samples_coords", wpd->vldata->cavity_sample_ubo);
DRW_shgroup_uniform_block(grp, "world_data", wpd->world_ubo);
if (SSAO_ENABLED(wpd)) {
+ DRW_shgroup_uniform_block(grp, "samples_coords", wpd->vldata->cavity_sample_ubo);
DRW_shgroup_uniform_texture(grp, "depthBuffer", dtxl->depth);
DRW_shgroup_uniform_texture(grp, "cavityJitter", wpd->vldata->cavity_jitter_tx);
}
diff --git a/source/blender/draw/engines/workbench/workbench_shader_shared.h b/source/blender/draw/engines/workbench/workbench_shader_shared.h
index 0bfd5957834..c63760a634d 100644
--- a/source/blender/draw/engines/workbench/workbench_shader_shared.h
+++ b/source/blender/draw/engines/workbench/workbench_shader_shared.h
@@ -1,6 +1,6 @@
#ifndef GPU_SHADER
-# include "gpu_shader_shared_utils.h"
+# include "GPU_shader_shared_utils.h"
#endif
#define WORKBENCH_SHADER_SHARED_H
diff --git a/source/blender/draw/intern/DRW_gpu_wrapper.hh b/source/blender/draw/intern/DRW_gpu_wrapper.hh
index af262272577..d4491223c10 100644
--- a/source/blender/draw/intern/DRW_gpu_wrapper.hh
+++ b/source/blender/draw/intern/DRW_gpu_wrapper.hh
@@ -286,28 +286,32 @@ template<
/** The number of values that can be stored in this uniform buffer. */
int64_t len
/** True if the buffer only resides on GPU memory and cannot be accessed. */
- /* TODO(fclem): Currently unsupported. */
+ /* TODO(@fclem): Currently unsupported. */
/* bool device_only = false */>
class UniformArrayBuffer : public detail::UniformCommon<T, len, false> {
public:
UniformArrayBuffer()
{
- /* TODO(fclem) We should map memory instead. */
+ /* TODO(@fclem): We should map memory instead. */
this->data_ = (T *)MEM_mallocN_aligned(len * sizeof(T), 16, this->name_);
}
+ ~UniformArrayBuffer()
+ {
+ MEM_freeN(this->data_);
+ }
};
template<
/** Type of the values stored in this uniform buffer. */
typename T
/** True if the buffer only resides on GPU memory and cannot be accessed. */
- /* TODO(fclem): Currently unsupported. */
+ /* TODO(@fclem): Currently unsupported. */
/* bool device_only = false */>
class UniformBuffer : public T, public detail::UniformCommon<T, 1, false> {
public:
UniformBuffer()
{
- /* TODO(fclem) How could we map this? */
+ /* TODO(@fclem): How could we map this? */
this->data_ = static_cast<T *>(this);
}
@@ -641,7 +645,7 @@ class Texture : NonCopyable {
bool cubemap = false)
{
- /* TODO(fclem) In the future, we need to check if mip_count did not change.
+ /* TODO(@fclem): In the future, we need to check if mip_count did not change.
* For now it's ok as we always define all MIP level. */
if (tx_) {
int3 size = this->size();
@@ -653,7 +657,7 @@ class Texture : NonCopyable {
if (tx_ == nullptr) {
tx_ = create(w, h, d, mips, format, data, layered, cubemap);
if (mips > 1) {
- /* TODO(fclem) Remove once we have immutable storage or when mips are
+ /* TODO(@fclem): Remove once we have immutable storage or when mips are
* generated on creation. */
GPU_texture_generate_mipmap(tx_);
}
@@ -674,20 +678,20 @@ class Texture : NonCopyable {
if (h == 0) {
return GPU_texture_create_1d(name_, w, mips, format, data);
}
- else if (d == 0) {
+ else if (cubemap) {
if (layered) {
- return GPU_texture_create_1d_array(name_, w, h, mips, format, data);
+ return GPU_texture_create_cube_array(name_, w, d, mips, format, data);
}
else {
- return GPU_texture_create_2d(name_, w, h, mips, format, data);
+ return GPU_texture_create_cube(name_, w, mips, format, data);
}
}
- else if (cubemap) {
+ else if (d == 0) {
if (layered) {
- return GPU_texture_create_cube_array(name_, w, d, mips, format, data);
+ return GPU_texture_create_1d_array(name_, w, h, mips, format, data);
}
else {
- return GPU_texture_create_cube(name_, w, mips, format, data);
+ return GPU_texture_create_2d(name_, w, h, mips, format, data);
}
}
else {
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 8c56d21746d..d531d8ad9f8 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -66,6 +66,15 @@
extern "C" {
#endif
+/* Uncomment to track unused resource bindings. */
+// #define DRW_UNUSED_RESOURCE_TRACKING
+
+#ifdef DRW_UNUSED_RESOURCE_TRACKING
+# define DRW_DEBUG_FILE_LINE_ARGS , const char *file, int line
+#else
+# define DRW_DEBUG_FILE_LINE_ARGS
+#endif
+
struct GPUBatch;
struct GPUMaterial;
struct GPUShader;
@@ -468,6 +477,10 @@ void DRW_shgroup_call_compute(DRWShadingGroup *shgroup,
int groups_x_len,
int groups_y_len,
int groups_z_len);
+/**
+ * \warning this keeps the ref to groups_ref until it actually dispatch.
+ */
+void DRW_shgroup_call_compute_ref(DRWShadingGroup *shgroup, int groups_ref[3]);
void DRW_shgroup_call_procedural_points(DRWShadingGroup *sh, Object *ob, uint point_count);
void DRW_shgroup_call_procedural_lines(DRWShadingGroup *sh, Object *ob, uint line_count);
void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *sh, Object *ob, uint tri_count);
@@ -534,6 +547,11 @@ void DRW_shgroup_stencil_set(DRWShadingGroup *shgroup,
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask);
/**
+ * Issue a barrier command.
+ */
+void DRW_shgroup_barrier(DRWShadingGroup *shgroup, eGPUBarrier type);
+
+/**
* Issue a clear command.
*/
void DRW_shgroup_clear_framebuffer(DRWShadingGroup *shgroup,
@@ -559,12 +577,12 @@ void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup,
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup,
const char *name,
struct GPUTexture **tex);
-void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
- const char *name,
- const struct GPUUniformBuf *ubo);
-void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup,
- const char *name,
- struct GPUUniformBuf **ubo);
+void DRW_shgroup_uniform_block_ex(DRWShadingGroup *shgroup,
+ const char *name,
+ const struct GPUUniformBuf *ubo DRW_DEBUG_FILE_LINE_ARGS);
+void DRW_shgroup_uniform_block_ref_ex(DRWShadingGroup *shgroup,
+ const char *name,
+ struct GPUUniformBuf **ubo DRW_DEBUG_FILE_LINE_ARGS);
void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup,
const char *name,
const float *value,
@@ -624,9 +642,32 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
const char *name,
const float (*value)[4],
int arraysize);
-void DRW_shgroup_vertex_buffer(DRWShadingGroup *shgroup,
- const char *name,
- struct GPUVertBuf *vertex_buffer);
+void DRW_shgroup_vertex_buffer_ex(DRWShadingGroup *shgroup,
+ const char *name,
+ struct GPUVertBuf *vertex_buffer DRW_DEBUG_FILE_LINE_ARGS);
+void DRW_shgroup_vertex_buffer_ref_ex(DRWShadingGroup *shgroup,
+ const char *name,
+ struct GPUVertBuf **vertex_buffer DRW_DEBUG_FILE_LINE_ARGS);
+
+#ifdef DRW_UNUSED_RESOURCE_TRACKING
+# define DRW_shgroup_vertex_buffer(shgroup, name, vert) \
+ DRW_shgroup_vertex_buffer_ex(shgroup, name, vert, __FILE__, __LINE__)
+# define DRW_shgroup_vertex_buffer_ref(shgroup, name, vert) \
+ DRW_shgroup_vertex_buffer_ref_ex(shgroup, name, vert, __FILE__, __LINE__)
+# define DRW_shgroup_uniform_block(shgroup, name, ubo) \
+ DRW_shgroup_uniform_block_ex(shgroup, name, ubo, __FILE__, __LINE__)
+# define DRW_shgroup_uniform_block_ref(shgroup, name, ubo) \
+ DRW_shgroup_uniform_block_ref_ex(shgroup, name, ubo, __FILE__, __LINE__)
+#else
+# define DRW_shgroup_vertex_buffer(shgroup, name, vert) \
+ DRW_shgroup_vertex_buffer_ex(shgroup, name, vert)
+# define DRW_shgroup_vertex_buffer_ref(shgroup, name, vert) \
+ DRW_shgroup_vertex_buffer_ref_ex(shgroup, name, vert)
+# define DRW_shgroup_uniform_block(shgroup, name, ubo) \
+ DRW_shgroup_uniform_block_ex(shgroup, name, ubo)
+# define DRW_shgroup_uniform_block_ref(shgroup, name, ubo) \
+ DRW_shgroup_uniform_block_ref_ex(shgroup, name, ubo)
+#endif
bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup);
diff --git a/source/blender/draw/intern/draw_cache_impl_hair.cc b/source/blender/draw/intern/draw_cache_impl_hair.cc
index d236f0c2f59..cdc06b121b0 100644
--- a/source/blender/draw/intern/draw_cache_impl_hair.cc
+++ b/source/blender/draw/intern/draw_cache_impl_hair.cc
@@ -29,7 +29,10 @@
#include "BLI_listbase.h"
#include "BLI_math_base.h"
+#include "BLI_math_vec_types.hh"
#include "BLI_math_vector.h"
+#include "BLI_math_vector.hh"
+#include "BLI_span.hh"
#include "BLI_utildefines.h"
#include "DNA_hair_types.h"
@@ -44,6 +47,10 @@
#include "draw_cache_impl.h" /* own include */
#include "draw_hair_private.h" /* own include */
+using blender::float3;
+using blender::IndexRange;
+using blender::Span;
+
static void hair_batch_cache_clear(Hair *hair);
/* ---------------------------------------------------------------------- */
@@ -131,17 +138,9 @@ static void ensure_seg_pt_count(Hair *hair, ParticleHairCache *hair_cache)
return;
}
- hair_cache->strands_len = 0;
- hair_cache->elems_len = 0;
- hair_cache->point_len = 0;
-
- HairCurve *curve = hair->curves;
- int num_curves = hair->totcurve;
- for (int i = 0; i < num_curves; i++, curve++) {
- hair_cache->strands_len++;
- hair_cache->elems_len += curve->numpoints + 1;
- hair_cache->point_len += curve->numpoints;
- }
+ hair_cache->strands_len = hair->geometry.curve_size;
+ hair_cache->elems_len = hair->geometry.point_size + hair->geometry.curve_size;
+ hair_cache->point_len = hair->geometry.point_size;
}
static void hair_batch_cache_fill_segments_proc_pos(Hair *hair,
@@ -149,30 +148,36 @@ static void hair_batch_cache_fill_segments_proc_pos(Hair *hair,
GPUVertBufRaw *length_step)
{
/* TODO: use hair radius layer if available. */
- HairCurve *curve = hair->curves;
- int num_curves = hair->totcurve;
- for (int i = 0; i < num_curves; i++, curve++) {
- float(*curve_co)[3] = hair->co + curve->firstpoint;
+ const int curve_size = hair->geometry.curve_size;
+ Span<int> offsets{hair->geometry.offsets, hair->geometry.curve_size + 1};
+
+ Span<float3> positions{(float3 *)hair->geometry.position, hair->geometry.point_size};
+
+ for (const int i : IndexRange(curve_size)) {
+ const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
+
+ Span<float3> spline_positions = positions.slice(curve_range);
float total_len = 0.0f;
- float *co_prev = nullptr, *seg_data_first;
- for (int j = 0; j < curve->numpoints; j++) {
+ float *seg_data_first;
+ for (const int i_spline : spline_positions.index_range()) {
float *seg_data = (float *)GPU_vertbuf_raw_step(attr_step);
- copy_v3_v3(seg_data, curve_co[j]);
- if (co_prev) {
- total_len += len_v3v3(co_prev, curve_co[j]);
+ copy_v3_v3(seg_data, spline_positions[i_spline]);
+ if (i_spline == 0) {
+ seg_data_first = seg_data;
}
else {
- seg_data_first = seg_data;
+ total_len += blender::math::distance(spline_positions[i_spline - 1],
+ spline_positions[i_spline]);
}
seg_data[3] = total_len;
- co_prev = curve_co[j];
}
/* Assign length value. */
*(float *)GPU_vertbuf_raw_step(length_step) = total_len;
if (total_len > 0.0f) {
/* Divide by total length to have a [0-1] number. */
- for (int j = 0; j < curve->numpoints; j++, seg_data_first += 4) {
+ for ([[maybe_unused]] const int i_spline : spline_positions.index_range()) {
seg_data_first[3] /= total_len;
+ seg_data_first += 4;
}
}
}
@@ -226,11 +231,14 @@ static void hair_batch_cache_fill_strands_data(Hair *hair,
GPUVertBufRaw *data_step,
GPUVertBufRaw *seg_step)
{
- HairCurve *curve = hair->curves;
- int num_curves = hair->totcurve;
- for (int i = 0; i < num_curves; i++, curve++) {
- *(uint *)GPU_vertbuf_raw_step(data_step) = curve->firstpoint;
- *(ushort *)GPU_vertbuf_raw_step(seg_step) = curve->numpoints - 1;
+ const int curve_size = hair->geometry.curve_size;
+ Span<int> offsets{hair->geometry.offsets, hair->geometry.curve_size + 1};
+
+ for (const int i : IndexRange(curve_size)) {
+ const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
+
+ *(uint *)GPU_vertbuf_raw_step(data_step) = curve_range.start();
+ *(ushort *)GPU_vertbuf_raw_step(seg_step) = curve_range.size() - 1;
}
}
@@ -289,10 +297,11 @@ static void hair_batch_cache_fill_segments_indices(Hair *hair,
const int res,
GPUIndexBufBuilder *elb)
{
- HairCurve *curve = hair->curves;
- int num_curves = hair->totcurve;
+ const int curve_size = hair->geometry.curve_size;
+
uint curr_point = 0;
- for (int i = 0; i < num_curves; i++, curve++) {
+
+ for ([[maybe_unused]] const int i : IndexRange(curve_size)) {
for (int k = 0; k < res; k++) {
GPU_indexbuf_add_generic_vert(elb, curr_point++);
}
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index f57921d058c..e7e0e97499f 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -505,8 +505,9 @@ static bool custom_data_match_attribute(const CustomData *custom_data,
int *r_layer_index,
int *r_type)
{
- const int possible_attribute_types[6] = {
+ const int possible_attribute_types[7] = {
CD_PROP_BOOL,
+ CD_PROP_INT8,
CD_PROP_INT32,
CD_PROP_FLOAT,
CD_PROP_FLOAT2,
@@ -655,6 +656,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
break;
}
case CD_PROP_BOOL:
+ case CD_PROP_INT8:
case CD_PROP_INT32:
case CD_PROP_FLOAT:
case CD_PROP_FLOAT2:
diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
index a24a3a5a3a7..4a8670a9ee2 100644
--- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc
+++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
@@ -999,7 +999,7 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache,
cache->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
- // Build patch coordinates for all the face dots
+ /* Build patch coordinates for all the face dots. */
cache->fdots_patch_coords = gpu_vertbuf_create_from_format(get_blender_patch_coords_format(),
mesh_eval->totpoly);
CompressedPatchCoord *blender_fdots_patch_coords = (CompressedPatchCoord *)GPU_vertbuf_get_data(
@@ -1760,7 +1760,7 @@ static void draw_subdiv_cache_ensure_mat_offsets(DRWSubdivCache *cache,
int *mat_start = static_cast<int *>(MEM_callocN(sizeof(int) * mat_len, "subdiv mat_start"));
int *subdiv_polygon_offset = cache->subdiv_polygon_offset;
- // TODO: parallel_reduce?
+ /* TODO: parallel_reduce? */
for (int i = 0; i < mesh_eval->totpoly; i++) {
const MPoly *mpoly = &mesh_eval->mpoly[i];
const int next_offset = (i == mesh_eval->totpoly - 1) ? number_of_quads :
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index d27eb8be9e0..73fd157426c 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -205,8 +205,10 @@ typedef enum {
/* Compute Commands. */
DRW_CMD_COMPUTE = 8,
+ DRW_CMD_COMPUTE_REF = 9,
/* Other Commands */
+ DRW_CMD_BARRIER = 11,
DRW_CMD_CLEAR = 12,
DRW_CMD_DRWSTATE = 13,
DRW_CMD_STENCIL = 14,
@@ -249,6 +251,14 @@ typedef struct DRWCommandCompute {
int groups_z_len;
} DRWCommandCompute;
+typedef struct DRWCommandComputeRef {
+ int *groups_ref;
+} DRWCommandComputeRef;
+
+typedef struct DRWCommandBarrier {
+ eGPUBarrier type;
+} DRWCommandBarrier;
+
typedef struct DRWCommandDrawProcedural {
GPUBatch *batch;
DRWResourceHandle handle;
@@ -286,6 +296,8 @@ typedef union DRWCommand {
DRWCommandDrawInstanceRange instance_range;
DRWCommandDrawProcedural procedural;
DRWCommandCompute compute;
+ DRWCommandComputeRef compute_ref;
+ DRWCommandBarrier barrier;
DRWCommandSetMutableState state;
DRWCommandSetStencil stencil;
DRWCommandSetSelectID select_id;
@@ -300,7 +312,7 @@ struct DRWCallBuffer {
};
/** Used by #DRWUniform.type */
-/* TODO(jbakker): rename to DRW_RESOURCE/DRWResourceType. */
+/* TODO(@jbakker): rename to DRW_RESOURCE/DRWResourceType. */
typedef enum {
DRW_UNIFORM_INT = 0,
DRW_UNIFORM_INT_COPY,
@@ -314,6 +326,7 @@ typedef enum {
DRW_UNIFORM_BLOCK_REF,
DRW_UNIFORM_TFEEDBACK_TARGET,
DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE,
+ DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE_REF,
/** Per drawcall uniforms/UBO */
DRW_UNIFORM_BLOCK_OBMATS,
DRW_UNIFORM_BLOCK_OBINFOS,
@@ -345,6 +358,11 @@ struct DRWUniform {
GPUUniformBuf *block;
GPUUniformBuf **block_ref;
};
+ /* DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE */
+ union {
+ GPUVertBuf *vertbuf;
+ GPUVertBuf **vertbuf_ref;
+ };
/* DRW_UNIFORM_FLOAT_COPY */
float fvalue[4];
/* DRW_UNIFORM_INT_COPY */
@@ -529,7 +547,7 @@ typedef struct DRWData {
struct GHash *obattrs_ubo_pool;
uint ubo_len;
/** Texture pool to reuse temp texture across engines. */
- /* TODO(fclem) the pool could be shared even between viewports. */
+ /* TODO(@fclem): The pool could be shared even between view-ports. */
struct DRWTexturePool *texture_pool;
/** Per stereo view data. Contains engine data and default framebuffers. */
struct DRWViewData *view_data[2];
@@ -549,7 +567,7 @@ typedef struct DupliKey {
typedef struct DRWManager {
/* TODO: clean up this struct a bit. */
/* Cache generation */
- /* TODO(fclem) Rename to data. */
+ /* TODO(@fclem): Rename to data. */
DRWData *vmempool;
/** Active view data structure for one of the 2 stereo view. Not related to DRWView. */
struct DRWViewData *view_data_active;
@@ -572,7 +590,7 @@ typedef struct DRWManager {
struct ID *dupli_origin_data;
/** Hash-map: #DupliKey -> void pointer for each enabled engine. */
struct GHash *dupli_ghash;
- /** TODO(fclem): try to remove usage of this. */
+ /** TODO(@fclem): try to remove usage of this. */
DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE];
/* Dupli data for the current dupli for each enabled engine. */
void **dupli_datas;
@@ -615,7 +633,7 @@ typedef struct DRWManager {
DRWView *view_active;
DRWView *view_previous;
uint primary_view_ct;
- /** TODO(fclem): Remove this. Only here to support
+ /** TODO(@fclem): Remove this. Only here to support
* shaders without common_view_lib.glsl */
DRWViewUboStorage view_storage_cpy;
@@ -640,7 +658,7 @@ typedef struct DRWManager {
GPUDrawList *draw_list;
struct {
- /* TODO(fclem): optimize: use chunks. */
+ /* TODO(@fclem): optimize: use chunks. */
DRWDebugLine *lines;
DRWDebugSphere *spheres;
} debug;
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index a4d5d6f3c31..3f299e878c4 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -283,19 +283,45 @@ void DRW_shgroup_uniform_image_ref(DRWShadingGroup *shgroup, const char *name, G
drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_IMAGE_REF, tex, 0, 0, 1);
}
-void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
- const char *name,
- const GPUUniformBuf *ubo)
+void DRW_shgroup_uniform_block_ex(DRWShadingGroup *shgroup,
+ const char *name,
+ const GPUUniformBuf *ubo DRW_DEBUG_FILE_LINE_ARGS)
{
BLI_assert(ubo != NULL);
int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
+ if (loc == -1) {
+#ifdef DRW_UNUSED_RESOURCE_TRACKING
+ printf("%s:%d: Unable to locate binding of shader uniform buffer object: %s.\n",
+ file,
+ line,
+ name);
+#else
+ /* TODO(@fclem): Would be good to have, but eevee has too much of this for the moment. */
+ // BLI_assert_msg(0, "Unable to locate binding of shader uniform buffer objects.");
+#endif
+ return;
+ }
drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK, ubo, 0, 0, 1);
}
-void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup, const char *name, GPUUniformBuf **ubo)
+void DRW_shgroup_uniform_block_ref_ex(DRWShadingGroup *shgroup,
+ const char *name,
+ GPUUniformBuf **ubo DRW_DEBUG_FILE_LINE_ARGS)
{
BLI_assert(ubo != NULL);
int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
+ if (loc == -1) {
+#ifdef DRW_UNUSED_RESOURCE_TRACKING
+ printf("%s:%d: Unable to locate binding of shader uniform buffer object: %s.\n",
+ file,
+ line,
+ name);
+#else
+ /* TODO(@fclem): Would be good to have, but eevee has too much of this for the moment. */
+ // BLI_assert_msg(0, "Unable to locate binding of shader uniform buffer objects.");
+#endif
+ return;
+ }
drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK_REF, ubo, 0, 0, 1);
}
@@ -447,19 +473,46 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
}
}
-void DRW_shgroup_vertex_buffer(DRWShadingGroup *shgroup,
- const char *name,
- GPUVertBuf *vertex_buffer)
+void DRW_shgroup_vertex_buffer_ex(DRWShadingGroup *shgroup,
+ const char *name,
+ GPUVertBuf *vertex_buffer DRW_DEBUG_FILE_LINE_ARGS)
{
int location = GPU_shader_get_ssbo(shgroup->shader, name);
if (location == -1) {
+#ifdef DRW_UNUSED_RESOURCE_TRACKING
+ printf("%s:%d: Unable to locate binding of shader storage buffer object: %s.\n",
+ file,
+ line,
+ name);
+#else
BLI_assert_msg(0, "Unable to locate binding of shader storage buffer objects.");
+#endif
return;
}
drw_shgroup_uniform_create_ex(
shgroup, location, DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE, vertex_buffer, 0, 0, 1);
}
+void DRW_shgroup_vertex_buffer_ref_ex(DRWShadingGroup *shgroup,
+ const char *name,
+ GPUVertBuf **vertex_buffer DRW_DEBUG_FILE_LINE_ARGS)
+{
+ int location = GPU_shader_get_ssbo(shgroup->shader, name);
+ if (location == -1) {
+#ifdef DRW_UNUSED_RESOURCE_TRACKING
+ printf("%s:%d: Unable to locate binding of shader storage buffer object: %s.\n",
+ file,
+ line,
+ name);
+#else
+ BLI_assert_msg(0, "Unable to locate binding of shader storage buffer objects.");
+#endif
+ return;
+ }
+ drw_shgroup_uniform_create_ex(
+ shgroup, location, DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE_REF, vertex_buffer, 0, 0, 1);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -730,6 +783,18 @@ static void drw_command_compute(DRWShadingGroup *shgroup,
cmd->groups_z_len = groups_z_len;
}
+static void drw_command_compute_ref(DRWShadingGroup *shgroup, int groups_ref[3])
+{
+ DRWCommandComputeRef *cmd = drw_command_create(shgroup, DRW_CMD_COMPUTE_REF);
+ cmd->groups_ref = groups_ref;
+}
+
+static void drw_command_barrier(DRWShadingGroup *shgroup, eGPUBarrier type)
+{
+ DRWCommandBarrier *cmd = drw_command_create(shgroup, DRW_CMD_BARRIER);
+ cmd->type = type;
+}
+
static void drw_command_draw_procedural(DRWShadingGroup *shgroup,
GPUBatch *batch,
DRWResourceHandle handle,
@@ -816,7 +881,7 @@ void DRW_shgroup_call_ex(DRWShadingGroup *shgroup,
culling->user_data = user_data;
}
if (bypass_culling) {
- /* NOTE this will disable culling for the whole object. */
+ /* NOTE: this will disable culling for the whole object. */
culling->bsphere.radius = -1.0f;
}
}
@@ -855,6 +920,20 @@ void DRW_shgroup_call_compute(DRWShadingGroup *shgroup,
drw_command_compute(shgroup, groups_x_len, groups_y_len, groups_z_len);
}
+void DRW_shgroup_call_compute_ref(DRWShadingGroup *shgroup, int groups_ref[3])
+{
+ BLI_assert(GPU_compute_shader_support());
+
+ drw_command_compute_ref(shgroup, groups_ref);
+}
+
+void DRW_shgroup_barrier(DRWShadingGroup *shgroup, eGPUBarrier type)
+{
+ BLI_assert(GPU_compute_shader_support());
+
+ drw_command_barrier(shgroup, type);
+}
+
static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup,
GPUBatch *geom,
Object *ob,
@@ -1248,7 +1327,7 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
int chunkid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_CHUNK);
int resourceid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_ID);
- /* TODO(fclem) Will take the place of the above after the GPUShaderCreateInfo port. */
+ /* TODO(@fclem): Will take the place of the above after the GPUShaderCreateInfo port. */
if (view_ubo_location == -1) {
view_ubo_location = GPU_shader_get_builtin_block(shader, GPU_UNIFORM_BLOCK_DRW_VIEW);
}
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 2095a8483d6..a579403975f 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -662,8 +662,11 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
*use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
((GPUVertBuf *)uni->pvalue));
break;
+ case DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE_REF:
+ GPU_vertbuf_bind_as_ssbo(*uni->vertbuf_ref, uni->location);
+ break;
case DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE:
- GPU_vertbuf_bind_as_ssbo((GPUVertBuf *)uni->pvalue, uni->location);
+ GPU_vertbuf_bind_as_ssbo(uni->vertbuf, uni->location);
break;
/* Legacy/Fallback support. */
case DRW_UNIFORM_BASE_INSTANCE:
@@ -1049,6 +1052,15 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
cmd->compute.groups_y_len,
cmd->compute.groups_z_len);
break;
+ case DRW_CMD_COMPUTE_REF:
+ GPU_compute_dispatch(shgroup->shader,
+ cmd->compute_ref.groups_ref[0],
+ cmd->compute_ref.groups_ref[1],
+ cmd->compute_ref.groups_ref[2]);
+ break;
+ case DRW_CMD_BARRIER:
+ GPU_memory_barrier(cmd->barrier.type);
+ break;
}
}
diff --git a/source/blender/draw/intern/draw_shader_shared.h b/source/blender/draw/intern/draw_shader_shared.h
index 35350417ca8..fba8f91b2f6 100644
--- a/source/blender/draw/intern/draw_shader_shared.h
+++ b/source/blender/draw/intern/draw_shader_shared.h
@@ -1,6 +1,6 @@
#ifndef GPU_SHADER
-# include "gpu_shader_shared_utils.h"
+# include "GPU_shader_shared_utils.h"
#endif
#define DRW_SHADER_SHARED_H
@@ -23,7 +23,7 @@ struct ViewInfos {
};
BLI_STATIC_ASSERT_ALIGN(ViewInfos, 16)
-/* TODO(fclem) Mass rename. */
+/* TODO(@fclem): Mass rename. */
#define ViewProjectionMatrix drw_view.persmat
#define ViewProjectionMatrixInverse drw_view.persinv
#define ViewMatrix drw_view.viewmat
diff --git a/source/blender/draw/intern/draw_view_data.h b/source/blender/draw/intern/draw_view_data.h
index b37e48c11e8..98ada5a59cb 100644
--- a/source/blender/draw/intern/draw_view_data.h
+++ b/source/blender/draw/intern/draw_view_data.h
@@ -35,7 +35,7 @@ struct DRWRegisteredDrawEngine;
struct DrawEngineType;
struct GPUViewport;
-/* NOTE these structs are only here for reading the actual lists from the engine.
+/* NOTE: these structs are only here for reading the actual lists from the engine.
* The actual length of them is stored in a ViewportEngineData_Info.
* The length of 1 is just here to avoid compiler warning. */
typedef struct FramebufferList {
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc
index b846da3f016..b27633405b9 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc
@@ -99,9 +99,10 @@ static uint gpu_component_size_for_attribute_type(CustomDataType type)
{
switch (type) {
case CD_PROP_BOOL:
+ case CD_PROP_INT8:
case CD_PROP_INT32:
case CD_PROP_FLOAT: {
- /* TODO(kevindietrich) : should be 1 when scalar attributes conversion is handled by us. See
+ /* TODO(@kevindietrich): should be 1 when scalar attributes conversion is handled by us. See
* comment #extract_attr_init. */
return 3;
}
@@ -317,7 +318,7 @@ static void extract_attr_init(const MeshRenderData *mr,
init_vbo_for_attribute(mr, vbo, request, false, static_cast<uint32_t>(mr->loop_len));
- /* TODO(kevindietrich) : float3 is used for scalar attributes as the implicit conversion done by
+ /* TODO(@kevindietrich): float3 is used for scalar attributes as the implicit conversion done by
* OpenGL to vec4 for a scalar `s` will produce a `vec4(s, 0, 0, 1)`. However, following the
* Blender convention, it should be `vec4(s, s, s, 1)`. This could be resolved using a similar
* texture as for volume attribute, so we can control the conversion ourselves. */
@@ -326,6 +327,10 @@ static void extract_attr_init(const MeshRenderData *mr,
extract_attr_generic<bool, float3>(mr, vbo, request);
break;
}
+ case CD_PROP_INT8: {
+ extract_attr_generic<int8_t, float3>(mr, vbo, request);
+ break;
+ }
case CD_PROP_INT32: {
extract_attr_generic<int32_t, float3>(mr, vbo, request);
break;
@@ -378,6 +383,10 @@ static void extract_attr_init_subdiv(const DRWSubdivCache *subdiv_cache,
extract_attr_generic<bool, float3>(mr, src_data, request);
break;
}
+ case CD_PROP_INT8: {
+ extract_attr_generic<int8_t, float3>(mr, src_data, request);
+ break;
+ }
case CD_PROP_INT32: {
extract_attr_generic<int32_t, float3>(mr, src_data, request);
break;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
index 8470a71059f..4185f2f84a2 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
@@ -78,7 +78,7 @@ static void extract_edge_fac_init(const MeshRenderData *mr,
data->edge_loop_count = static_cast<uchar *>(
MEM_callocN(sizeof(uint32_t) * mr->edge_len, __func__));
- /* HACK(fclem) Detecting the need for edge render.
+ /* HACK(@fclem): Detecting the need for edge render.
* We could have a flag in the mesh instead or check the modifier stack. */
const MEdge *med = mr->medge;
for (int e_index = 0; e_index < mr->edge_len; e_index++, med++) {
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
index 5d2ea923658..11f1515275c 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
@@ -270,7 +270,7 @@ static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache
const MVert *coarse_verts = coarse_mesh->mvert;
uint offset = subdiv_cache->num_subdiv_loops;
- /* TODO(kevindietrich) : replace this when compressed normals are supported. */
+ /* TODO(@kevindietrich): replace this when compressed normals are supported. */
struct SubdivPosNorLoop {
float pos[3];
float nor[3];
diff --git a/source/blender/draw/intern/shaders/common_fxaa_lib.glsl b/source/blender/draw/intern/shaders/common_fxaa_lib.glsl
index bf59972fbaa..599d875c500 100644
--- a/source/blender/draw/intern/shaders/common_fxaa_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_fxaa_lib.glsl
@@ -51,7 +51,7 @@
/*============================================================================
FXAA QUALITY - TUNING KNOBS
------------------------------------------------------------------------------
-NOTE the other tuning knobs are now in the shader function inputs!
+NOTE: the other tuning knobs are now in the shader function inputs!
============================================================================*/
#ifndef FXAA_QUALITY__PRESET
/*
diff --git a/source/blender/draw/intern/shaders/common_subdiv_lib.glsl b/source/blender/draw/intern/shaders/common_subdiv_lib.glsl
index 9dd86c35ee4..e6538d80111 100644
--- a/source/blender/draw/intern/shaders/common_subdiv_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_subdiv_lib.glsl
@@ -101,7 +101,7 @@ uint get_index(uint i)
* the format. */
struct PosNorLoop {
float x, y, z;
- /* TODO(kevindietrich) : figure how to compress properly as GLSL does not have char/short types,
+ /* TODO(@kevindietrich): figure how to compress properly as GLSL does not have char/short types,
* bit operations get tricky. */
float nx, ny, nz;
float flag;
diff --git a/source/blender/draw/intern/shaders/draw_hair_refine_info.hh b/source/blender/draw/intern/shaders/draw_hair_refine_info.hh
index b41be7d8605..bdfc26b7dcd 100644
--- a/source/blender/draw/intern/shaders/draw_hair_refine_info.hh
+++ b/source/blender/draw/intern/shaders/draw_hair_refine_info.hh
@@ -25,7 +25,7 @@
GPU_SHADER_CREATE_INFO(draw_hair_refine_compute)
.local_group_size(1, 1)
- .storage_buf(0, Qualifier::WRITE_ONLY, "vec4", "posTime[]")
+ .storage_buf(0, Qualifier::WRITE, "vec4", "posTime[]")
.sampler(0, ImageType::FLOAT_BUFFER, "hairPointBuffer")
.sampler(1, ImageType::UINT_BUFFER, "hairStrandBuffer")
.sampler(2, ImageType::UINT_BUFFER, "hairStrandSegBuffer")
diff --git a/source/blender/draw/intern/shaders/draw_view_info.hh b/source/blender/draw/intern/shaders/draw_view_info.hh
index 0a25059ffed..f9dcf291f95 100644
--- a/source/blender/draw/intern/shaders/draw_view_info.hh
+++ b/source/blender/draw/intern/shaders/draw_view_info.hh
@@ -30,7 +30,7 @@ GPU_SHADER_CREATE_INFO(draw_resource_id_uniform)
/**
* Declare a resource handle that identify a unique object.
- * Requires draw_resource_id[_constant].
+ * Requires draw_resource_id[_uniform].
*/
GPU_SHADER_CREATE_INFO(draw_resource_handle)
.define("resource_handle (drw_resourceChunk * DRW_RESOURCE_CHUNK_LEN + resource_id)")
@@ -83,7 +83,7 @@ GPU_SHADER_CREATE_INFO(draw_hair)
.sampler(15, ImageType::FLOAT_BUFFER, "hairPointBuffer")
.sampler(14, ImageType::UINT_BUFFER, "hairStrandBuffer")
.sampler(13, ImageType::UINT_BUFFER, "hairStrandSegBuffer")
- /* TODO(fclem) Pack thoses into one UBO. */
+ /* TODO(@fclem): Pack these into one UBO. */
.push_constant(Type::INT, "hairStrandsRes")
.push_constant(Type::INT, "hairThicknessRes")
.push_constant(Type::FLOAT, "hairRadRoot")
diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt
index 6fa4d94df3a..0baac40660d 100644
--- a/source/blender/editors/animation/CMakeLists.txt
+++ b/source/blender/editors/animation/CMakeLists.txt
@@ -60,10 +60,6 @@ set(LIB
bf_blenlib
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 2eaa42ee578..5afb9334612 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -3418,7 +3418,7 @@ static void acf_gpd_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale),
/* TODO: just get this from RNA? */
static int acf_gpd_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_GREASEPENCIL;
+ return ICON_OUTLINER_OB_GREASEPENCIL;
}
/* check if some setting exists for this channel */
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index aff5803f037..c8ca27c64a3 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -63,9 +63,5 @@ set(LIB
bf_blenlib
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_armature "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index 02ecfdb4ea6..4a327904ddd 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -581,8 +581,6 @@ static void updateDuplicateLocRotConstraintSettings(Object *ob,
{
/* This code assumes that bRotLimitConstraint and bLocLimitConstraint have the same fields in
* the same memory locations. */
- BLI_assert(sizeof(bLocLimitConstraint) == sizeof(bRotLimitConstraint));
-
bRotLimitConstraint *limit = (bRotLimitConstraint *)curcon->data;
float local_mat[4][4], imat[4][4];
@@ -798,6 +796,13 @@ static void updateDuplicateTransformConstraintSettings(Object *ob,
trans->to_min_rot[i] = temp_vec[i];
}
}
+
+ if (trans->from == TRANS_ROTATION && trans->map[1] == Y) {
+ /* Y Rot to Y Rot: Flip and invert */
+ trans->to_max_rot[1] = -trans->to_min_rot[1];
+ trans->to_min_rot[1] = -temp_vec[1];
+ }
+
break;
}
/* convert back to the settings space */
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index 252cf806e34..aaeac29b7d0 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -27,6 +27,7 @@
struct wmOperatorType;
struct Base;
+struct GPUSelectResult;
struct Object;
struct Scene;
struct bContext;
@@ -323,21 +324,21 @@ struct Bone *ED_armature_pick_bone(struct bContext *C,
struct EditBone *ED_armature_pick_ebone_from_selectbuffer(struct Base **bases,
uint bases_len,
- const uint *buffer,
+ const struct GPUSelectResult *buffer,
short hits,
bool findunsel,
bool do_nearest,
struct Base **r_base);
struct bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(struct Base **bases,
uint bases_len,
- const uint *buffer,
+ const struct GPUSelectResult *buffer,
short hits,
bool findunsel,
bool do_nearest,
struct Base **r_base);
struct Bone *ED_armature_pick_bone_from_selectbuffer(struct Base **bases,
uint bases_len,
- const uint *buffer,
+ const struct GPUSelectResult *buffer,
short hits,
bool findunsel,
bool do_nearest,
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 5e4cb813064..f9b52eb53ed 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -55,6 +55,8 @@
#include "DEG_depsgraph.h"
+#include "GPU_select.h"
+
#include "armature_intern.h"
/* utility macros for storing a temp int in the bone (selection flag) */
@@ -67,10 +69,10 @@
Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
uint bases_len,
- int hit,
+ const uint select_id,
EditBone **r_ebone)
{
- const uint hit_object = hit & 0xFFFF;
+ const uint hit_object = select_id & 0xFFFF;
Base *base = NULL;
EditBone *ebone = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
@@ -81,7 +83,7 @@ Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
}
}
if (base != NULL) {
- const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
+ const uint hit_bone = (select_id & ~BONESEL_ANY) >> 16;
bArmature *arm = base->object->data;
ebone = BLI_findlink(arm->edbo, hit_bone);
}
@@ -91,10 +93,10 @@ Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
uint objects_len,
- int hit,
+ const uint select_id,
EditBone **r_ebone)
{
- const uint hit_object = hit & 0xFFFF;
+ const uint hit_object = select_id & 0xFFFF;
Object *ob = NULL;
EditBone *ebone = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
@@ -105,7 +107,7 @@ Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
}
}
if (ob != NULL) {
- const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
+ const uint hit_bone = (select_id & ~BONESEL_ANY) >> 16;
bArmature *arm = ob->data;
ebone = BLI_findlink(arm->edbo, hit_bone);
}
@@ -115,10 +117,10 @@ Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
Base *ED_armature_base_and_pchan_from_select_buffer(Base **bases,
uint bases_len,
- int hit,
+ const uint select_id,
bPoseChannel **r_pchan)
{
- const uint hit_object = hit & 0xFFFF;
+ const uint hit_object = select_id & 0xFFFF;
Base *base = NULL;
bPoseChannel *pchan = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
@@ -130,7 +132,7 @@ Base *ED_armature_base_and_pchan_from_select_buffer(Base **bases,
}
if (base != NULL) {
if (base->object->pose != NULL) {
- const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
+ const uint hit_bone = (select_id & ~BONESEL_ANY) >> 16;
/* pchan may be NULL. */
pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
}
@@ -141,11 +143,11 @@ Base *ED_armature_base_and_pchan_from_select_buffer(Base **bases,
Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
uint bases_len,
- int hit,
+ const uint select_id,
Bone **r_bone)
{
bPoseChannel *pchan = NULL;
- Base *base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, hit, &pchan);
+ Base *base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, select_id, &pchan);
*r_bone = pchan ? pchan->bone : NULL;
return base;
}
@@ -166,8 +168,8 @@ Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode,
Base **bases,
uint bases_len,
- const uint *buffer,
- short hits,
+ const GPUSelectResult *buffer,
+ const short hits,
bool findunsel,
bool do_nearest,
Base **r_base)
@@ -181,7 +183,7 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
int minsel = 0xffffffff, minunsel = 0xffffffff;
for (short i = 0; i < hits; i++) {
- hitresult = buffer[3 + (i * 4)];
+ hitresult = buffer[i].id;
if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
Base *base = NULL;
@@ -221,10 +223,10 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
if (data) {
if (sel) {
if (do_nearest) {
- if (minsel > buffer[4 * i + 1]) {
+ if (minsel > buffer[i].depth) {
firstSel = data;
firstSel_base = base;
- minsel = buffer[4 * i + 1];
+ minsel = buffer[i].depth;
}
}
else {
@@ -237,10 +239,10 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
}
else {
if (do_nearest) {
- if (minunsel > buffer[4 * i + 1]) {
+ if (minunsel > buffer[i].depth) {
firstunSel = data;
firstunSel_base = base;
- minunsel = buffer[4 * i + 1];
+ minunsel = buffer[i].depth;
}
}
else {
@@ -268,8 +270,8 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
EditBone *ED_armature_pick_ebone_from_selectbuffer(Base **bases,
uint bases_len,
- const uint *buffer,
- short hits,
+ const GPUSelectResult *buffer,
+ const short hits,
bool findunsel,
bool do_nearest,
Base **r_base)
@@ -281,8 +283,8 @@ EditBone *ED_armature_pick_ebone_from_selectbuffer(Base **bases,
bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(Base **bases,
uint bases_len,
- const uint *buffer,
- short hits,
+ const GPUSelectResult *buffer,
+ const short hits,
bool findunsel,
bool do_nearest,
Base **r_base)
@@ -294,8 +296,8 @@ bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(Base **bases,
Bone *ED_armature_pick_bone_from_selectbuffer(Base **bases,
uint bases_len,
- const uint *buffer,
- short hits,
+ const GPUSelectResult *buffer,
+ const short hits,
bool findunsel,
bool do_nearest,
Base **r_base)
@@ -327,7 +329,7 @@ static void *ed_armature_pick_bone_impl(
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
rcti rect;
- uint buffer[MAXPICKBUF];
+ GPUSelectResult buffer[MAXPICKELEMS];
short hits;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
@@ -340,7 +342,7 @@ static void *ed_armature_pick_bone_impl(
hits = view3d_opengl_select_with_id_filter(&vc,
buffer,
- MAXPICKBUF,
+ ARRAY_SIZE(buffer),
&rect,
VIEW3D_SELECT_PICK_NEAREST,
VIEW3D_SELECT_FILTER_NOP,
@@ -636,15 +638,15 @@ void ARMATURE_OT_select_linked_pick(wmOperatorType *ot)
* \{ */
/* utility function for get_nearest_editbonepoint */
-static int selectbuffer_ret_hits_12(uint *UNUSED(buffer), const int hits12)
+static int selectbuffer_ret_hits_12(GPUSelectResult *UNUSED(buffer), const int hits12)
{
return hits12;
}
-static int selectbuffer_ret_hits_5(uint *buffer, const int hits12, const int hits5)
+static int selectbuffer_ret_hits_5(GPUSelectResult *buffer, const int hits12, const int hits5)
{
- const int ofs = 4 * hits12;
- memcpy(buffer, buffer + ofs, 4 * hits5 * sizeof(uint));
+ const int ofs = hits12;
+ memcpy(buffer, buffer + ofs, hits5 * sizeof(*buffer));
return hits5;
}
@@ -653,7 +655,7 @@ static int selectbuffer_ret_hits_5(uint *buffer, const int hits12, const int hit
static EditBone *get_nearest_editbonepoint(
ViewContext *vc, bool findunsel, bool use_cycle, Base **r_base, int *r_selmask)
{
- uint buffer[MAXPICKBUF];
+ GPUSelectResult buffer[MAXPICKELEMS];
struct {
uint hitresult;
Base *base;
@@ -692,7 +694,7 @@ static EditBone *get_nearest_editbonepoint(
rcti rect;
BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
const int hits12 = view3d_opengl_select_with_id_filter(
- vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter, select_id_ignore);
+ vc, buffer, ARRAY_SIZE(buffer), &rect, select_mode, select_filter, select_id_ignore);
if (hits12 == 1) {
hits = selectbuffer_ret_hits_12(buffer, hits12);
@@ -701,10 +703,15 @@ static EditBone *get_nearest_editbonepoint(
else if (hits12 > 0) {
int ofs;
- ofs = 4 * hits12;
+ ofs = hits12;
BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
- const int hits5 = view3d_opengl_select_with_id_filter(
- vc, buffer + ofs, MAXPICKBUF - ofs, &rect, select_mode, select_filter, select_id_ignore);
+ const int hits5 = view3d_opengl_select_with_id_filter(vc,
+ buffer + ofs,
+ ARRAY_SIZE(buffer) - ofs,
+ &rect,
+ select_mode,
+ select_filter,
+ select_id_ignore);
if (hits5 == 1) {
hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
@@ -732,7 +739,7 @@ cache_end:
/* See if there are any selected bones in this group */
if (hits > 0) {
if (hits == 1) {
- result_bias.hitresult = buffer[3];
+ result_bias.hitresult = buffer->id;
result_bias.base = ED_armature_base_and_ebone_from_select_buffer(
bases, bases_len, result_bias.hitresult, &result_bias.ebone);
}
@@ -771,7 +778,7 @@ cache_end:
}
for (int i = 0; i < hits; i++) {
- const uint hitresult = buffer[3 + (i * 4)];
+ const uint hitresult = buffer[i].id;
Base *base = NULL;
EditBone *ebone;
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 8bd6c9f54fd..cc99027c470 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -149,36 +149,6 @@ bool ED_object_posemode_exit(bContext *C, Object *ob)
return ok;
}
-/* if a selected or active bone is protected, throw error (only if warn == 1) and return 1 */
-/* only_selected == 1: the active bone is allowed to be protected */
-#if 0 /* UNUSED 2.5 */
-static bool pose_has_protected_selected(Object *ob, short warn)
-{
- /* check protection */
- if (ob->proxy) {
- bPoseChannel *pchan;
- bArmature *arm = ob->data;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone && BKE_pose_is_layer_visible(arm, pchan)) {
- if (pchan->bone->layer & arm->layer_protected) {
- if (pchan->bone->flag & BONE_SELECTED) {
- break;
- }
- }
- }
- }
- if (pchan) {
- if (warn) {
- error("Cannot change Proxy protected bones");
- }
- return 1;
- }
- }
- return 0;
-}
-#endif
-
/* ********************************************** */
/* Motion Paths */
@@ -1056,10 +1026,6 @@ static int pose_hide_exec(bContext *C, wmOperator *op)
Object *ob_iter = objects[ob_index];
bArmature *arm = ob_iter->data;
- if (ob_iter->proxy != NULL) {
- BKE_report(op->reports, RPT_INFO, "Undo of hiding can only be done with Reveal Selected");
- }
-
bool changed = bone_looper(ob_iter, arm->bonebase.first, hide_select_p, hide_pose_bone_fn) !=
0;
if (changed) {
diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c
index 38d15d8b880..466c423c27c 100644
--- a/source/blender/editors/armature/pose_group.c
+++ b/source/blender/editors/armature/pose_group.c
@@ -62,8 +62,8 @@ static bool pose_group_poll(bContext *C)
}
Object *obpose = ED_pose_object_from_context(C);
- if ((obpose->proxy != NULL) || (obpose->proxy_group != NULL) || ID_IS_OVERRIDE_LIBRARY(obpose)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit bone groups for proxies or library overrides");
+ if (ID_IS_OVERRIDE_LIBRARY(obpose)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit bone groups for library overrides");
return false;
}
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 0b889149f9d..f41c3657431 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -240,8 +240,8 @@ void ED_armature_pose_select_pick_bone(ViewLayer *view_layer,
bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer,
View3D *v3d,
Base *base,
- const uint *buffer,
- short hits,
+ const struct GPUSelectResult *buffer,
+ const short hits,
bool extend,
bool deselect,
bool toggle,
diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt
index 086fab4ab47..d91102528e5 100644
--- a/source/blender/editors/asset/CMakeLists.txt
+++ b/source/blender/editors/asset/CMakeLists.txt
@@ -21,6 +21,7 @@ set(INC
../../blenkernel
../../blenlib
../../blenloader
+ ../../blentranslation
../../makesdna
../../makesrna
../../windowmanager
diff --git a/source/blender/editors/asset/intern/asset_ops.cc b/source/blender/editors/asset/intern/asset_ops.cc
index f7755aa9fea..0469f14487d 100644
--- a/source/blender/editors/asset/intern/asset_ops.cc
+++ b/source/blender/editors/asset/intern/asset_ops.cc
@@ -39,6 +39,8 @@
/* XXX needs access to the file list, should all be done via the asset system in future. */
#include "ED_fileselect.h"
+#include "BLT_translation.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -342,8 +344,8 @@ static bool asset_clear_poll(bContext *C)
IDVecStats ctx_stats = asset_operation_get_id_vec_stats_from_context(C);
if (!ctx_stats.has_asset) {
- const char *msg_single = "Data-block is not marked as asset";
- const char *msg_multiple = "No data-block selected that is marked as asset";
+ const char *msg_single = TIP_("Data-block is not marked as asset");
+ const char *msg_multiple = TIP_("No data-block selected that is marked as asset");
CTX_wm_operator_poll_msg_set(C, ctx_stats.is_single ? msg_single : msg_multiple);
return false;
}
@@ -365,8 +367,8 @@ static char *asset_clear_get_description(struct bContext *UNUSED(C),
}
return BLI_strdup(
- "Delete all asset metadata, turning the selected asset data-blocks back into normal "
- "data-blocks, and set Fake User to ensure the data-blocks will still be saved");
+ TIP_("Delete all asset metadata, turning the selected asset data-blocks back into normal "
+ "data-blocks, and set Fake User to ensure the data-blocks will still be saved"));
}
static void ASSET_OT_clear(wmOperatorType *ot)
diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt
index 877c2d99102..0ac572c0422 100644
--- a/source/blender/editors/curve/CMakeLists.txt
+++ b/source/blender/editors/curve/CMakeLists.txt
@@ -51,9 +51,5 @@ set(LIB
extern_curve_fit_nd
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_curve "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
index 3635ceb8f13..3871c1de77a 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
@@ -91,7 +91,7 @@ static void gizmo_calc_rect_view_scale(const wmGizmo *gz, const float dims[3], f
static void gizmo_calc_rect_view_margin(const wmGizmo *gz, const float dims[3], float margin[3])
{
- const float handle_size = 0.15f;
+ const float handle_size = 9.0f;
/* XXX, the scale isn't taking offset into account, we need to calculate scale per handle! */
// handle_size *= gz->scale_final;
@@ -178,7 +178,7 @@ static void cage3d_draw_box_interaction(const RegionView3D *rv3d,
float co_test[3];
mul_v3_m4v3(co_test, matrix_final, co);
float rad_scale[3];
- mul_v3_v3fl(rad_scale, rad, ED_view3d_pixel_size(rv3d, co_test) * 60);
+ mul_v3_v3fl(rad_scale, rad, ED_view3d_pixel_size(rv3d, co_test));
{
uint pos = GPU_vertformat_attr_add(
@@ -255,7 +255,7 @@ static void cage3d_draw_circle_handles(const RegionView3D *rv3d,
const float margin[3],
const float color[3],
bool solid,
- float scale)
+ const float handle_scale)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
const float rad[3] = {margin[0] / 3, margin[1] / 3, margin[2] / 3};
@@ -274,7 +274,7 @@ static void cage3d_draw_circle_handles(const RegionView3D *rv3d,
float co_test[3];
mul_v3_m4v3(co_test, matrix_final, co);
float rad_scale[3];
- mul_v3_v3fl(rad_scale, rad, ED_view3d_pixel_size(rv3d, co_test) * scale);
+ mul_v3_v3fl(rad_scale, rad, ED_view3d_pixel_size(rv3d, co_test) * handle_scale);
imm_draw_point_aspect_3d(pos, co, rad_scale, solid);
}
}
@@ -381,7 +381,8 @@ static void gizmo_cage3d_draw_intern(
}
if (show) {
- cage3d_draw_box_interaction(rv3d, matrix_final, gz->color, gz->highlight_part, size_real, margin);
+ cage3d_draw_box_interaction(
+ rv3d, matrix_final, gz->color, gz->highlight_part, size_real, margin);
}
}
else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
@@ -395,10 +396,10 @@ static void gizmo_cage3d_draw_intern(
cage3d_draw_circle_wire(
size_real, margin, color, transform_flag, draw_options, gz->line_width);
- /* corner gizmos */
+ /* Corner gizmos (draw the outer & inner so there is a visible outline). */
GPU_polygon_smooth(true);
- cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, black, true, 60);
- cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, color, true, 40);
+ cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, black, true, 1.0f);
+ cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, color, true, 1.0f / 1.5f);
GPU_polygon_smooth(false);
GPU_blend(GPU_BLEND_NONE);
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index bff7310e9f7..93d17598181 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -86,9 +86,5 @@ if(WITH_POTRACE)
add_definitions(-DWITH_POTRACE)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_gpencil "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index afb786da8c6..c910162415d 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -4635,7 +4635,7 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
}
}
- /* Separate the entrie stroke. */
+ /* Separate the entire stroke. */
if (all_points_selected) {
/* deselect old stroke */
gps->flag &= ~GP_STROKE_SELECT;
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 11b7c85ec58..0521b39ca1a 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -35,6 +35,7 @@ struct Base;
struct Bone;
struct Depsgraph;
struct EditBone;
+struct GPUSelectResult;
struct ListBase;
struct Main;
struct Mesh;
@@ -157,22 +158,22 @@ int ED_armature_join_objects_exec(struct bContext *C, struct wmOperator *op);
struct Base *ED_armature_base_and_ebone_from_select_buffer(struct Base **bases,
uint bases_len,
- int hit,
+ unsigned int select_id,
struct EditBone **r_ebone);
struct Object *ED_armature_object_and_ebone_from_select_buffer(struct Object **objects,
uint objects_len,
- int hit,
+ unsigned int select_id,
struct EditBone **r_ebone);
struct Base *ED_armature_base_and_pchan_from_select_buffer(struct Base **bases,
uint bases_len,
- int hit,
+ unsigned int select_id,
struct bPoseChannel **r_pchan);
/**
* For callers that don't need the pose channel.
*/
struct Base *ED_armature_base_and_bone_from_select_buffer(struct Base **bases,
uint bases_len,
- int hit,
+ unsigned int select_id,
struct Bone **r_bone);
bool ED_armature_edit_deselect_all(struct Object *obedit);
bool ED_armature_edit_deselect_all_visible(struct Object *obedit);
@@ -334,7 +335,7 @@ void ED_armature_pose_select_pick_bone(struct ViewLayer *view_layer,
bool ED_armature_pose_select_pick_with_buffer(struct ViewLayer *view_layer,
struct View3D *v3d,
struct Base *base,
- const unsigned int *buffer,
+ const struct GPUSelectResult *buffer,
short hits,
bool extend,
bool deselect,
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 181b6848ac7..08f4648d02b 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -57,7 +57,7 @@ typedef enum {
#define NODE_EDGE_PAN_DELAY 0.5f
#define NODE_EDGE_PAN_ZOOM_INFLUENCE 0.5f
-/* space_node.c */
+/* space_node.cc */
void ED_node_cursor_location_get(const struct SpaceNode *snode, float value[2]);
void ED_node_cursor_location_set(struct SpaceNode *snode, const float value[2]);
@@ -76,7 +76,7 @@ struct bNodeTree *ED_node_tree_get(struct SpaceNode *snode, int level);
void ED_node_set_active_viewer_key(struct SpaceNode *snode);
-/* drawnode.c */
+/* drawnode.cc */
void ED_node_init_butfuncs(void);
void ED_init_custom_node_type(struct bNodeType *ntype);
@@ -103,7 +103,7 @@ void ED_node_tag_update_id(struct ID *id);
float ED_node_grid_size(void);
-/* node_relationships.c */
+/* node_relationships.cc */
/**
* Test == 0, clear all intersect flags.
@@ -114,7 +114,7 @@ void ED_node_link_intersect_test(struct ScrArea *area, int test);
*/
void ED_node_link_insert(struct Main *bmain, struct ScrArea *area);
-/* node_edit.c */
+/* node_edit.cc */
void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo);
bool ED_node_is_compositor(struct SpaceNode *snode);
@@ -175,11 +175,12 @@ void ED_node_composite_job(const struct bContext *C,
struct bNodeTree *nodetree,
struct Scene *scene_owner);
-/* node_ops.c */
+/* node_ops.cc */
void ED_operatormacros_node(void);
-/* node_view.c */
+/* node_view.cc */
+
/**
* Returns mouse position in image space.
*/
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 0398c209c68..3bbffc3b7c9 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -41,6 +41,7 @@ struct Camera;
struct CustomData_MeshMasks;
struct Depsgraph;
struct EditBone;
+struct GPUSelectResult;
struct ID;
struct MVert;
struct Main;
@@ -871,9 +872,14 @@ bool ED_view3d_autodist_simple(struct ARegion *region,
bool ED_view3d_depth_read_cached_seg(
const ViewDepths *vd, const int mval_sta[2], const int mval_end[2], int margin, float *depth);
-/* select */
+/**
+ * The default value for the maximum number of elements that can be selected at once
+ * using view-port selection.
+ *
+ * \note in many cases this defines the size of fixed-size stack buffers,
+ * so take care increasing this value.
+ */
#define MAXPICKELEMS 2500
-#define MAXPICKBUF (4 * MAXPICKELEMS)
typedef enum {
/* all elements in the region, ignore depth */
@@ -912,21 +918,21 @@ void view3d_opengl_select_cache_end(void);
* \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection.
*/
int view3d_opengl_select_ex(struct ViewContext *vc,
- unsigned int *buffer,
- unsigned int bufsize,
+ struct GPUSelectResult *buffer,
+ unsigned int buffer_len,
const struct rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter,
bool do_material_slot_selection);
int view3d_opengl_select(struct ViewContext *vc,
- unsigned int *buffer,
- unsigned int bufsize,
+ struct GPUSelectResult *buffer,
+ unsigned int buffer_len,
const struct rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter);
int view3d_opengl_select_with_id_filter(struct ViewContext *vc,
- unsigned int *buffer,
- unsigned int bufsize,
+ struct GPUSelectResult *buffer,
+ unsigned int buffer_len,
const struct rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter,
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 3796fa51499..ae4c2ff16fd 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1370,6 +1370,8 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block,
/* for passing inputs to ButO buttons */
struct PointerRNA *UI_but_operator_ptr_get(uiBut *but);
+struct bContextStore *UI_but_context_get(const uiBut *but);
+
void UI_but_unit_type_set(uiBut *but, int unit_type);
int UI_but_unit_type_get(const uiBut *but);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 636281ba373..2292bf759b7 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -5928,6 +5928,11 @@ PointerRNA *UI_but_operator_ptr_get(uiBut *but)
return but->opptr;
}
+bContextStore *UI_but_context_get(const uiBut *but)
+{
+ return but->context;
+}
+
void UI_but_unit_type_set(uiBut *but, const int unit_type)
{
but->unit_type = (uchar)(RNA_SUBTYPE_UNIT_VALUE(unit_type));
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index fd03cc5e12c..6fa94730365 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -25,6 +25,7 @@
#include "DNA_space_types.h"
#include "BLI_math_color.h"
+#include "BLI_math_vector.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -107,7 +108,7 @@ wmKeyMap *eyedropper_colorband_modal_keymap(wmKeyConfig *keyconf)
/** \name Generic Shared Functions
* \{ */
-static void eyedropper_draw_cursor_text_ex(const int x, const int y, const char *name)
+static void eyedropper_draw_cursor_text_ex(const int xy[2], const char *name)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
@@ -119,7 +120,7 @@ static void eyedropper_draw_cursor_text_ex(const int x, const int y, const char
rgba_uchar_to_float(col_fg, wcol->text);
rgba_uchar_to_float(col_bg, wcol->inner);
- UI_fontstyle_draw_simple_backdrop(fstyle, x, y + U.widget_unit, name, col_fg, col_bg);
+ UI_fontstyle_draw_simple_backdrop(fstyle, xy[0], xy[1] + U.widget_unit, name, col_fg, col_bg);
}
void eyedropper_draw_cursor_text_window(const struct wmWindow *window, const char *name)
@@ -128,19 +129,16 @@ void eyedropper_draw_cursor_text_window(const struct wmWindow *window, const cha
return;
}
- const int x = window->eventstate->xy[0];
- const int y = window->eventstate->xy[1];
-
- eyedropper_draw_cursor_text_ex(x, y, name);
+ eyedropper_draw_cursor_text_ex(window->eventstate->xy, name);
}
-void eyedropper_draw_cursor_text_region(const int x, const int y, const char *name)
+void eyedropper_draw_cursor_text_region(const int xy[2], const char *name)
{
if (name[0] == '\0') {
return;
}
- eyedropper_draw_cursor_text_ex(x, y, name);
+ eyedropper_draw_cursor_text_ex(xy, name);
}
uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *event)
@@ -173,8 +171,7 @@ void datadropper_win_area_find(
}
}
else if (mval != r_mval) {
- r_mval[0] = mval[0];
- r_mval[1] = mval[1];
+ copy_v2_v2_int(r_mval, mval);
}
}
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index 05840175fab..b5eed2534a3 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -254,8 +254,10 @@ static bool eyedropper_cryptomatte_sample_image_fl(const bNode *node,
return success;
}
-static bool eyedropper_cryptomatte_sample_fl(
- bContext *C, Eyedropper *eye, int mx, int my, float r_col[3])
+static bool eyedropper_cryptomatte_sample_fl(bContext *C,
+ Eyedropper *eye,
+ const int m_xy[2],
+ float r_col[3])
{
bNode *node = eye->crypto_node;
NodeCryptomatte *crypto = node ? ((NodeCryptomatte *)node->storage) : NULL;
@@ -265,17 +267,17 @@ static bool eyedropper_cryptomatte_sample_fl(
}
bScreen *screen = CTX_wm_screen(C);
- ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, (const int[2]){mx, my});
+ ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, m_xy);
if (!area || !ELEM(area->spacetype, SPACE_IMAGE, SPACE_NODE, SPACE_CLIP)) {
return false;
}
- ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, (const int[2]){mx, my});
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, m_xy);
if (!region) {
return false;
}
- int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
+ int mval[2] = {m_xy[0] - region->winrct.xmin, m_xy[1] - region->winrct.ymin};
float fpos[2] = {-1.0f, -1.0};
switch (area->spacetype) {
case SPACE_IMAGE: {
@@ -324,7 +326,7 @@ static bool eyedropper_cryptomatte_sample_fl(
return false;
}
-void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
+void eyedropper_color_sample_fl(bContext *C, const int m_xy[2], float r_col[3])
{
/* we could use some clever */
Main *bmain = CTX_data_main(C);
@@ -332,10 +334,10 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
const char *display_device = CTX_data_scene(C)->display_settings.display_device;
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
+ int mval[2];
wmWindow *win;
ScrArea *area;
- int mval[2] = {mx, my};
- datadropper_win_area_find(C, mval, mval, &win, &area);
+ datadropper_win_area_find(C, m_xy, mval, &win, &area);
if (area) {
if (area->spacetype == SPACE_IMAGE) {
@@ -406,17 +408,17 @@ static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3
RNA_property_update(C, &eye->ptr, eye->prop);
}
-static void eyedropper_color_sample(bContext *C, Eyedropper *eye, int mx, int my)
+static void eyedropper_color_sample(bContext *C, Eyedropper *eye, const int m_xy[2])
{
/* Accumulate color. */
float col[3];
if (eye->crypto_node) {
- if (!eyedropper_cryptomatte_sample_fl(C, eye, mx, my, col)) {
+ if (!eyedropper_cryptomatte_sample_fl(C, eye, m_xy, col)) {
return;
}
}
else {
- eyedropper_color_sample_fl(C, mx, my, col);
+ eyedropper_color_sample_fl(C, m_xy, col);
}
if (!eye->crypto_node) {
@@ -439,13 +441,13 @@ static void eyedropper_color_sample(bContext *C, Eyedropper *eye, int mx, int my
eyedropper_color_set(C, eye, accum_col);
}
-static void eyedropper_color_sample_text_update(bContext *C, Eyedropper *eye, int mx, int my)
+static void eyedropper_color_sample_text_update(bContext *C, Eyedropper *eye, const int m_xy[2])
{
float col[3];
eye->sample_text[0] = '\0';
if (eye->cryptomatte_session) {
- if (eyedropper_cryptomatte_sample_fl(C, eye, mx, my, col)) {
+ if (eyedropper_cryptomatte_sample_fl(C, eye, m_xy, col)) {
BKE_cryptomatte_find_name(
eye->cryptomatte_session, col[0], eye->sample_text, sizeof(eye->sample_text));
eye->sample_text[sizeof(eye->sample_text) - 1] = '\0';
@@ -476,7 +478,7 @@ static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
case EYE_MODAL_SAMPLE_CONFIRM: {
const bool is_undo = eye->is_undo;
if (eye->accum_tot == 0) {
- eyedropper_color_sample(C, eye, event->xy[0], event->xy[1]);
+ eyedropper_color_sample(C, eye, event->xy);
}
eyedropper_exit(C, op);
/* Could support finished & undo-skip. */
@@ -485,23 +487,23 @@ static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
case EYE_MODAL_SAMPLE_BEGIN:
/* enable accum and make first sample */
eye->accum_start = true;
- eyedropper_color_sample(C, eye, event->xy[0], event->xy[1]);
+ eyedropper_color_sample(C, eye, event->xy);
break;
case EYE_MODAL_SAMPLE_RESET:
eye->accum_tot = 0;
zero_v3(eye->accum_col);
- eyedropper_color_sample(C, eye, event->xy[0], event->xy[1]);
+ eyedropper_color_sample(C, eye, event->xy);
break;
}
}
else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
if (eye->accum_start) {
/* button is pressed so keep sampling */
- eyedropper_color_sample(C, eye, event->xy[0], event->xy[1]);
+ eyedropper_color_sample(C, eye, event->xy);
}
if (eye->draw_handle_sample_text) {
- eyedropper_color_sample_text_update(C, eye, event->xy[0], event->xy[1]);
+ eyedropper_color_sample_text_update(C, eye, event->xy);
ED_region_tag_redraw(CTX_wm_region(C));
}
}
diff --git a/source/blender/editors/interface/interface_eyedropper_colorband.c b/source/blender/editors/interface/interface_eyedropper_colorband.c
index 22320282766..05ed4ecf601 100644
--- a/source/blender/editors/interface/interface_eyedropper_colorband.c
+++ b/source/blender/editors/interface/interface_eyedropper_colorband.c
@@ -58,7 +58,7 @@ typedef struct Colorband_RNAUpdateCb {
} Colorband_RNAUpdateCb;
typedef struct EyedropperColorband {
- int last_x, last_y;
+ int event_xy_last[2];
/* Alpha is currently fixed at 1.0, may support in future. */
float (*color_buffer)[4];
int color_buffer_alloc;
@@ -142,13 +142,12 @@ static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
static void eyedropper_colorband_sample_point(bContext *C,
EyedropperColorband *eye,
- int mx,
- int my)
+ const int m_xy[2])
{
- if (eye->last_x != mx || eye->last_y != my) {
+ if (eye->event_xy_last[0] != m_xy[0] || eye->event_xy_last[1] != m_xy[1]) {
float col[4];
col[3] = 1.0f; /* TODO: sample alpha */
- eyedropper_color_sample_fl(C, mx, my, col);
+ eyedropper_color_sample_fl(C, m_xy, col);
if (eye->color_buffer_len + 1 == eye->color_buffer_alloc) {
eye->color_buffer_alloc *= 2;
eye->color_buffer = MEM_reallocN(eye->color_buffer,
@@ -156,8 +155,7 @@ static void eyedropper_colorband_sample_point(bContext *C,
}
copy_v4_v4(eye->color_buffer[eye->color_buffer_len], col);
eye->color_buffer_len += 1;
- eye->last_x = mx;
- eye->last_y = my;
+ copy_v2_v2_int(eye->event_xy_last, m_xy);
eye->is_set = true;
}
}
@@ -167,21 +165,20 @@ static bool eyedropper_colorband_sample_callback(int mx, int my, void *userdata)
struct EyedropperColorband_Context *data = userdata;
bContext *C = data->context;
EyedropperColorband *eye = data->eye;
- eyedropper_colorband_sample_point(C, eye, mx, my);
+ const int cursor[2] = {mx, my};
+ eyedropper_colorband_sample_point(C, eye, cursor);
return true;
}
static void eyedropper_colorband_sample_segment(bContext *C,
EyedropperColorband *eye,
- int mx,
- int my)
+ const int m_xy[2])
{
/* Since the mouse tends to move rather rapidly we use #BLI_bitmap_draw_2d_line_v2v2i
* to interpolate between the reported coordinates */
struct EyedropperColorband_Context userdata = {C, eye};
- const int p1[2] = {eye->last_x, eye->last_y};
- const int p2[2] = {mx, my};
- BLI_bitmap_draw_2d_line_v2v2i(p1, p2, eyedropper_colorband_sample_callback, &userdata);
+ BLI_bitmap_draw_2d_line_v2v2i(
+ eye->event_xy_last, m_xy, eyedropper_colorband_sample_callback, &userdata);
}
static void eyedropper_colorband_exit(bContext *C, wmOperator *op)
@@ -233,7 +230,7 @@ static int eyedropper_colorband_modal(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_CANCELLED;
case EYE_MODAL_SAMPLE_CONFIRM: {
const bool is_undo = eye->is_undo;
- eyedropper_colorband_sample_segment(C, eye, event->xy[0], event->xy[1]);
+ eyedropper_colorband_sample_segment(C, eye, event->xy);
eyedropper_colorband_apply(C, op);
eyedropper_colorband_exit(C, op);
/* Could support finished & undo-skip. */
@@ -242,10 +239,9 @@ static int eyedropper_colorband_modal(bContext *C, wmOperator *op, const wmEvent
case EYE_MODAL_SAMPLE_BEGIN:
/* enable accum and make first sample */
eye->sample_start = true;
- eyedropper_colorband_sample_point(C, eye, event->xy[0], event->xy[1]);
+ eyedropper_colorband_sample_point(C, eye, event->xy);
eyedropper_colorband_apply(C, op);
- eye->last_x = event->xy[0];
- eye->last_y = event->xy[1];
+ copy_v2_v2_int(eye->event_xy_last, event->xy);
break;
case EYE_MODAL_SAMPLE_RESET:
break;
@@ -253,7 +249,7 @@ static int eyedropper_colorband_modal(bContext *C, wmOperator *op, const wmEvent
}
else if (event->type == MOUSEMOVE) {
if (eye->sample_start) {
- eyedropper_colorband_sample_segment(C, eye, event->xy[0], event->xy[1]);
+ eyedropper_colorband_sample_segment(C, eye, event->xy);
eyedropper_colorband_apply(C, op);
}
}
@@ -280,7 +276,7 @@ static int eyedropper_colorband_point_modal(bContext *C, wmOperator *op, const w
}
break;
case EYE_MODAL_POINT_SAMPLE:
- eyedropper_colorband_sample_point(C, eye, event->xy[0], event->xy[1]);
+ eyedropper_colorband_sample_point(C, eye, event->xy);
eyedropper_colorband_apply(C, op);
if (eye->color_buffer_len == MAXCOLORBAND) {
eyedropper_colorband_exit(C, op);
diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c
index cf53ef0ec75..812011101e8 100644
--- a/source/blender/editors/interface/interface_eyedropper_datablock.c
+++ b/source/blender/editors/interface/interface_eyedropper_datablock.c
@@ -32,6 +32,7 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "BLI_math_vector.h"
#include "BLI_string.h"
#include "BLT_translation.h"
@@ -80,7 +81,7 @@ static void datadropper_draw_cb(const struct bContext *UNUSED(C),
void *arg)
{
DataDropper *ddr = arg;
- eyedropper_draw_cursor_text_region(UNPACK2(ddr->name_pos), ddr->name);
+ eyedropper_draw_cursor_text_region(ddr->name_pos, ddr->name);
}
static int datadropper_init(bContext *C, wmOperator *op)
@@ -152,7 +153,7 @@ static void datadropper_exit(bContext *C, wmOperator *op)
* \brief get the ID from the 3D view or outliner.
*/
static void datadropper_id_sample_pt(
- bContext *C, wmWindow *win, ScrArea *area, DataDropper *ddr, int mx, int my, ID **r_id)
+ bContext *C, wmWindow *win, ScrArea *area, DataDropper *ddr, const int m_xy[2], ID **r_id)
{
wmWindow *win_prev = CTX_wm_window(C);
ScrArea *area_prev = CTX_wm_area(C);
@@ -162,9 +163,9 @@ static void datadropper_id_sample_pt(
if (area) {
if (ELEM(area->spacetype, SPACE_VIEW3D, SPACE_OUTLINER)) {
- ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, (const int[2]){mx, my});
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, m_xy);
if (region) {
- const int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
+ const int mval[2] = {m_xy[0] - region->winrct.xmin, m_xy[1] - region->winrct.ymin};
Base *base;
CTX_wm_window_set(C, win);
@@ -205,8 +206,7 @@ static void datadropper_id_sample_pt(
*r_id = id;
}
- ddr->name_pos[0] = mval[0];
- ddr->name_pos[1] = mval[1];
+ copy_v2_v2_int(ddr->name_pos, mval);
}
}
}
@@ -234,17 +234,16 @@ static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id)
}
/* single point sample & set */
-static bool datadropper_id_sample(bContext *C, DataDropper *ddr, int mx, int my)
+static bool datadropper_id_sample(bContext *C, DataDropper *ddr, const int m_xy[2])
{
ID *id = NULL;
+ int mval[2];
wmWindow *win;
ScrArea *area;
+ datadropper_win_area_find(C, m_xy, mval, &win, &area);
- int mval[] = {mx, my};
- datadropper_win_area_find(C, mval, mval, &win, &area);
-
- datadropper_id_sample_pt(C, win, area, ddr, mval[0], mval[1], &id);
+ datadropper_id_sample_pt(C, win, area, ddr, mval, &id);
return datadropper_id_set(C, ddr, id);
}
@@ -292,7 +291,7 @@ static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
case EYE_MODAL_SAMPLE_CONFIRM: {
const bool is_undo = ddr->is_undo;
- const bool success = datadropper_id_sample(C, ddr, event->xy[0], event->xy[1]);
+ const bool success = datadropper_id_sample(C, ddr, event->xy);
datadropper_exit(C, op);
if (success) {
/* Could support finished & undo-skip. */
@@ -306,16 +305,15 @@ static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
else if (event->type == MOUSEMOVE) {
ID *id = NULL;
+ int mval[2];
wmWindow *win;
ScrArea *area;
-
- int mval[] = {event->xy[0], event->xy[1]};
- datadropper_win_area_find(C, mval, mval, &win, &area);
+ datadropper_win_area_find(C, event->xy, mval, &win, &area);
/* Set the region for eyedropper cursor text drawing */
datadropper_set_draw_callback_region(area, ddr);
- datadropper_id_sample_pt(C, win, area, ddr, mval[0], mval[1], &id);
+ datadropper_id_sample_pt(C, win, area, ddr, mval, &id);
}
return OPERATOR_RUNNING_MODAL;
diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c
index 8c6b0ac9cfe..b11001c4bf2 100644
--- a/source/blender/editors/interface/interface_eyedropper_depth.c
+++ b/source/blender/editors/interface/interface_eyedropper_depth.c
@@ -81,7 +81,7 @@ static void depthdropper_draw_cb(const struct bContext *UNUSED(C),
void *arg)
{
DepthDropper *ddr = arg;
- eyedropper_draw_cursor_text_region(UNPACK2(ddr->name_pos), ddr->name);
+ eyedropper_draw_cursor_text_region(ddr->name_pos, ddr->name);
}
static int depthdropper_init(bContext *C, wmOperator *op)
@@ -152,12 +152,14 @@ static void depthdropper_exit(bContext *C, wmOperator *op)
/**
* \brief get the ID from the screen.
*/
-static void depthdropper_depth_sample_pt(
- bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth)
+static void depthdropper_depth_sample_pt(bContext *C,
+ DepthDropper *ddr,
+ const int m_xy[2],
+ float *r_depth)
{
/* we could use some clever */
bScreen *screen = CTX_wm_screen(C);
- ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, (const int[2]){mx, my});
+ ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, m_xy);
Scene *scene = CTX_data_scene(C);
ScrArea *area_prev = CTX_wm_area(C);
@@ -167,14 +169,14 @@ static void depthdropper_depth_sample_pt(
if (area) {
if (area->spacetype == SPACE_VIEW3D) {
- ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, (const int[2]){mx, my});
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, m_xy);
if (region) {
struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
View3D *v3d = area->spacedata.first;
RegionView3D *rv3d = region->regiondata;
/* weak, we could pass in some reference point */
const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3];
- const int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
+ const int mval[2] = {m_xy[0] - region->winrct.xmin, m_xy[1] - region->winrct.ymin};
copy_v2_v2_int(ddr->name_pos, mval);
float co[3];
@@ -234,19 +236,19 @@ static void depthdropper_depth_set_accum(bContext *C, DepthDropper *ddr)
}
/* single point sample & set */
-static void depthdropper_depth_sample(bContext *C, DepthDropper *ddr, int mx, int my)
+static void depthdropper_depth_sample(bContext *C, DepthDropper *ddr, const int m_xy[2])
{
float depth = -1.0f;
if (depth != -1.0f) {
- depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
+ depthdropper_depth_sample_pt(C, ddr, m_xy, &depth);
depthdropper_depth_set(C, ddr, depth);
}
}
-static void depthdropper_depth_sample_accum(bContext *C, DepthDropper *ddr, int mx, int my)
+static void depthdropper_depth_sample_accum(bContext *C, DepthDropper *ddr, const int m_xy[2])
{
float depth = -1.0f;
- depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
+ depthdropper_depth_sample_pt(C, ddr, m_xy, &depth);
if (depth != -1.0f) {
ddr->accum_depth += depth;
ddr->accum_tot++;
@@ -276,7 +278,7 @@ static int depthdropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
case EYE_MODAL_SAMPLE_CONFIRM: {
const bool is_undo = ddr->is_undo;
if (ddr->accum_tot == 0) {
- depthdropper_depth_sample(C, ddr, event->xy[0], event->xy[1]);
+ depthdropper_depth_sample(C, ddr, event->xy);
}
else {
depthdropper_depth_set_accum(C, ddr);
@@ -288,12 +290,12 @@ static int depthdropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
case EYE_MODAL_SAMPLE_BEGIN:
/* enable accum and make first sample */
ddr->accum_start = true;
- depthdropper_depth_sample_accum(C, ddr, event->xy[0], event->xy[1]);
+ depthdropper_depth_sample_accum(C, ddr, event->xy);
break;
case EYE_MODAL_SAMPLE_RESET:
ddr->accum_tot = 0;
ddr->accum_depth = 0.0f;
- depthdropper_depth_sample_accum(C, ddr, event->xy[0], event->xy[1]);
+ depthdropper_depth_sample_accum(C, ddr, event->xy);
depthdropper_depth_set_accum(C, ddr);
break;
}
@@ -301,7 +303,7 @@ static int depthdropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
else if (event->type == MOUSEMOVE) {
if (ddr->accum_start) {
/* button is pressed so keep sampling */
- depthdropper_depth_sample_accum(C, ddr, event->xy[0], event->xy[1]);
+ depthdropper_depth_sample_accum(C, ddr, event->xy);
depthdropper_depth_set_accum(C, ddr);
}
}
diff --git a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
index d76ff84bcad..c1d49406818 100644
--- a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
@@ -265,9 +265,9 @@ static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, Eyed
}
/* Sample the color below cursor. */
-static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, int mx, int my)
+static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, const int m_xy[2])
{
- eyedropper_color_sample_fl(C, mx, my, eye->color);
+ eyedropper_color_sample_fl(C, m_xy, eye->color);
}
/* Cancel operator. */
@@ -292,7 +292,7 @@ static int eyedropper_gpencil_modal(bContext *C, wmOperator *op, const wmEvent *
return OPERATOR_CANCELLED;
}
case EYE_MODAL_SAMPLE_CONFIRM: {
- eyedropper_gpencil_color_sample(C, eye, event->xy[0], event->xy[1]);
+ eyedropper_gpencil_color_sample(C, eye, event->xy);
/* Create material. */
eyedropper_gpencil_color_set(C, event, eye);
@@ -309,7 +309,7 @@ static int eyedropper_gpencil_modal(bContext *C, wmOperator *op, const wmEvent *
}
case MOUSEMOVE:
case INBETWEEN_MOUSEMOVE: {
- eyedropper_gpencil_color_sample(C, eye, event->xy[0], event->xy[1]);
+ eyedropper_gpencil_color_sample(C, eye, event->xy);
break;
}
default: {
diff --git a/source/blender/editors/interface/interface_eyedropper_intern.h b/source/blender/editors/interface/interface_eyedropper_intern.h
index ec448ef9b9f..335ee520791 100644
--- a/source/blender/editors/interface/interface_eyedropper_intern.h
+++ b/source/blender/editors/interface/interface_eyedropper_intern.h
@@ -25,7 +25,7 @@
/* interface_eyedropper.c */
void eyedropper_draw_cursor_text_window(const struct wmWindow *window, const char *name);
-void eyedropper_draw_cursor_text_region(int x, int y, const char *name);
+void eyedropper_draw_cursor_text_region(const int xy[2], const char *name);
/**
* Utility to retrieve a button representing a RNA property that is currently under the cursor.
*
@@ -51,7 +51,7 @@ void datadropper_win_area_find(const struct bContext *C,
*
* \note Exposed by 'interface_eyedropper_intern.h' for use with color band picking.
*/
-void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3]);
+void eyedropper_color_sample_fl(bContext *C, const int m_xy[2], float r_col[3]);
/* Used for most eye-dropper operators. */
enum {
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 905fd452b6c..a171160d020 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -3957,7 +3957,14 @@ static void ui_do_but_textedit(
ui_textedit_delete_selection(but, data);
}
if (event->type == WM_IME_COMPOSITE_EVENT && ime_data->result_len) {
- ui_textedit_insert_buf(but, data, ime_data->str_result, ime_data->result_len);
+ if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) &&
+ strcmp(ime_data->str_result, "\xE3\x80\x82") == 0) {
+ /* Convert Ideographic Full Stop (U+3002) to decimal point when entering numbers. */
+ ui_textedit_insert_ascii(but, data, '.');
+ }
+ else {
+ ui_textedit_insert_buf(but, data, ime_data->str_result, ime_data->result_len);
+ }
}
}
else if (event->type == WM_IME_COMPOSITE_END) {
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 33c6e382f50..260e3dabc25 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -2073,8 +2073,9 @@ static void UI_OT_tree_view_drop(wmOperatorType *ot)
/** \name UI Tree-View Item Rename Operator
*
* General purpose renaming operator for tree-views. Thanks to this, to add a rename button to
- * context menus for example, tree-view API users don't have to implement own renaming operators
- * with the same logic as they already have for their #ui::AbstractTreeViewItem::rename() override.
+ * context menus for example, tree-view API users don't have to implement their own renaming
+ * operators with the same logic as they already have for their #ui::AbstractTreeViewItem::rename()
+ * override.
*
* \{ */
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 44942d508ca..bf3fa6e62d4 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -39,9 +39,8 @@
#include "BKE_global.h"
#include "BLF_api.h"
-#ifdef WITH_INTERNATIONAL
-# include "BLT_translation.h"
-#endif
+
+#include "BLT_translation.h"
#include "UI_interface.h"
@@ -454,15 +453,6 @@ void uiStyleInit(void)
printf("%s: error, no fonts available\n", __func__);
}
}
- else {
- /* ? just for speed to initialize?
- * Yes, this build the glyph cache and create
- * the texture.
- */
- BLF_size(font->blf_id, 11.0f * U.pixelsize, U.dpi);
- BLF_size(font->blf_id, 12.0f * U.pixelsize, U.dpi);
- BLF_size(font->blf_id, 14.0f * U.pixelsize, U.dpi);
- }
}
if (style == NULL) {
@@ -486,8 +476,6 @@ void uiStyleInit(void)
blf_mono_font = BLF_load_mono_default(unique);
}
- BLF_size(blf_mono_font, 12.0f * U.pixelsize, 72);
-
/* Set default flags based on UI preferences (not render fonts) */
{
const int flag_disable = (BLF_MONOCHROME | BLF_HINTING_NONE | BLF_HINTING_SLIGHT |
@@ -530,8 +518,6 @@ void uiStyleInit(void)
const bool unique = true;
blf_mono_font_render = BLF_load_mono_default(unique);
}
-
- BLF_size(blf_mono_font_render, 12.0f * U.pixelsize, 72);
}
void UI_fontstyle_set(const uiFontStyle *fs)
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 8330f8c0db7..d605847c270 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -2672,18 +2672,6 @@ static void constraint_ops_extra_draw(bContext *C, uiLayout *layout, void *con_v
static void draw_constraint_header(uiLayout *layout, Object *ob, bConstraint *con)
{
- bPoseChannel *pchan = BKE_pose_channel_active_if_layer_visible(ob);
- short proxy_protected, xco = 0, yco = 0;
- // int rb_col; // UNUSED
-
- /* determine whether constraint is proxy protected or not */
- if (BKE_constraints_proxylocked_owner(ob, pchan)) {
- proxy_protected = (con->flag & CONSTRAINT_PROXY_LOCAL) == 0;
- }
- else {
- proxy_protected = 0;
- }
-
/* unless button has own callback, it adds this callback to button */
uiBlock *block = uiLayoutGetBlock(layout);
UI_block_func_set(block, constraint_active_func, ob, con);
@@ -2708,72 +2696,23 @@ static void draw_constraint_header(uiLayout *layout, Object *ob, bConstraint *co
uiLayout *row = uiLayoutRow(layout, true);
- if (proxy_protected == 0) {
- uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
- }
- else {
- uiItemL(row, IFACE_(con->name), ICON_NONE);
- }
-
- /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
- if (proxy_protected) {
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- /* draw a ghost icon (for proxy) and also a lock beside it,
- * to show that constraint is "proxy locked" */
- uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_GHOST_ENABLED,
- xco + 12.2f * UI_UNIT_X,
- yco,
- 0.95f * UI_UNIT_X,
- 0.95f * UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- TIP_("Proxy Protected"));
- uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_LOCKED,
- xco + 13.1f * UI_UNIT_X,
- yco,
- 0.95f * UI_UNIT_X,
- 0.95f * UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- TIP_("Proxy Protected"));
+ uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
- UI_block_emboss_set(block, UI_EMBOSS);
- }
- else {
- /* Enabled eye icon. */
- uiItemR(row, &ptr, "enabled", 0, "", ICON_NONE);
+ /* Enabled eye icon. */
+ uiItemR(row, &ptr, "enabled", 0, "", ICON_NONE);
- /* Extra operators menu. */
- uiItemMenuF(row, "", ICON_DOWNARROW_HLT, constraint_ops_extra_draw, con);
+ /* Extra operators menu. */
+ uiItemMenuF(row, "", ICON_DOWNARROW_HLT, constraint_ops_extra_draw, con);
- /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
- sub = uiLayoutRow(row, false);
- uiLayoutSetEmboss(sub, UI_EMBOSS_NONE);
- uiLayoutSetOperatorContext(sub, WM_OP_INVOKE_DEFAULT);
- uiItemO(sub, "", ICON_X, "CONSTRAINT_OT_delete");
- }
+ /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
+ sub = uiLayoutRow(row, false);
+ uiLayoutSetEmboss(sub, UI_EMBOSS_NONE);
+ uiLayoutSetOperatorContext(sub, WM_OP_INVOKE_DEFAULT);
+ uiItemO(sub, "", ICON_X, "CONSTRAINT_OT_delete");
/* Some extra padding at the end, so the 'x' icon isn't too close to drag button. */
uiItemS(layout);
- /* Set but-locks for protected settings (magic numbers are used here!) */
- if (proxy_protected) {
- UI_block_lock_set(block, true, TIP_("Cannot edit Proxy-Protected Constraint"));
- }
-
/* clear any locks set up for proxies/lib-linking */
UI_block_lock_clear(block);
}
diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt
index cb1c3cedf8e..5db16354124 100644
--- a/source/blender/editors/io/CMakeLists.txt
+++ b/source/blender/editors/io/CMakeLists.txt
@@ -84,10 +84,6 @@ if(WITH_USD)
add_definitions(-DWITH_USD)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_PUGIXML)
add_definitions(-DWITH_PUGIXML)
endif()
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 4ad2e57d266..0fb64c8a46b 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -78,10 +78,6 @@ set(LIB
bf_windowmanager
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 7e05209f79e..8383492e459 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -32,6 +32,7 @@
#include "BLI_math.h"
#include "BLI_math_bits.h"
#include "BLI_rand.h"
+#include "BLI_string.h"
#include "BLI_utildefines_stack.h"
#include "BKE_context.h"
@@ -55,6 +56,8 @@
#include "ED_transform.h"
#include "ED_view3d.h"
+#include "BLT_translation.h"
+
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -1389,6 +1392,37 @@ static int edbm_select_mode_invoke(bContext *C, wmOperator *op, const wmEvent *e
return edbm_select_mode_exec(C, op);
}
+static char *edbm_select_mode_get_description(struct bContext *UNUSED(C),
+ struct wmOperatorType *UNUSED(op),
+ struct PointerRNA *values)
+{
+ const int type = RNA_enum_get(values, "type");
+
+ /* Because the special behavior for shift and ctrl click depend on user input, they may be
+ * incorrect if the operator is used from a script or from a special button. So only return the
+ * specialized descriptions if only the "type" is set, which conveys that the operator is meant
+ * to be used with the logic in the `invoke` method. */
+ if (RNA_struct_property_is_set(values, "type") &&
+ !RNA_struct_property_is_set(values, "use_extend") &&
+ !RNA_struct_property_is_set(values, "use_expand") &&
+ !RNA_struct_property_is_set(values, "action")) {
+ switch (type) {
+ case SCE_SELECT_VERTEX:
+ return BLI_strdup(TIP_(
+ "Vertex select - Shift-Click for multiple modes, Ctrl-Click contracts selection"));
+ case SCE_SELECT_EDGE:
+ return BLI_strdup(
+ TIP_("Edge select - Shift-Click for multiple modes, "
+ "Ctrl-Click expands/contracts selection depending on the current mode"));
+ case SCE_SELECT_FACE:
+ return BLI_strdup(
+ TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"));
+ }
+ }
+
+ return NULL;
+}
+
void MESH_OT_select_mode(wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -1409,6 +1443,7 @@ void MESH_OT_select_mode(wmOperatorType *ot)
ot->invoke = edbm_select_mode_invoke;
ot->exec = edbm_select_mode_exec;
ot->poll = ED_operator_editmesh;
+ ot->get_description = edbm_select_mode_get_description;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/metaball/CMakeLists.txt b/source/blender/editors/metaball/CMakeLists.txt
index 4e600dc0277..a247920c305 100644
--- a/source/blender/editors/metaball/CMakeLists.txt
+++ b/source/blender/editors/metaball/CMakeLists.txt
@@ -20,6 +20,7 @@ set(INC
../../blenkernel
../../blenlib
../../depsgraph
+ ../../gpu
../../makesdna
../../makesrna
../../render
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index bedb9d4f4f4..51cfc920d1d 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -47,6 +47,8 @@
#include "DEG_depsgraph.h"
+#include "GPU_select.h"
+
#include "ED_mball.h"
#include "ED_object.h"
#include "ED_screen.h"
@@ -756,15 +758,19 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
static MetaElem *startelem = NULL;
ViewContext vc;
int a, hits;
- uint buffer[MAXPICKBUF];
+ GPUSelectResult buffer[MAXPICKELEMS];
rcti rect;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
BLI_rcti_init_pt_radius(&rect, mval, 12);
- hits = view3d_opengl_select(
- &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
+ hits = view3d_opengl_select(&vc,
+ buffer,
+ ARRAY_SIZE(buffer),
+ &rect,
+ VIEW3D_SELECT_PICK_NEAREST,
+ VIEW3D_SELECT_FILTER_NOP);
FOREACH_BASE_IN_EDIT_MODE_BEGIN (vc.view_layer, vc.v3d, base) {
ED_view3d_viewcontext_init_object(&vc, base->object);
@@ -789,7 +795,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
ml = startelem;
while (ml) {
for (a = 0; a < hits; a++) {
- int hitresult = buffer[(4 * a) + 3];
+ const int hitresult = buffer[a].id;
if (hitresult == -1) {
continue;
}
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 040b5cd5066..a953c7d7f89 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -85,10 +85,6 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_SIMULATION_DATABLOCK)
add_definitions(-DWITH_POINT_CLOUD)
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 8a493eb0743..0f1b0f5bdc0 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -2347,11 +2347,6 @@ static void make_object_duplilist_real(bContext *C,
BKE_animdata_free(&ob_dst->id, true);
ob_dst->adt = NULL;
- /* Proxies are not to be copied. */
- ob_dst->proxy_from = NULL;
- ob_dst->proxy_group = NULL;
- ob_dst->proxy = NULL;
-
ob_dst->parent = NULL;
BKE_constraints_free(&ob_dst->constraints);
ob_dst->runtime.curve_cache = NULL;
@@ -2466,13 +2461,6 @@ static void make_object_duplilist_real(bContext *C,
}
if (base->object->transflag & OB_DUPLICOLLECTION && base->object->instance_collection) {
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- if (ob->proxy_group == base->object) {
- ob->proxy = NULL;
- ob->proxy_from = NULL;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- }
base->object->instance_collection = NULL;
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 91a512ae8e9..7ef17689912 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -1356,15 +1356,6 @@ void ED_object_constraint_update(Main *bmain, Object *ob)
static void object_pose_tag_update(Main *bmain, Object *ob)
{
BKE_pose_tag_recalc(bmain, ob->pose); /* Checks & sort pose channels. */
- if (ob->proxy && ob->adt) {
- /* We need to make use of ugly #POSE_ANIMATION_WORKAROUND here too,
- * else anim data are not reloaded after calling `BKE_pose_rebuild()`,
- * which causes T43872.
- * Note that this is a bit wide here, since we cannot be sure whether there are some locked
- * proxy bones or not.
- * XXX Temp hack until new depsgraph hopefully solves this. */
- DEG_id_tag_update(&ob->id, ID_RECALC_ANIMATION);
- }
}
void ED_object_constraint_dependency_update(Main *bmain, Object *ob)
@@ -2453,12 +2444,6 @@ static int constraint_add_exec(
if ((ob->type == OB_ARMATURE) && (pchan)) {
BKE_pose_tag_recalc(bmain, ob->pose); /* sort pose channels */
- if (BKE_constraints_proxylocked_owner(ob, pchan) && ob->adt) {
- /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too,
- * else anim data are not reloaded after calling `BKE_pose_rebuild()`, which causes T43872.
- * XXX Temp hack until new depsgraph hopefully solves this. */
- DEG_id_tag_update(&ob->id, ID_RECALC_ANIMATION);
- }
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
}
else {
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index 595822de1e7..3744cbee3a4 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -43,6 +43,8 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
+#include "BLT_translation.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -610,8 +612,8 @@ static char *data_transfer_get_description(bContext *UNUSED(C),
const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
if (reverse_transfer) {
- return BLI_strdup(
- "Transfer data layer(s) (weights, edge sharp, etc.) from selected meshes to active one");
+ return BLI_strdup(TIP_(
+ "Transfer data layer(s) (weights, edge sharp, etc.) from selected meshes to active one"));
}
return NULL;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index d517d68f1fc..f478f5004d4 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -65,7 +65,6 @@ void OBJECT_OT_track_set(struct wmOperatorType *ot);
void OBJECT_OT_track_clear(struct wmOperatorType *ot);
void OBJECT_OT_make_local(struct wmOperatorType *ot);
void OBJECT_OT_make_override_library(struct wmOperatorType *ot);
-void OBJECT_OT_convert_proxy_to_override(struct wmOperatorType *ot);
void OBJECT_OT_make_single_user(struct wmOperatorType *ot);
void OBJECT_OT_make_links_scene(struct wmOperatorType *ot);
void OBJECT_OT_make_links_data(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 4ac2a9dca62..775fac96d57 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -84,6 +84,8 @@
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_query.h"
+#include "BLT_translation.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -1521,7 +1523,7 @@ static char *modifier_apply_as_shapekey_get_description(struct bContext *UNUSED(
bool keep = RNA_boolean_get(values, "keep_modifier");
if (keep) {
- return BLI_strdup("Apply modifier as a new shapekey and keep it in the stack");
+ return BLI_strdup(TIP_("Apply modifier as a new shapekey and keep it in the stack"));
}
return NULL;
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index b171da42522..03a36006fea 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -75,7 +75,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_track_clear);
WM_operatortype_append(OBJECT_OT_make_local);
WM_operatortype_append(OBJECT_OT_make_override_library);
- WM_operatortype_append(OBJECT_OT_convert_proxy_to_override);
WM_operatortype_append(OBJECT_OT_make_single_user);
WM_operatortype_append(OBJECT_OT_make_links_scene);
WM_operatortype_append(OBJECT_OT_make_links_data);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index a6eb35d49b9..57a0fe0a39d 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2334,7 +2334,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
const bool success = BKE_lib_override_library_create(
- bmain, scene, view_layer, id_root, &obact->id, NULL);
+ bmain, scene, view_layer, NULL, id_root, &obact->id, NULL);
/* Remove the instance empty from this scene, the items now have an overridden collection
* instead. */
@@ -2419,63 +2419,6 @@ void OBJECT_OT_make_override_library(wmOperatorType *ot)
ot->prop = prop;
}
-static bool convert_proxy_to_override_poll(bContext *C)
-{
- Object *obact = CTX_data_active_object(C);
-
- return obact != NULL && obact->proxy != NULL;
-}
-
-static int convert_proxy_to_override_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-
- Object *ob_proxy = CTX_data_active_object(C);
- Object *ob_proxy_group = ob_proxy->proxy_group;
- const bool is_override_instancing_object = ob_proxy_group != NULL;
-
- const bool success = BKE_lib_override_library_proxy_convert(bmain, scene, view_layer, ob_proxy);
-
- if (!success) {
- BKE_reportf(
- op->reports,
- RPT_ERROR_INVALID_INPUT,
- "Could not create a library override from proxy '%s' (might use already local data?)",
- ob_proxy->id.name + 2);
- return OPERATOR_CANCELLED;
- }
-
- /* Remove the instance empty from this scene, the items now have an overridden collection
- * instead. */
- if (is_override_instancing_object) {
- ED_object_base_free_and_unlink(bmain, scene, ob_proxy_group);
- }
-
- DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_WINDOW, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_convert_proxy_to_override(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Convert Proxy to Override";
- ot->description = "Convert a proxy to a local library override";
- ot->idname = "OBJECT_OT_convert_proxy_to_override";
-
- /* api callbacks */
- ot->exec = convert_proxy_to_override_exec;
- ot->poll = convert_proxy_to_override_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
/** \} */
/* ------------------------------------------------------------------- */
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 3e74aaeeb10..ed0f7b2fad0 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -39,6 +39,7 @@
#include "BLI_alloca.h"
#include "BLI_array.h"
+#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
@@ -63,6 +64,8 @@
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_query.h"
+#include "BLT_translation.h"
+
#include "DNA_armature_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -2464,17 +2467,14 @@ void ED_vgroup_mirror(Object *ob,
sel = sel_mirr = true;
}
- /* tag verts we have used */
- for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
- mv->flag &= ~ME_VERT_TMP_TAG;
- }
+ BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__);
for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
- if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
+ if (!BLI_BITMAP_TEST(vert_tag, vidx)) {
if ((vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology)) != -1) {
if (vidx != vidx_mirr) {
mv_mirr = &me->mvert[vidx_mirr];
- if ((mv_mirr->flag & ME_VERT_TMP_TAG) == 0) {
+ if (!BLI_BITMAP_TEST(vert_tag, vidx_mirr)) {
if (use_vert_sel) {
sel = mv->flag & SELECT;
@@ -2489,8 +2489,8 @@ void ED_vgroup_mirror(Object *ob,
totmirr++;
}
- mv->flag |= ME_VERT_TMP_TAG;
- mv_mirr->flag |= ME_VERT_TMP_TAG;
+ BLI_BITMAP_ENABLE(vert_tag, vidx);
+ BLI_BITMAP_ENABLE(vert_tag, vidx_mirr);
}
}
}
@@ -2499,6 +2499,8 @@ void ED_vgroup_mirror(Object *ob,
}
}
}
+
+ MEM_freeN(vert_tag);
}
}
else if (ob->type == OB_LATTICE) {
@@ -3427,16 +3429,16 @@ static char *vertex_group_lock_description(struct bContext *UNUSED(C),
switch (action) {
case VGROUP_LOCK:
- action_str = "Lock";
+ action_str = TIP_("Lock");
break;
case VGROUP_UNLOCK:
- action_str = "Unlock";
+ action_str = TIP_("Unlock");
break;
case VGROUP_TOGGLE:
- action_str = "Toggle locks of";
+ action_str = TIP_("Toggle locks of");
break;
case VGROUP_INVERT:
- action_str = "Invert locks of";
+ action_str = TIP_("Invert locks of");
break;
default:
return NULL;
@@ -3444,34 +3446,34 @@ static char *vertex_group_lock_description(struct bContext *UNUSED(C),
switch (mask) {
case VGROUP_MASK_ALL:
- target_str = "all";
+ target_str = TIP_("all");
break;
case VGROUP_MASK_SELECTED:
- target_str = "selected";
+ target_str = TIP_("selected");
break;
case VGROUP_MASK_UNSELECTED:
- target_str = "unselected";
+ target_str = TIP_("unselected");
break;
case VGROUP_MASK_INVERT_UNSELECTED:
switch (action) {
case VGROUP_INVERT:
- target_str = "selected";
+ target_str = TIP_("selected");
break;
case VGROUP_LOCK:
- target_str = "selected and unlock unselected";
+ target_str = TIP_("selected and unlock unselected");
break;
case VGROUP_UNLOCK:
- target_str = "selected and lock unselected";
+ target_str = TIP_("selected and lock unselected");
break;
default:
- target_str = "all and invert unselected";
+ target_str = TIP_("all and invert unselected");
}
break;
default:
return NULL;
}
- return BLI_sprintfN("%s %s vertex groups of the active object", action_str, target_str);
+ return BLI_sprintfN(TIP_("%s %s vertex groups of the active object"), action_str, target_str);
}
void OBJECT_OT_vertex_group_lock(wmOperatorType *ot)
diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt
index a607663763e..7c32a2dcf1d 100644
--- a/source/blender/editors/physics/CMakeLists.txt
+++ b/source/blender/editors/physics/CMakeLists.txt
@@ -60,10 +60,6 @@ if(WITH_MOD_FLUID)
add_definitions(-DWITH_FLUID)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_BULLET)
list(APPEND INC
../../../../intern/rigidbody
diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt
index 1f867c6f1f7..934badd3b6f 100644
--- a/source/blender/editors/render/CMakeLists.txt
+++ b/source/blender/editors/render/CMakeLists.txt
@@ -67,8 +67,4 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_render "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/render/render_internal.cc b/source/blender/editors/render/render_internal.cc
index 8e9a052381c..d04e45e4ccb 100644
--- a/source/blender/editors/render/render_internal.cc
+++ b/source/blender/editors/render/render_internal.cc
@@ -90,7 +90,7 @@ struct RenderJob {
Scene *scene;
ViewLayer *single_layer;
Scene *current_scene;
- /* TODO(sergey): Should not be needed once engine will have own
+ /* TODO(sergey): Should not be needed once engine will have its own
* depsgraph and copy-on-write will be implemented.
*/
Depsgraph *depsgraph;
@@ -981,7 +981,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->scene = scene;
rj->current_scene = rj->scene;
rj->single_layer = single_layer;
- /* TODO(sergey): Render engine should be using own depsgraph.
+ /* TODO(sergey): Render engine should be using its own depsgraph.
*
* NOTE: Currently is only used by ED_update_for_newframe() at the end of the render, so no
* need to ensure evaluation here. */
diff --git a/source/blender/editors/render/render_opengl.cc b/source/blender/editors/render/render_opengl.cc
index 8bd0244c899..c4ce8bac126 100644
--- a/source/blender/editors/render/render_opengl.cc
+++ b/source/blender/editors/render/render_opengl.cc
@@ -72,8 +72,11 @@
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+
#include "RE_pipeline.h"
+#include "BLT_translation.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -1326,12 +1329,12 @@ static char *screen_opengl_render_description(struct bContext *UNUSED(C),
}
if (RNA_boolean_get(ptr, "render_keyed_only")) {
- return BLI_strdup(
+ return BLI_strdup(TIP_(
"Render the viewport for the animation range of this scene, but only render keyframes of "
- "selected objects");
+ "selected objects"));
}
- return BLI_strdup("Render the viewport for the animation range of this scene");
+ return BLI_strdup(TIP_("Render the viewport for the animation range of this scene"));
}
void RENDER_OT_opengl(wmOperatorType *ot)
diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc
index df078bbd890..c1c75e485f7 100644
--- a/source/blender/editors/render/render_preview.cc
+++ b/source/blender/editors/render/render_preview.cc
@@ -767,7 +767,7 @@ struct ObjectPreviewData {
/* The main for the preview, not of the current file. */
Main *pr_main;
/* Copy of the object to create the preview for. The copy is for thread safety (and to insert
- * it into an own main). */
+ * it into its own main). */
Object *object;
/* Current frame. */
int cfra;
diff --git a/source/blender/editors/scene/CMakeLists.txt b/source/blender/editors/scene/CMakeLists.txt
index cd59f06c6e3..ce0c2062766 100644
--- a/source/blender/editors/scene/CMakeLists.txt
+++ b/source/blender/editors/scene/CMakeLists.txt
@@ -39,8 +39,5 @@ set(LIB
bf_blenlib
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
blender_add_lib(bf_editor_scene "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt
index d194d0cdbb6..7c5ae4dcd5e 100644
--- a/source/blender/editors/screen/CMakeLists.txt
+++ b/source/blender/editors/screen/CMakeLists.txt
@@ -57,9 +57,5 @@ set(LIB
bf_editor_space_sequencer
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_screen "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 152a5c87c78..4af965621e3 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -2608,7 +2608,7 @@ typedef struct RegionMoveData {
ARegion *region;
ScrArea *area;
int bigger, smaller, origval;
- int origx, origy;
+ int orig_xy[2];
int maxsize;
AZEdge edge;
@@ -2716,8 +2716,7 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event
}
rmd->area = sad->sa1;
rmd->edge = az->edge;
- rmd->origx = event->xy[0];
- rmd->origy = event->xy[1];
+ copy_v2_v2_int(rmd->orig_xy, event->xy);
rmd->maxsize = area_max_regionsize(rmd->area, rmd->region, rmd->edge);
/* if not set we do now, otherwise it uses type */
@@ -2804,7 +2803,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
(BLI_rcti_size_x(&rmd->region->v2d.mask) + 1);
const int snap_size_threshold = (U.widget_unit * 2) / aspect;
if (ELEM(rmd->edge, AE_LEFT_TO_TOPRIGHT, AE_RIGHT_TO_TOPLEFT)) {
- delta = event->xy[0] - rmd->origx;
+ delta = event->xy[0] - rmd->orig_xy[0];
if (rmd->edge == AE_LEFT_TO_TOPRIGHT) {
delta = -delta;
}
@@ -2837,7 +2836,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
else {
- delta = event->xy[1] - rmd->origy;
+ delta = event->xy[1] - rmd->orig_xy[1];
if (rmd->edge == AE_BOTTOM_TO_TOPLEFT) {
delta = -delta;
}
@@ -2879,7 +2878,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
case LEFTMOUSE:
if (event->val == KM_RELEASE) {
- if (len_manhattan_v2v2_int(event->xy, &rmd->origx) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) {
+ if (len_manhattan_v2v2_int(event->xy, rmd->orig_xy) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) {
if (rmd->region->flag & RGN_FLAG_HIDDEN) {
region_scale_toggle_hidden(C, rmd);
}
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index b15b6784d34..907080626e0 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -90,9 +90,5 @@ set(LIB
bf_blenlib
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_sculpt_paint "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index ca012f20f01..f05cd4c3d5f 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -1730,17 +1730,12 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
normalize_v3(no);
}
else {
-#if 1
/* In case the normalizing per pixel isn't optimal,
* we could cache or access from evaluated mesh. */
normal_tri_v3(no,
ps->mvert_eval[lt_vtri[0]].co,
ps->mvert_eval[lt_vtri[1]].co,
ps->mvert_eval[lt_vtri[2]].co);
-#else
- /* Don't use because some modifiers don't have normal data (subsurf for eg). */
- copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, tri_index, CD_NORMAL));
-#endif
}
if (UNLIKELY(ps->is_flip_object)) {
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
index 46c2acf112a..1234a56853c 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -430,7 +430,7 @@ void PAINT_OT_weight_sample_group(wmOperatorType *ot)
/* Group to use (dynamic enum). */
prop = RNA_def_enum(
- ot->srna, "group", DummyRNA_DEFAULT_items, 0, "Group", "Vertex group to set as active");
+ ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "Vertex group to set as active");
RNA_def_enum_funcs(prop, weight_paint_sample_enum_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 184d715a347..ba4ba04d548 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -658,7 +658,7 @@ static char *actkeys_paste_description(bContext *UNUSED(C),
{
/* Custom description if the 'flipped' option is used. */
if (RNA_boolean_get(ptr, "flipped")) {
- return BLI_strdup("Paste keyframes from mirrored bones if they exist");
+ return BLI_strdup(TIP_("Paste keyframes from mirrored bones if they exist"));
}
/* Use the default description in the other cases. */
diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt
index b5f6874fcfc..e2b2579c256 100644
--- a/source/blender/editors/space_buttons/CMakeLists.txt
+++ b/source/blender/editors/space_buttons/CMakeLists.txt
@@ -40,10 +40,6 @@ set(SRC
set(LIB
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt
index db881dafa6b..8f1a2c3c81e 100644
--- a/source/blender/editors/space_clip/CMakeLists.txt
+++ b/source/blender/editors/space_clip/CMakeLists.txt
@@ -68,11 +68,6 @@ set(LIB
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
-
blender_add_lib(bf_editor_space_clip "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# Needed so we can use dna_type_offsets.h for defaults initialization.
diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt
index cbeb2e6f529..1df0c9c4409 100644
--- a/source/blender/editors/space_file/CMakeLists.txt
+++ b/source/blender/editors/space_file/CMakeLists.txt
@@ -92,10 +92,6 @@ if(WITH_IMAGE_HDR)
add_definitions(-DWITH_HDR)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 2d31e8030a4..044d7aba88f 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -524,7 +524,7 @@ static int compare_apply_inverted(int val, const struct FileSortData *sort_data)
* 2) If not possible (file names match) and both represent local IDs, sort by ID-type.
* 3) If not possible and only one is a local ID, place files representing local IDs first.
*
- * TODO (not actually implemented, but should be):
+ * TODO: (not actually implemented, but should be):
* 4) If no file represents a local ID, sort by file path, so that files higher up the file system
* hierarchy are placed first.
*/
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index 14f596ae7bf..0a69d0f9b39 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -745,14 +745,17 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
N_("Fonts"),
ICON_FILE_FONT,
FS_INSERT_LAST);
+ fsmenu_add_windows_folder(fsmenu,
+ FS_CATEGORY_SYSTEM_BOOKMARKS,
+ &FOLDERID_SkyDrive,
+ N_("OneDrive"),
+ ICON_URL,
+ FS_INSERT_LAST);
/* These items are just put in path cache for thumbnail views and if bookmarked. */
fsmenu_add_windows_folder(
fsmenu, FS_CATEGORY_OTHER, &FOLDERID_UserProfiles, NULL, ICON_COMMUNITY, FS_INSERT_LAST);
-
- fsmenu_add_windows_folder(
- fsmenu, FS_CATEGORY_OTHER, &FOLDERID_SkyDrive, NULL, ICON_URL, FS_INSERT_LAST);
}
}
#elif defined(__APPLE__)
diff --git a/source/blender/editors/space_graph/CMakeLists.txt b/source/blender/editors/space_graph/CMakeLists.txt
index 2a795dd954c..2e6e6971ce9 100644
--- a/source/blender/editors/space_graph/CMakeLists.txt
+++ b/source/blender/editors/space_graph/CMakeLists.txt
@@ -61,9 +61,5 @@ if(WITH_AUDASPACE)
add_definitions(-DWITH_AUDASPACE)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_space_graph "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 9675901ead3..63de7fb570e 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -586,7 +586,7 @@ static char *graphkeys_paste_description(bContext *UNUSED(C),
{
/* Custom description if the 'flipped' option is used. */
if (RNA_boolean_get(ptr, "flipped")) {
- return BLI_strdup("Paste keyframes from mirrored bones if they exist");
+ return BLI_strdup(TIP_("Paste keyframes from mirrored bones if they exist"));
}
/* Use the default description in the other cases. */
diff --git a/source/blender/editors/space_graph/graph_slider_ops.c b/source/blender/editors/space_graph/graph_slider_ops.c
index 4b8c983a761..cfaea33605a 100644
--- a/source/blender/editors/space_graph/graph_slider_ops.c
+++ b/source/blender/editors/space_graph/graph_slider_ops.c
@@ -483,7 +483,7 @@ static char *decimate_desc(bContext *UNUSED(C), wmOperatorType *UNUSED(op), Poin
if (RNA_enum_get(ptr, "mode") == DECIM_ERROR) {
return BLI_strdup(
- "Decimate F-Curves by specifying how much it can deviate from the original curve");
+ TIP_("Decimate F-Curves by specifying how much they can deviate from the original curve"));
}
/* Use default description. */
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt
index 7a1bab0ef14..25d0e02ecc0 100644
--- a/source/blender/editors/space_image/CMakeLists.txt
+++ b/source/blender/editors/space_image/CMakeLists.txt
@@ -53,10 +53,6 @@ set(LIB
bf_editor_uvedit
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_OPENIMAGEIO)
add_definitions(-DWITH_OPENIMAGEIO)
endif()
diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c
index e81f3b6a490..73993606a14 100644
--- a/source/blender/editors/space_image/image_undo.c
+++ b/source/blender/editors/space_image/image_undo.c
@@ -1000,7 +1000,7 @@ void ED_image_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = image_undosys_foreach_ID_ref;
- /* NOTE this is actually a confusing case, since it expects a valid context, but only in a
+ /* NOTE: this is actually a confusing case, since it expects a valid context, but only in a
* specific case, see `image_undosys_step_encode` code. We cannot specify
* `UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE` though, as it can be called with a NULL context by
* current code. */
diff --git a/source/blender/editors/space_info/CMakeLists.txt b/source/blender/editors/space_info/CMakeLists.txt
index 144b21fb9b8..fb17a6c9709 100644
--- a/source/blender/editors/space_info/CMakeLists.txt
+++ b/source/blender/editors/space_info/CMakeLists.txt
@@ -48,9 +48,5 @@ set(SRC
set(LIB
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_space_info "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_nla/CMakeLists.txt b/source/blender/editors/space_nla/CMakeLists.txt
index 9a94d28c604..5326f1cce2b 100644
--- a/source/blender/editors/space_nla/CMakeLists.txt
+++ b/source/blender/editors/space_nla/CMakeLists.txt
@@ -47,9 +47,5 @@ set(LIB
bf_blenlib
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_space_nla "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index 41d6388c947..15e0d04c8fa 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -63,10 +63,6 @@ set(LIB
bf_editor_screen
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_COMPOSITOR)
add_definitions(-DWITH_COMPOSITOR)
endif()
diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh
index c161fc70402..f6397baf9f2 100644
--- a/source/blender/editors/space_node/node_intern.hh
+++ b/source/blender/editors/space_node/node_intern.hh
@@ -109,18 +109,28 @@ enum NodeResizeDirection {
};
ENUM_OPERATORS(NodeResizeDirection, NODE_RESIZE_LEFT);
+/* Nodes draw without dpi - the view zoom is flexible. */
+#define HIDDEN_RAD (0.75f * U.widget_unit)
+#define BASIS_RAD (0.2f * U.widget_unit)
+#define NODE_DYS (U.widget_unit / 2)
+#define NODE_DY U.widget_unit
+#define NODE_SOCKDY (0.1f * U.widget_unit)
+#define NODE_WIDTH(node) (node.width * UI_DPI_FAC)
+#define NODE_HEIGHT(node) (node.height * UI_DPI_FAC)
+#define NODE_MARGIN_X (1.2f * U.widget_unit)
+#define NODE_SOCKSIZE (0.25f * U.widget_unit)
+#define NODE_MULTI_INPUT_LINK_GAP (0.25f * U.widget_unit)
+#define NODE_RESIZE_MARGIN (0.20f * U.widget_unit)
+#define NODE_LINK_RESOL 12
+
+/* space_node.cc */
+
/**
* Transform between View2Ds in the tree path.
*/
float2 space_node_group_offset(const SpaceNode &snode);
-float node_socket_calculate_height(const bNodeSocket &socket);
-float2 node_link_calculate_multi_input_position(const float2 &socket_position,
- int index,
- int total_inputs);
-
int node_get_resize_cursor(NodeResizeDirection directions);
-NodeResizeDirection node_get_resize_direction(const bNode *node, int x, int y);
/**
* Usual convention here would be #node_socket_get_color(),
* but that's already used (for setting a color property socket).
@@ -130,6 +140,9 @@ void node_socket_color_get(const bContext &C,
PointerRNA &node_ptr,
const bNodeSocket &sock,
float r_color[4]);
+
+/* node_draw.cc */
+
void node_draw_space(const bContext &C, ARegion &region);
/**
@@ -144,9 +157,13 @@ float2 node_to_view(const bNode &node, const float2 &co);
void node_to_updated_rect(const bNode &node, rctf &r_rect);
float2 node_from_view(const bNode &node, const float2 &co);
+/* node_ops.cc */
+
void node_operatortypes();
void node_keymap(wmKeyConfig *keyconf);
+/* node_select.cc */
+
void node_deselect_all(SpaceNode &snode);
void node_socket_select(bNode *node, bNodeSocket &sock);
void node_socket_deselect(bNode *node, bNodeSocket &sock, bool deselect_node);
@@ -165,6 +182,8 @@ void NODE_OT_select_grouped(wmOperatorType *ot);
void NODE_OT_select_same_type_step(wmOperatorType *ot);
void NODE_OT_find_node(wmOperatorType *ot);
+/* node_view.cc */
+
bool space_node_view_flag(
bContext &C, SpaceNode &snode, ARegion &region, int node_flag, int smooth_viewtx);
@@ -177,6 +196,10 @@ void NODE_OT_backimage_zoom(wmOperatorType *ot);
void NODE_OT_backimage_fit(wmOperatorType *ot);
void NODE_OT_backimage_sample(wmOperatorType *ot);
+/* drawnode.cc */
+
+NodeResizeDirection node_get_resize_direction(const bNode *node, int x, int y);
+
void nodelink_batch_start(SpaceNode &snode);
void nodelink_batch_end(SpaceNode &snode);
@@ -215,7 +238,7 @@ void draw_nodespace_back_pix(const bContext &C,
SpaceNode &snode,
bNodeInstanceKey parent_key);
-void node_select_all(ListBase *lb, int action);
+/* node_add.cc */
/**
* XXX Does some additional initialization on top of #nodeAddNode
@@ -232,6 +255,8 @@ void NODE_OT_add_file(wmOperatorType *ot);
void NODE_OT_add_mask(wmOperatorType *ot);
void NODE_OT_new_node_tree(wmOperatorType *ot);
+/* node_group.cc */
+
const char *node_group_idname(bContext *C);
void NODE_OT_group_make(wmOperatorType *ot);
void NODE_OT_group_insert(wmOperatorType *ot);
@@ -239,6 +264,8 @@ void NODE_OT_group_ungroup(wmOperatorType *ot);
void NODE_OT_group_separate(wmOperatorType *ot);
void NODE_OT_group_edit(wmOperatorType *ot);
+/* node_relationships.cc */
+
void sort_multi_input_socket_links(SpaceNode &snode,
bNode &node,
bNodeLink *drag_link,
@@ -259,6 +286,16 @@ void NODE_OT_link_viewer(wmOperatorType *ot);
void NODE_OT_insert_offset(wmOperatorType *ot);
+/* node_edit.cc */
+
+float2 node_link_calculate_multi_input_position(const float2 &socket_position,
+ int index,
+ int total_inputs);
+
+void node_select_all(ListBase *lb, int action);
+
+float node_socket_calculate_height(const bNodeSocket &socket);
+
void snode_set_context(const bContext &C);
bool composite_node_active(bContext *C);
@@ -314,13 +351,17 @@ void NODE_OT_shader_script_update(wmOperatorType *ot);
void NODE_OT_viewer_border(wmOperatorType *ot);
void NODE_OT_clear_viewer_border(wmOperatorType *ot);
+void NODE_OT_cryptomatte_layer_add(wmOperatorType *ot);
+void NODE_OT_cryptomatte_layer_remove(wmOperatorType *ot);
+
+/* node_gizmo.cc */
+
void NODE_GGT_backdrop_transform(wmGizmoGroupType *gzgt);
void NODE_GGT_backdrop_crop(wmGizmoGroupType *gzgt);
void NODE_GGT_backdrop_sun_beams(wmGizmoGroupType *gzgt);
void NODE_GGT_backdrop_corner_pin(wmGizmoGroupType *gzgt);
-void NODE_OT_cryptomatte_layer_add(wmOperatorType *ot);
-void NODE_OT_cryptomatte_layer_remove(wmOperatorType *ot);
+/* node_geometry_attribute_search.cc */
void node_geometry_add_attribute_search_button(const bContext &C,
const bNodeTree &node_tree,
@@ -328,22 +369,12 @@ void node_geometry_add_attribute_search_button(const bContext &C,
PointerRNA &socket_ptr,
uiLayout &layout);
-/* Nodes draw without dpi - the view zoom is flexible. */
-#define HIDDEN_RAD (0.75f * U.widget_unit)
-#define BASIS_RAD (0.2f * U.widget_unit)
-#define NODE_DYS (U.widget_unit / 2)
-#define NODE_DY U.widget_unit
-#define NODE_SOCKDY (0.1f * U.widget_unit)
-#define NODE_WIDTH(node) (node.width * UI_DPI_FAC)
-#define NODE_HEIGHT(node) (node.height * UI_DPI_FAC)
-#define NODE_MARGIN_X (1.2f * U.widget_unit)
-#define NODE_SOCKSIZE (0.25f * U.widget_unit)
-#define NODE_MULTI_INPUT_LINK_GAP (0.25f * U.widget_unit)
-#define NODE_RESIZE_MARGIN (0.20f * U.widget_unit)
-#define NODE_LINK_RESOL 12
+/* node_context_path.c */
Vector<ui::ContextPathItem> context_path_for_space_node(const bContext &C);
+/* link_drag_search.cc */
+
void invoke_node_link_drag_add_menu(bContext &C,
bNode &node,
bNodeSocket &socket,
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index bc6db978a4f..d97f48bcb68 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -95,9 +95,5 @@ set(LIB
bf_editor_undo
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_space_outliner "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc
index 5fd7559370f..259fdd4e009 100644
--- a/source/blender/editors/space_outliner/outliner_draw.cc
+++ b/source/blender/editors/space_outliner/outliner_draw.cc
@@ -2480,9 +2480,6 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case TSE_POSE_CHANNEL:
data.icon = ICON_BONE_DATA;
break;
- case TSE_PROXY:
- data.icon = ICON_GHOST_ENABLED;
- break;
case TSE_R_LAYER_BASE:
data.icon = ICON_RENDERLAYERS;
break;
diff --git a/source/blender/editors/space_outliner/outliner_intern.hh b/source/blender/editors/space_outliner/outliner_intern.hh
index 9db1d73dc76..bd288241a63 100644
--- a/source/blender/editors/space_outliner/outliner_intern.hh
+++ b/source/blender/editors/space_outliner/outliner_intern.hh
@@ -57,10 +57,12 @@ class AbstractTreeDisplay;
class AbstractTreeElement;
} // namespace blender::ed::outliner
+namespace outliner = blender::ed::outliner;
+
struct SpaceOutliner_Runtime {
/** Object to create and manage the tree for a specific display type (View Layers, Scenes,
* Blender File, etc.). */
- std::unique_ptr<blender::ed::outliner::AbstractTreeDisplay> tree_display;
+ std::unique_ptr<outliner::AbstractTreeDisplay> tree_display;
/** Pointers to tree-store elements, grouped by `(id, type, nr)`
* in hash-table for faster searching. */
@@ -93,11 +95,12 @@ typedef struct TreeElement {
struct TreeElement *next, *prev, *parent;
/**
- * Handle to the new C++ object (a derived type of base #AbstractTreeElement) that should replace
- * #TreeElement. Step by step, data should be moved to it and operations based on the type should
- * become virtual methods of the class hierarchy.
+ * The new inheritance based representation of the element (a derived type of base
+ * #AbstractTreeElement) that should eventually replace #TreeElement. Step by step, data should
+ * be moved to it and operations based on the type should become virtual methods of the class
+ * hierarchy.
*/
- std::unique_ptr<blender::ed::outliner::AbstractTreeElement> type;
+ std::unique_ptr<outliner::AbstractTreeElement> abstract_element;
ListBase subtree;
int xs, ys; /* Do selection. */
@@ -700,7 +703,7 @@ template<typename TreeElementT> TreeElementT *tree_element_cast(const TreeElemen
{
static_assert(std::is_base_of_v<AbstractTreeElement, TreeElementT>,
"Requested tree-element type must be an AbstractTreeElement");
- return dynamic_cast<TreeElementT *>(te->type.get());
+ return dynamic_cast<TreeElementT *>(te->abstract_element.get());
}
} // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc
index 03fc4c20fe5..3b8c284cd65 100644
--- a/source/blender/editors/space_outliner/outliner_tools.cc
+++ b/source/blender/editors/space_outliner/outliner_tools.cc
@@ -764,38 +764,6 @@ static void id_local_fn(bContext *C,
}
}
-static void object_proxy_to_override_convert_fn(bContext *C,
- ReportList *reports,
- Scene *UNUSED(scene),
- TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep),
- TreeStoreElem *tselem,
- void *UNUSED(user_data))
-{
- BLI_assert(TSE_IS_REAL_ID(tselem));
- ID *id_proxy = tselem->id;
- BLI_assert(GS(id_proxy->name) == ID_OB);
- Object *ob_proxy = (Object *)id_proxy;
- Scene *scene = CTX_data_scene(C);
-
- if (ob_proxy->proxy == nullptr) {
- return;
- }
-
- if (!BKE_lib_override_library_proxy_convert(
- CTX_data_main(C), scene, CTX_data_view_layer(C), ob_proxy)) {
- BKE_reportf(
- reports,
- RPT_ERROR_INVALID_INPUT,
- "Could not create a library override from proxy '%s' (might use already local data?)",
- ob_proxy->id.name + 2);
- return;
- }
-
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_WINDOW, nullptr);
-}
-
struct OutlinerLibOverrideData {
bool do_hierarchy;
/**
@@ -874,8 +842,13 @@ static void id_override_library_create_fn(bContext *C,
te->store_elem->id->tag |= LIB_TAG_DOIT;
}
- success = BKE_lib_override_library_create(
- bmain, CTX_data_scene(C), CTX_data_view_layer(C), id_root, id_reference, nullptr);
+ success = BKE_lib_override_library_create(bmain,
+ CTX_data_scene(C),
+ CTX_data_view_layer(C),
+ nullptr,
+ id_root,
+ id_reference,
+ nullptr);
}
else if (ID_IS_OVERRIDABLE_LIBRARY(id_root)) {
success = BKE_lib_override_library_create_from_id(bmain, id_root, true) != nullptr;
@@ -1532,7 +1505,6 @@ enum {
OL_OP_SELECT_HIERARCHY,
OL_OP_REMAP,
OL_OP_RENAME,
- OL_OP_PROXY_TO_OVERRIDE_CONVERT,
};
static const EnumPropertyItem prop_object_op_types[] = {
@@ -1545,11 +1517,6 @@ static const EnumPropertyItem prop_object_op_types[] = {
"Remap Users",
"Make all users of selected data-blocks to use instead a new chosen one"},
{OL_OP_RENAME, "RENAME", 0, "Rename", ""},
- {OL_OP_PROXY_TO_OVERRIDE_CONVERT,
- "OBJECT_PROXY_TO_OVERRIDE",
- 0,
- "Convert Proxy to Override",
- "Convert a Proxy object to a full library override, including all its dependencies"},
{0, nullptr, 0, nullptr, nullptr},
};
@@ -1614,15 +1581,6 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
C, op->reports, scene, space_outliner, &space_outliner->tree, item_rename_fn);
str = "Rename Object";
}
- else if (event == OL_OP_PROXY_TO_OVERRIDE_CONVERT) {
- outliner_do_object_operation(C,
- op->reports,
- scene,
- space_outliner,
- &space_outliner->tree,
- object_proxy_to_override_convert_fn);
- str = "Convert Proxy to Override";
- }
else {
BLI_assert(0);
return OPERATOR_CANCELLED;
@@ -1794,7 +1752,6 @@ enum eOutlinerIdOpTypes {
OUTLINER_IDOP_LOCAL,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY,
- OUTLINER_IDOP_OVERRIDE_LIBRARY_PROXY_CONVERT,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY,
@@ -1836,11 +1793,6 @@ static const EnumPropertyItem prop_id_op_types[] = {
0,
"Make Library Override Hierarchy",
"Make a local override of this linked data-block, and its hierarchy of dependencies"},
- {OUTLINER_IDOP_OVERRIDE_LIBRARY_PROXY_CONVERT,
- "OVERRIDE_LIBRARY_PROXY_CONVERT",
- 0,
- "Convert Proxy to Override",
- "Convert a Proxy object to a full library override, including all its dependencies"},
{OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
"OVERRIDE_LIBRARY_RESET",
0,
@@ -1913,16 +1865,6 @@ static bool outliner_id_operation_item_poll(bContext *C,
return true;
}
return false;
- case OUTLINER_IDOP_OVERRIDE_LIBRARY_PROXY_CONVERT: {
- if (GS(tselem->id->name) == ID_OB) {
- Object *ob = (Object *)tselem->id;
-
- if ((ob != nullptr) && (ob->proxy != nullptr)) {
- return true;
- }
- }
- return false;
- }
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY:
@@ -2099,16 +2041,6 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
ED_undo_push(C, "Overridden Data Hierarchy");
break;
}
- case OUTLINER_IDOP_OVERRIDE_LIBRARY_PROXY_CONVERT: {
- outliner_do_object_operation(C,
- op->reports,
- scene,
- space_outliner,
- &space_outliner->tree,
- object_proxy_to_override_convert_fn);
- ED_undo_push(C, "Convert Proxy to Override");
- break;
- }
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: {
OutlinerLibOverrideData override_data{};
outliner_do_libdata_operation(C,
diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc
index eb885eba20d..4e16fe64988 100644
--- a/source/blender/editors/space_outliner/outliner_tree.cc
+++ b/source/blender/editors/space_outliner/outliner_tree.cc
@@ -217,7 +217,7 @@ void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree)
if (element->flag & TE_FREE_NAME) {
MEM_freeN((void *)element->name);
}
- element->type = nullptr;
+ element->abstract_element = nullptr;
MEM_delete(element);
}
@@ -302,10 +302,6 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
/* FIXME: add a special type for this. */
outliner_add_element(space_outliner, &te->subtree, ob->poselib, te, TSE_SOME_ID, 0);
- if (ob->proxy && !ID_IS_LINKED(ob)) {
- outliner_add_element(space_outliner, &te->subtree, ob->proxy, te, TSE_PROXY, 0);
- }
-
outliner_add_element(space_outliner, &te->subtree, ob->data, te, TSE_SOME_ID, 0);
if (ob->pose) {
@@ -860,10 +856,10 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
te->parent = parent;
te->index = index; /* For data arrays. */
- /* New C++ based type handle. Only some support this, eventually this should replace
- * `TreeElement` entirely. */
- te->type = AbstractTreeElement::createFromType(type, *te, idv);
- if (te->type) {
+ /* New inheritance based element representation. Not all element types support this yet,
+ * eventually it should replace #TreeElement entirely. */
+ te->abstract_element = AbstractTreeElement::createFromType(type, *te, idv);
+ if (te->abstract_element) {
/* Element types ported to the new design are expected to have their name set at this point! */
BLI_assert(te->name != nullptr);
}
@@ -887,12 +883,12 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
/* pass */
}
else if (type == TSE_SOME_ID) {
- if (!te->type) {
+ if (!te->abstract_element) {
BLI_assert_msg(0, "Expected this ID type to be ported to new Outliner tree-element design");
}
}
else if (ELEM(type, TSE_LIBRARY_OVERRIDE_BASE, TSE_LIBRARY_OVERRIDE)) {
- if (!te->type) {
+ if (!te->abstract_element) {
BLI_assert_msg(0,
"Expected override types to be ported to new Outliner tree-element design");
}
@@ -903,20 +899,20 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
/* The new type design sets the name already, don't override that here. We need to figure out
* how to deal with the idcode for non-TSE_SOME_ID types still. Some rely on it... */
- if (!te->type) {
+ if (!te->abstract_element) {
te->name = id->name + 2; /* Default, can be overridden by Library or non-ID data. */
}
te->idcode = GS(id->name);
}
- if (te->type && te->type->isExpandValid()) {
- tree_element_expand(*te->type, *space_outliner);
+ if (te->abstract_element && te->abstract_element->isExpandValid()) {
+ tree_element_expand(*te->abstract_element, *space_outliner);
}
else if (type == TSE_SOME_ID) {
/* ID types not (fully) ported to new design yet. */
- if (te->type->expandPoll(*space_outliner)) {
+ if (te->abstract_element->expandPoll(*space_outliner)) {
outliner_add_id_contents(space_outliner, te, tselem, id);
- te->type->postExpand(*space_outliner);
+ te->abstract_element->postExpand(*space_outliner);
}
}
else if (ELEM(type,
diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt
index bf8cf89699d..d93dc0ac0c0 100644
--- a/source/blender/editors/space_sequencer/CMakeLists.txt
+++ b/source/blender/editors/space_sequencer/CMakeLists.txt
@@ -70,9 +70,5 @@ if(WITH_AUDASPACE)
)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_space_sequencer "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
index 18f383d45fb..357b3e0a8b4 100644
--- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
+++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
@@ -554,7 +554,7 @@ static void spreadsheet_footer_region_draw(const bContext *C, ARegion *region)
UI_LAYOUT_HEADER,
UI_HEADER_OFFSET,
region->winy - (region->winy - UI_UNIT_Y) / 2.0f,
- region->sizex,
+ region->winx,
1,
0,
style);
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
index f4b5ff819ed..d9837b7c1a6 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
@@ -127,6 +127,28 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
}
+ if (data.type().is<int8_t>()) {
+ const int8_t value = data.get<int8_t>(real_index);
+ const std::string value_str = std::to_string(value);
+ uiBut *but = uiDefIconTextBut(params.block,
+ UI_BTYPE_LABEL,
+ 0,
+ ICON_NONE,
+ value_str.c_str(),
+ params.xmin,
+ params.ymin,
+ params.width,
+ params.height,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ nullptr);
+ /* Right-align Integers. */
+ UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
+ UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
+ }
else if (data.type().is<float>()) {
const float value = data.get<float>(real_index);
std::stringstream ss;
diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt
index abd7620ea2b..a85c69caa50 100644
--- a/source/blender/editors/space_text/CMakeLists.txt
+++ b/source/blender/editors/space_text/CMakeLists.txt
@@ -61,8 +61,5 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
blender_add_lib(bf_editor_space_text "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 8fb55ed9b46..27941b881b8 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -79,10 +79,8 @@ static void text_font_end(const TextDrawContext *UNUSED(tdc))
static int text_font_draw(const TextDrawContext *tdc, int x, int y, const char *str)
{
- int columns;
-
BLF_position(tdc->font_id, x, y, 0);
- columns = BLF_draw_mono(tdc->font_id, str, BLF_DRAW_STR_DUMMY_MAX, tdc->cwidth_px);
+ const int columns = BLF_draw_mono(tdc->font_id, str, BLF_DRAW_STR_DUMMY_MAX, tdc->cwidth_px);
return tdc->cwidth_px * columns;
}
@@ -90,18 +88,17 @@ static int text_font_draw(const TextDrawContext *tdc, int x, int y, const char *
static int text_font_draw_character(const TextDrawContext *tdc, int x, int y, char c)
{
BLF_position(tdc->font_id, x, y, 0);
- BLF_draw(tdc->font_id, &c, 1);
+ BLF_draw_mono(tdc->font_id, &c, 1, tdc->cwidth_px);
return tdc->cwidth_px;
}
-static int text_font_draw_character_utf8(const TextDrawContext *tdc, int x, int y, const char *c)
+static int text_font_draw_character_utf8(
+ const TextDrawContext *tdc, int x, int y, const char *c, const int c_len)
{
- int columns;
-
- const size_t len = BLI_str_utf8_size_safe(c);
+ BLI_assert(c_len == BLI_str_utf8_size_safe(c));
BLF_position(tdc->font_id, x, y, 0);
- columns = BLF_draw_mono(tdc->font_id, c, len, tdc->cwidth_px);
+ const int columns = BLF_draw_mono(tdc->font_id, c, c_len, tdc->cwidth_px);
return tdc->cwidth_px * columns;
}
@@ -463,13 +460,15 @@ static int text_draw_wrapped(const SpaceText *st,
}
/* Draw the visible portion of text on the overshot line */
- for (a = fstart, ma = mstart; ma < mend; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
+ for (a = fstart, ma = mstart; ma < mend; a++) {
if (use_syntax) {
if (fmt_prev != format[a]) {
format_draw_color(tdc, fmt_prev = format[a]);
}
}
- x += text_font_draw_character_utf8(tdc, x, y, str + ma);
+ const int c_len = BLI_str_utf8_size_safe(str + ma);
+ x += text_font_draw_character_utf8(tdc, x, y, str + ma, c_len);
+ ma += c_len;
fpos++;
}
y -= TXT_LINE_HEIGHT(st);
@@ -491,15 +490,16 @@ static int text_draw_wrapped(const SpaceText *st,
}
/* Draw the remaining text */
- for (a = fstart, ma = mstart; str[ma] && y > clip_min_y;
- a++, ma += BLI_str_utf8_size_safe(str + ma)) {
+ for (a = fstart, ma = mstart; str[ma] && y > clip_min_y; a++) {
if (use_syntax) {
if (fmt_prev != format[a]) {
format_draw_color(tdc, fmt_prev = format[a]);
}
}
- x += text_font_draw_character_utf8(tdc, x, y, str + ma);
+ const int c_len = BLI_str_utf8_size_safe(str + ma);
+ x += text_font_draw_character_utf8(tdc, x, y, str + ma, c_len);
+ ma += c_len;
}
flatten_string_free(&fs);
@@ -559,8 +559,9 @@ static void text_draw(const SpaceText *st,
if (format[a] != fmt_prev) {
format_draw_color(tdc, fmt_prev = format[a]);
}
- x += text_font_draw_character_utf8(tdc, x, y, in + str_shift);
- str_shift += BLI_str_utf8_size_safe(in + str_shift);
+ const int c_len = BLI_str_utf8_size_safe(in + str_shift);
+ x += text_font_draw_character_utf8(tdc, x, y, in + str_shift, c_len);
+ str_shift += c_len;
}
}
else {
diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c
index d40229332fd..e4c11bc8668 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -30,6 +30,7 @@
#ifdef WIN32
# include "BLI_winstuff.h"
#endif
+#include "BLI_path_util.h"
#include "BKE_context.h"
#include "BKE_main.h"
@@ -142,16 +143,20 @@ static void PREFERENCES_OT_autoexec_path_remove(wmOperatorType *ot)
static int preferences_asset_library_add_exec(bContext *UNUSED(C), wmOperator *op)
{
- char *directory = RNA_string_get_alloc(op->ptr, "directory", NULL, 0, NULL);
+ char *path = RNA_string_get_alloc(op->ptr, "directory", NULL, 0, NULL);
+ char dirname[FILE_MAXFILE];
+
+ BLI_path_slash_rstrip(path);
+ BLI_split_file_part(path, dirname, sizeof(dirname));
/* NULL is a valid directory path here. A library without path will be created then. */
- BKE_preferences_asset_library_add(&U, NULL, directory);
+ BKE_preferences_asset_library_add(&U, dirname, path);
U.runtime.is_dirty = true;
/* There's no dedicated notifier for the Preferences. */
WM_main_add_notifier(NC_WINDOW, NULL);
- MEM_freeN(directory);
+ MEM_freeN(path);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 19f869ed50b..7e8b013192f 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -60,8 +60,17 @@ set(SRC
view3d_gizmo_tool_generic.c
view3d_header.c
view3d_iterators.c
+ view3d_navigate.c
+ view3d_navigate_dolly.c
view3d_navigate_fly.c
+ view3d_navigate_move.c
+ view3d_navigate_ndof.c
+ view3d_navigate_roll.c
+ view3d_navigate_rotate.c
+ view3d_navigate_smoothview.c
view3d_navigate_walk.c
+ view3d_navigate_zoom.c
+ view3d_navigate_zoom_border.c
view3d_ops.c
view3d_placement.c
view3d_project.c
@@ -71,6 +80,7 @@ set(SRC
view3d_view.c
view3d_intern.h
+ view3d_navigate.h
)
set(LIB
@@ -83,11 +93,6 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
-
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 595ae3d8457..51107499d3f 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -89,6 +89,7 @@
#include "DEG_depsgraph_build.h"
#include "view3d_intern.h" /* own include */
+#include "view3d_navigate.h"
/* ******************** manage regions ********************* */
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index b1f19581543..3f639e8ee1a 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1036,7 +1036,7 @@ static void draw_rotation_guide(const RegionView3D *rv3d)
negate_v3_v3(o, rv3d->ofs);
GPU_blend(GPU_BLEND_ALPHA);
- GPU_depth_mask(false); /* don't overwrite zbuf */
+ GPU_depth_mask(false); /* Don't overwrite the Z-buffer. */
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
@@ -1258,11 +1258,7 @@ static void draw_viewport_name(ARegion *region, View3D *v3d, int xoffset, int *y
/* 6 is the maximum size of the axis roll text. */
/* increase size for unicode languages (Chinese in utf-8...) */
-#ifdef WITH_INTERNATIONAL
char tmpstr[96 + 6];
-#else
- char tmpstr[32 + 6];
-#endif
BLF_enable(font_id, BLF_SHADOW);
BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
@@ -1689,9 +1685,9 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
G.f |= G_FLAG_RENDER_VIEWPORT;
{
- /* free images which can have changed on frame-change
- * warning! can be slow so only free animated images - campbell */
- BKE_image_free_anim_gputextures(G.main); /* XXX :((( */
+ /* Free images which can have changed on frame-change.
+ * WARNING(@campbellbarton): can be slow so only free animated images. */
+ BKE_image_free_anim_gputextures(G.main);
}
GPU_matrix_push_projection();
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 80089815284..4c7a7cb4c61 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -23,70 +23,39 @@
* 3D view manipulation/operators.
*/
-#include <float.h>
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "DNA_world_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_dial_2d.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_camera.h"
-#include "BKE_context.h"
-#include "BKE_gpencil_geom.h"
-#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
-#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
-#include "BKE_vfont.h"
-#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
#include "WM_api.h"
#include "WM_message.h"
-#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "ED_armature.h"
-#include "ED_mesh.h"
-#include "ED_particle.h"
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_transform_snap_object_context.h"
-#include "ED_view3d.h"
-
-#include "UI_resources.h"
-
-#include "PIL_time.h"
#include "view3d_intern.h" /* own include */
-enum {
- HAS_TRANSLATE = (1 << 0),
- HAS_ROTATE = (1 << 0),
-};
-
/* test for unlocked camera view in quad view */
static bool view3d_camera_user_poll(bContext *C)
{
@@ -115,3052 +84,6 @@ static bool view3d_lock_poll(bContext *C)
return false;
}
-static bool view3d_pan_poll(bContext *C)
-{
- if (ED_operator_region_view3d_active(C)) {
- const RegionView3D *rv3d = CTX_wm_region_view3d(C);
- return !(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_LOCATION);
- }
- return false;
-}
-
-static bool view3d_zoom_or_dolly_poll(bContext *C)
-{
- if (ED_operator_region_view3d_active(C)) {
- const RegionView3D *rv3d = CTX_wm_region_view3d(C);
- return !(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ZOOM_AND_DOLLY);
- }
- return false;
-}
-
-/* -------------------------------------------------------------------- */
-/** \name Generic View Operator Properties
- * \{ */
-
-enum eV3D_OpPropFlag {
- V3D_OP_PROP_MOUSE_CO = (1 << 0),
- V3D_OP_PROP_DELTA = (1 << 1),
- V3D_OP_PROP_USE_ALL_REGIONS = (1 << 2),
- V3D_OP_PROP_USE_MOUSE_INIT = (1 << 3),
-};
-
-static void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3D_OpPropFlag flag)
-{
- if (flag & V3D_OP_PROP_MOUSE_CO) {
- PropertyRNA *prop;
- prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Region Position X", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Region Position Y", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
- if (flag & V3D_OP_PROP_DELTA) {
- RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
- }
- if (flag & V3D_OP_PROP_USE_ALL_REGIONS) {
- PropertyRNA *prop;
- prop = RNA_def_boolean(
- ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- }
- if (flag & V3D_OP_PROP_USE_MOUSE_INIT) {
- WM_operator_properties_use_cursor_init(ot);
- }
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Generic View Operator Custom-Data
- * \{ */
-
-typedef struct ViewOpsData {
- /** Context pointers (assigned by #viewops_data_alloc). */
- Main *bmain;
- Scene *scene;
- ScrArea *area;
- ARegion *region;
- View3D *v3d;
- RegionView3D *rv3d;
- Depsgraph *depsgraph;
-
- /** Needed for continuous zoom. */
- wmTimer *timer;
-
- /** Viewport state on initialization, don't change afterwards. */
- struct {
- float dist;
- float camzoom;
- float quat[4];
- /** #wmEvent.xy. */
- int event_xy[2];
- /** Offset to use when #VIEWOPS_FLAG_USE_MOUSE_INIT is not set.
- * so we can simulate pressing in the middle of the screen. */
- int event_xy_offset[2];
- /** #wmEvent.type that triggered the operator. */
- int event_type;
- float ofs[3];
- /** Initial distance to 'ofs'. */
- float zfac;
-
- /** Trackball rotation only. */
- float trackvec[3];
- /** Dolly only. */
- float mousevec[3];
-
- /**
- * #RegionView3D.persp set after auto-perspective is applied.
- * If we want the value before running the operator, add a separate member.
- */
- char persp;
-
- /** Used for roll */
- Dial *dial;
- } init;
-
- /** Previous state (previous modal event handled). */
- struct {
- int event_xy[2];
- /** For operators that use time-steps (continuous zoom). */
- double time;
- } prev;
-
- /** Current state. */
- struct {
- /** Working copy of #RegionView3D.viewquat, needed for rotation calculation
- * so we can apply snap to the 3D Viewport while keeping the unsnapped rotation
- * here to use when snap is disabled and for continued calculation. */
- float viewquat[4];
- } curr;
-
- float reverse;
- bool axis_snap; /* view rotate only */
-
- /** Use for orbit selection and auto-dist. */
- float dyn_ofs[3];
- bool use_dyn_ofs;
-} ViewOpsData;
-
-/**
- * Size of the sphere being dragged for trackball rotation within the view bounds.
- * also affects speed (smaller is faster).
- */
-#define TRACKBALLSIZE (1.1f)
-
-static void calctrackballvec(const rcti *rect, const int event_xy[2], float r_dir[3])
-{
- const float radius = TRACKBALLSIZE;
- const float t = radius / (float)M_SQRT2;
- const float size[2] = {BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)};
- /* Aspect correct so dragging in a non-square view doesn't squash the direction.
- * So diagonal motion rotates the same direction the cursor is moving. */
- const float size_min = min_ff(size[0], size[1]);
- const float aspect[2] = {size_min / size[0], size_min / size[1]};
-
- /* Normalize x and y. */
- r_dir[0] = (event_xy[0] - BLI_rcti_cent_x(rect)) / ((size[0] * aspect[0]) / 2.0);
- r_dir[1] = (event_xy[1] - BLI_rcti_cent_y(rect)) / ((size[1] * aspect[1]) / 2.0);
- const float d = len_v2(r_dir);
- if (d < t) {
- /* Inside sphere. */
- r_dir[2] = sqrtf(square_f(radius) - square_f(d));
- }
- else {
- /* On hyperbola. */
- r_dir[2] = square_f(t) / d;
- }
-}
-
-/**
- * Allocate and fill in context pointers for #ViewOpsData
- */
-static void viewops_data_alloc(bContext *C, wmOperator *op)
-{
- ViewOpsData *vod = MEM_callocN(sizeof(ViewOpsData), "viewops data");
-
- /* store data */
- op->customdata = vod;
- vod->bmain = CTX_data_main(C);
- vod->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- vod->scene = CTX_data_scene(C);
- vod->area = CTX_wm_area(C);
- vod->region = CTX_wm_region(C);
- vod->v3d = vod->area->spacedata.first;
- vod->rv3d = vod->region->regiondata;
-}
-
-void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
- const float ofs_old[3],
- const float viewquat_old[4],
- const float viewquat_new[4],
- const float dyn_ofs[3])
-{
- float q[4];
- invert_qt_qt_normalized(q, viewquat_old);
- mul_qt_qtqt(q, q, viewquat_new);
-
- invert_qt_normalized(q);
-
- sub_v3_v3v3(r_ofs, ofs_old, dyn_ofs);
- mul_qt_v3(q, r_ofs);
- add_v3_v3(r_ofs, dyn_ofs);
-}
-
-static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
-{
- static float lastofs[3] = {0, 0, 0};
- bool is_set = false;
-
- const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
- View3D *v3d = CTX_wm_view3d(C);
- Object *ob_act_eval = OBACT(view_layer_eval);
- Object *ob_act = DEG_get_original_object(ob_act_eval);
-
- if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) &&
- /* with weight-paint + pose-mode, fall through to using calculateTransformCenter */
- ((ob_act->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(ob_act)) == 0) {
- /* in case of sculpting use last average stroke position as a rotation
- * center, in other cases it's not clear what rotation center shall be
- * so just rotate around object origin
- */
- if (ob_act->mode &
- (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
- float stroke[3];
- BKE_paint_stroke_get_average(scene, ob_act_eval, stroke);
- copy_v3_v3(lastofs, stroke);
- }
- else {
- copy_v3_v3(lastofs, ob_act_eval->obmat[3]);
- }
- is_set = true;
- }
- else if (ob_act && (ob_act->mode & OB_MODE_EDIT) && (ob_act->type == OB_FONT)) {
- Curve *cu = ob_act_eval->data;
- EditFont *ef = cu->editfont;
-
- zero_v3(lastofs);
- for (int i = 0; i < 4; i++) {
- add_v2_v2(lastofs, ef->textcurs[i]);
- }
- mul_v2_fl(lastofs, 1.0f / 4.0f);
-
- mul_m4_v3(ob_act_eval->obmat, lastofs);
-
- is_set = true;
- }
- else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) {
- /* object mode use boundbox centers */
- Base *base_eval;
- uint tot = 0;
- float select_center[3];
-
- zero_v3(select_center);
- for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
- if (BASE_SELECTED(v3d, base_eval)) {
- /* use the boundbox if we can */
- Object *ob_eval = base_eval->object;
-
- if (ob_eval->runtime.bb && !(ob_eval->runtime.bb->flag & BOUNDBOX_DIRTY)) {
- float cent[3];
-
- BKE_boundbox_calc_center_aabb(ob_eval->runtime.bb, cent);
-
- mul_m4_v3(ob_eval->obmat, cent);
- add_v3_v3(select_center, cent);
- }
- else {
- add_v3_v3(select_center, ob_eval->obmat[3]);
- }
- tot++;
- }
- }
- if (tot) {
- mul_v3_fl(select_center, 1.0f / (float)tot);
- copy_v3_v3(lastofs, select_center);
- is_set = true;
- }
- }
- else {
- /* If there's no selection, lastofs is unmodified and last value since static */
- is_set = calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, lastofs, NULL);
- }
-
- copy_v3_v3(r_dyn_ofs, lastofs);
-
- return is_set;
-}
-
-enum eViewOpsFlag {
- /** When enabled, rotate around the selection. */
- VIEWOPS_FLAG_ORBIT_SELECT = (1 << 0),
- /** When enabled, use the depth under the cursor for navigation. */
- VIEWOPS_FLAG_DEPTH_NAVIGATE = (1 << 1),
- /**
- * When enabled run #ED_view3d_persp_ensure this may switch out of camera view
- * when orbiting or switch from orthographic to perspective when auto-perspective is enabled.
- * Some operations don't require this (view zoom/pan or NDOF where subtle rotation is common
- * so we don't want it to trigger auto-perspective). */
- VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2),
- /** When set, ignore any options that depend on initial cursor location. */
- VIEWOPS_FLAG_USE_MOUSE_INIT = (1 << 3),
-};
-
-static enum eViewOpsFlag viewops_flag_from_args(bool use_select, bool use_depth)
-{
- enum eViewOpsFlag flag = 0;
- if (use_select) {
- flag |= VIEWOPS_FLAG_ORBIT_SELECT;
- }
- if (use_depth) {
- flag |= VIEWOPS_FLAG_DEPTH_NAVIGATE;
- }
-
- return flag;
-}
-
-static enum eViewOpsFlag viewops_flag_from_prefs(void)
-{
- return viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0,
- (U.uiflag & USER_DEPTH_NAVIGATE) != 0);
-}
-
-/**
- * Calculate the values for #ViewOpsData
- */
-static void viewops_data_create(bContext *C,
- wmOperator *op,
- const wmEvent *event,
- enum eViewOpsFlag viewops_flag)
-{
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ViewOpsData *vod = op->customdata;
- RegionView3D *rv3d = vod->rv3d;
-
- /* Could do this more nicely. */
- if ((viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) == 0) {
- viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
- }
-
- /* we need the depth info before changing any viewport options */
- if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
- float fallback_depth_pt[3];
-
- view3d_operator_needs_opengl(C); /* needed for zbuf drawing */
-
- negate_v3_v3(fallback_depth_pt, rv3d->ofs);
-
- vod->use_dyn_ofs = ED_view3d_autodist(
- depsgraph, vod->region, vod->v3d, event->mval, vod->dyn_ofs, true, fallback_depth_pt);
- }
- else {
- vod->use_dyn_ofs = false;
- }
-
- if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
- if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->region)) {
- /* If we're switching from camera view to the perspective one,
- * need to tag viewport update, so camera view and borders are properly updated. */
- ED_region_tag_redraw(vod->region);
- }
- }
-
- /* set the view from the camera, if view locking is enabled.
- * we may want to make this optional but for now its needed always */
- ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d);
-
- vod->init.persp = rv3d->persp;
- vod->init.dist = rv3d->dist;
- vod->init.camzoom = rv3d->camzoom;
- copy_qt_qt(vod->init.quat, rv3d->viewquat);
- copy_v2_v2_int(vod->init.event_xy, event->xy);
- copy_v2_v2_int(vod->prev.event_xy, event->xy);
-
- if (viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) {
- zero_v2_int(vod->init.event_xy_offset);
- }
- else {
- /* Simulate the event starting in the middle of the region. */
- vod->init.event_xy_offset[0] = BLI_rcti_cent_x(&vod->region->winrct) - event->xy[0];
- vod->init.event_xy_offset[1] = BLI_rcti_cent_y(&vod->region->winrct) - event->xy[1];
- }
-
- vod->init.event_type = event->type;
- copy_v3_v3(vod->init.ofs, rv3d->ofs);
-
- copy_qt_qt(vod->curr.viewquat, rv3d->viewquat);
-
- if (viewops_flag & VIEWOPS_FLAG_ORBIT_SELECT) {
- float ofs[3];
- if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) {
- vod->use_dyn_ofs = true;
- negate_v3_v3(vod->dyn_ofs, ofs);
- viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
- }
- }
-
- if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
- if (vod->use_dyn_ofs) {
- if (rv3d->is_persp) {
- float my_origin[3]; /* original G.vd->ofs */
- float my_pivot[3]; /* view */
- float dvec[3];
-
- /* locals for dist correction */
- float mat[3][3];
- float upvec[3];
-
- negate_v3_v3(my_origin, rv3d->ofs); /* ofs is flipped */
-
- /* Set the dist value to be the distance from this 3d point this means you'll
- * always be able to zoom into it and panning won't go bad when dist was zero. */
-
- /* remove dist value */
- upvec[0] = upvec[1] = 0;
- upvec[2] = rv3d->dist;
- copy_m3_m4(mat, rv3d->viewinv);
-
- mul_m3_v3(mat, upvec);
- sub_v3_v3v3(my_pivot, rv3d->ofs, upvec);
- negate_v3(my_pivot); /* ofs is flipped */
-
- /* find a new ofs value that is along the view axis
- * (rather than the mouse location) */
- closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin);
- vod->init.dist = rv3d->dist = len_v3v3(my_pivot, dvec);
-
- negate_v3_v3(rv3d->ofs, dvec);
- }
- else {
- const float mval_region_mid[2] = {(float)vod->region->winx / 2.0f,
- (float)vod->region->winy / 2.0f};
-
- ED_view3d_win_to_3d(vod->v3d, vod->region, vod->dyn_ofs, mval_region_mid, rv3d->ofs);
- negate_v3(rv3d->ofs);
- }
- negate_v3(vod->dyn_ofs);
- copy_v3_v3(vod->init.ofs, rv3d->ofs);
- }
- }
-
- /* For dolly */
- ED_view3d_win_to_vector(vod->region, (const float[2]){UNPACK2(event->mval)}, vod->init.mousevec);
-
- {
- int event_xy_offset[2];
- add_v2_v2v2_int(event_xy_offset, event->xy, vod->init.event_xy_offset);
-
- /* For rotation with trackball rotation. */
- calctrackballvec(&vod->region->winrct, event_xy_offset, vod->init.trackvec);
- }
-
- {
- float tvec[3];
- negate_v3_v3(tvec, rv3d->ofs);
- vod->init.zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
- }
-
- vod->reverse = 1.0f;
- if (rv3d->persmat[2][1] < 0.0f) {
- vod->reverse = -1.0f;
- }
-
- rv3d->rflag |= RV3D_NAVIGATING;
-}
-
-static void viewops_data_free(bContext *C, wmOperator *op)
-{
- ARegion *region;
- if (op->customdata) {
- ViewOpsData *vod = op->customdata;
- region = vod->region;
- vod->rv3d->rflag &= ~RV3D_NAVIGATING;
-
- if (vod->timer) {
- WM_event_remove_timer(CTX_wm_manager(C), vod->timer->win, vod->timer);
- }
-
- if (vod->init.dial) {
- MEM_freeN(vod->init.dial);
- }
-
- MEM_freeN(vod);
- op->customdata = NULL;
- }
- else {
- region = CTX_wm_region(C);
- }
-
- /* Need to redraw because drawing code uses RV3D_NAVIGATING to draw
- * faster while navigation operator runs. */
- ED_region_tag_redraw(region);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name View Rotate Operator
- * \{ */
-
-enum {
- VIEW_PASS = 0,
- VIEW_APPLY,
- VIEW_CONFIRM,
-};
-
-/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
-enum {
- VIEW_MODAL_CONFIRM = 1, /* used for all view operations */
- VIEWROT_MODAL_AXIS_SNAP_ENABLE = 2,
- VIEWROT_MODAL_AXIS_SNAP_DISABLE = 3,
- VIEWROT_MODAL_SWITCH_ZOOM = 4,
- VIEWROT_MODAL_SWITCH_MOVE = 5,
- VIEWROT_MODAL_SWITCH_ROTATE = 6,
-};
-
-void viewrotate_modal_keymap(wmKeyConfig *keyconf)
-{
- static const EnumPropertyItem modal_items[] = {
- {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
-
- {VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Axis Snap", ""},
- {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Axis Snap (Off)", ""},
-
- {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
- {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
-
- {0, NULL, 0, NULL, NULL},
- };
-
- wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Rotate Modal");
-
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) {
- return;
- }
-
- keymap = WM_modalkeymap_ensure(keyconf, "View3D Rotate Modal", modal_items);
-
- /* disabled mode switching for now, can re-implement better, later on */
-#if 0
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
- WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
- WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
-#endif
-
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate");
-}
-
-static void viewrotate_apply_dyn_ofs(ViewOpsData *vod, const float viewquat_new[4])
-{
- if (vod->use_dyn_ofs) {
- RegionView3D *rv3d = vod->rv3d;
- view3d_orbit_apply_dyn_ofs(
- rv3d->ofs, vod->init.ofs, vod->init.quat, viewquat_new, vod->dyn_ofs);
- }
-}
-
-static void viewrotate_apply_snap(ViewOpsData *vod)
-{
- const float axis_limit = DEG2RADF(45 / 3);
-
- RegionView3D *rv3d = vod->rv3d;
-
- float viewquat_inv[4];
- float zaxis[3] = {0, 0, 1};
- float zaxis_best[3];
- int x, y, z;
- bool found = false;
-
- invert_qt_qt_normalized(viewquat_inv, vod->curr.viewquat);
-
- mul_qt_v3(viewquat_inv, zaxis);
- normalize_v3(zaxis);
-
- for (x = -1; x < 2; x++) {
- for (y = -1; y < 2; y++) {
- for (z = -1; z < 2; z++) {
- if (x || y || z) {
- float zaxis_test[3] = {x, y, z};
-
- normalize_v3(zaxis_test);
-
- if (angle_normalized_v3v3(zaxis_test, zaxis) < axis_limit) {
- copy_v3_v3(zaxis_best, zaxis_test);
- found = true;
- }
- }
- }
- }
- }
-
- if (found) {
-
- /* find the best roll */
- float quat_roll[4], quat_final[4], quat_best[4], quat_snap[4];
- float viewquat_align[4]; /* viewquat aligned to zaxis_best */
- float viewquat_align_inv[4]; /* viewquat aligned to zaxis_best */
- float best_angle = axis_limit;
- int j;
-
- /* viewquat_align is the original viewquat aligned to the snapped axis
- * for testing roll */
- rotation_between_vecs_to_quat(viewquat_align, zaxis_best, zaxis);
- normalize_qt(viewquat_align);
- mul_qt_qtqt(viewquat_align, vod->curr.viewquat, viewquat_align);
- normalize_qt(viewquat_align);
- invert_qt_qt_normalized(viewquat_align_inv, viewquat_align);
-
- vec_to_quat(quat_snap, zaxis_best, OB_NEGZ, OB_POSY);
- normalize_qt(quat_snap);
- invert_qt_normalized(quat_snap);
-
- /* check if we can find the roll */
- found = false;
-
- /* find best roll */
- for (j = 0; j < 8; j++) {
- float angle;
- float xaxis1[3] = {1, 0, 0};
- float xaxis2[3] = {1, 0, 0};
- float quat_final_inv[4];
-
- axis_angle_to_quat(quat_roll, zaxis_best, (float)j * DEG2RADF(45.0f));
- normalize_qt(quat_roll);
-
- mul_qt_qtqt(quat_final, quat_snap, quat_roll);
- normalize_qt(quat_final);
-
- /* compare 2 vector angles to find the least roll */
- invert_qt_qt_normalized(quat_final_inv, quat_final);
- mul_qt_v3(viewquat_align_inv, xaxis1);
- mul_qt_v3(quat_final_inv, xaxis2);
- angle = angle_v3v3(xaxis1, xaxis2);
-
- if (angle <= best_angle) {
- found = true;
- best_angle = angle;
- copy_qt_qt(quat_best, quat_final);
- }
- }
-
- if (found) {
- /* lock 'quat_best' to an axis view if we can */
- ED_view3d_quat_to_axis_view(quat_best, 0.01f, &rv3d->view, &rv3d->view_axis_roll);
- if (rv3d->view != RV3D_VIEW_USER) {
- ED_view3d_quat_from_axis_view(rv3d->view, rv3d->view_axis_roll, quat_best);
- }
- }
- else {
- copy_qt_qt(quat_best, viewquat_align);
- }
-
- copy_qt_qt(rv3d->viewquat, quat_best);
-
- viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
-
- if (U.uiflag & USER_AUTOPERSP) {
- if (RV3D_VIEW_IS_AXIS(rv3d->view)) {
- if (rv3d->persp == RV3D_PERSP) {
- rv3d->persp = RV3D_ORTHO;
- }
- }
- }
- }
- else if (U.uiflag & USER_AUTOPERSP) {
- rv3d->persp = vod->init.persp;
- }
-}
-
-static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
-{
- RegionView3D *rv3d = vod->rv3d;
-
- rv3d->view = RV3D_VIEW_USER; /* need to reset every time because of view snapping */
-
- if (U.flag & USER_TRACKBALL) {
- float axis[3], q1[4], dvec[3], newvec[3];
- float angle;
-
- {
- const int event_xy_offset[2] = {
- event_xy[0] + vod->init.event_xy_offset[0],
- event_xy[1] + vod->init.event_xy_offset[1],
- };
- calctrackballvec(&vod->region->winrct, event_xy_offset, newvec);
- }
-
- sub_v3_v3v3(dvec, newvec, vod->init.trackvec);
-
- angle = (len_v3(dvec) / (2.0f * TRACKBALLSIZE)) * (float)M_PI;
-
- /* Before applying the sensitivity this is rotating 1:1,
- * where the cursor would match the surface of a sphere in the view. */
- angle *= U.view_rotate_sensitivity_trackball;
-
- /* Allow for rotation beyond the interval [-pi, pi] */
- angle = angle_wrap_rad(angle);
-
- /* This relation is used instead of the actual angle between vectors
- * so that the angle of rotation is linearly proportional to
- * the distance that the mouse is dragged. */
-
- cross_v3_v3v3(axis, vod->init.trackvec, newvec);
- axis_angle_to_quat(q1, axis, angle);
-
- mul_qt_qtqt(vod->curr.viewquat, q1, vod->init.quat);
-
- viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
- }
- else {
- float quat_local_x[4], quat_global_z[4];
- float m[3][3];
- float m_inv[3][3];
- const float zvec_global[3] = {0.0f, 0.0f, 1.0f};
- float xaxis[3];
-
- /* Radians per-pixel. */
- const float sensitivity = U.view_rotate_sensitivity_turntable / U.dpi_fac;
-
- /* Get the 3x3 matrix and its inverse from the quaternion */
- quat_to_mat3(m, vod->curr.viewquat);
- invert_m3_m3(m_inv, m);
-
- /* Avoid Gimbal Lock
- *
- * Even though turn-table mode is in use, this can occur when the user exits the camera view
- * or when aligning the view to a rotated object.
- *
- * We have gimbal lock when the user's view is rotated +/- 90 degrees along the view axis.
- * In this case the vertical rotation is the same as the sideways turntable motion.
- * Making it impossible to get out of the gimbal locked state without resetting the view.
- *
- * The logic below lets the user exit out of this state without any abrupt 'fix'
- * which would be disorienting.
- *
- * This works by blending two horizons:
- * - Rotated-horizon: `cross_v3_v3v3(xaxis, zvec_global, m_inv[2])`
- * When only this is used, this turntable rotation works - but it's side-ways
- * (as if the entire turn-table has been placed on its side)
- * While there is no gimbal lock, it's also awkward to use.
- * - Un-rotated-horizon: `m_inv[0]`
- * When only this is used, the turntable rotation can have gimbal lock.
- *
- * The solution used here is to blend between these two values,
- * so the severity of the gimbal lock is used to blend the rotated horizon.
- * Blending isn't essential, it just makes the transition smoother.
- *
- * This allows sideways turn-table rotation on a Z axis that isn't world-space Z,
- * While up-down turntable rotation eventually corrects gimbal lock. */
-#if 1
- if (len_squared_v3v3(zvec_global, m_inv[2]) > 0.001f) {
- float fac;
- cross_v3_v3v3(xaxis, zvec_global, m_inv[2]);
- if (dot_v3v3(xaxis, m_inv[0]) < 0) {
- negate_v3(xaxis);
- }
- fac = angle_normalized_v3v3(zvec_global, m_inv[2]) / (float)M_PI;
- fac = fabsf(fac - 0.5f) * 2;
- fac = fac * fac;
- interp_v3_v3v3(xaxis, xaxis, m_inv[0], fac);
- }
- else {
- copy_v3_v3(xaxis, m_inv[0]);
- }
-#else
- copy_v3_v3(xaxis, m_inv[0]);
-#endif
-
- /* Determine the direction of the x vector (for rotating up and down) */
- /* This can likely be computed directly from the quaternion. */
-
- /* Perform the up/down rotation */
- axis_angle_to_quat(quat_local_x, xaxis, sensitivity * -(event_xy[1] - vod->prev.event_xy[1]));
- mul_qt_qtqt(quat_local_x, vod->curr.viewquat, quat_local_x);
-
- /* Perform the orbital rotation */
- axis_angle_to_quat_single(
- quat_global_z, 'Z', sensitivity * vod->reverse * (event_xy[0] - vod->prev.event_xy[0]));
- mul_qt_qtqt(vod->curr.viewquat, quat_local_x, quat_global_z);
-
- viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
- }
-
- /* avoid precision loss over time */
- normalize_qt(vod->curr.viewquat);
-
- /* use a working copy so view rotation locking doesn't overwrite the locked
- * rotation back into the view we calculate with */
- copy_qt_qt(rv3d->viewquat, vod->curr.viewquat);
-
- /* Check for view snap,
- * NOTE: don't apply snap to `vod->viewquat` so the view won't jam up. */
- if (vod->axis_snap) {
- viewrotate_apply_snap(vod);
- }
- vod->prev.event_xy[0] = event_xy[0];
- vod->prev.event_xy[1] = event_xy[1];
-
- ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d);
-
- ED_region_tag_redraw(vod->region);
-}
-
-static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ViewOpsData *vod = op->customdata;
- short event_code = VIEW_PASS;
- bool use_autokey = false;
- int ret = OPERATOR_RUNNING_MODAL;
-
- /* execute the events */
- if (event->type == MOUSEMOVE) {
- event_code = VIEW_APPLY;
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case VIEW_MODAL_CONFIRM:
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_AXIS_SNAP_ENABLE:
- vod->axis_snap = true;
- event_code = VIEW_APPLY;
- break;
- case VIEWROT_MODAL_AXIS_SNAP_DISABLE:
- vod->rv3d->persp = vod->init.persp;
- vod->axis_snap = false;
- event_code = VIEW_APPLY;
- break;
- case VIEWROT_MODAL_SWITCH_ZOOM:
- WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- }
- }
- else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
- event_code = VIEW_CONFIRM;
- }
-
- if (event_code == VIEW_APPLY) {
- viewrotate_apply(vod, event->xy);
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- use_autokey = true;
- }
- }
- else if (event_code == VIEW_CONFIRM) {
- use_autokey = true;
- ret = OPERATOR_FINISHED;
- }
-
- if (use_autokey) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
- }
-
- if (ret & OPERATOR_FINISHED) {
- viewops_data_free(C, op);
- }
-
- return ret;
-}
-
-static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ViewOpsData *vod;
-
- const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
-
- /* makes op->customdata */
- viewops_data_alloc(C, op);
- vod = op->customdata;
-
- /* poll should check but in some cases fails, see poll func for details */
- if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_ROTATION) {
- viewops_data_free(C, op);
- return OPERATOR_PASS_THROUGH;
- }
-
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
-
- viewops_data_create(C,
- op,
- event,
- viewops_flag_from_prefs() | VIEWOPS_FLAG_PERSP_ENSURE |
- (use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
-
- if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
- /* Rotate direction we keep always same */
- int event_xy[2];
-
- if (event->type == MOUSEPAN) {
- if (event->is_direction_inverted) {
- event_xy[0] = 2 * event->xy[0] - event->prev_xy[0];
- event_xy[1] = 2 * event->xy[1] - event->prev_xy[1];
- }
- else {
- copy_v2_v2_int(event_xy, event->prev_xy);
- }
- }
- else {
- /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
- copy_v2_v2_int(event_xy, event->prev_xy);
- }
-
- viewrotate_apply(vod, event_xy);
-
- viewops_data_free(C, op);
-
- return OPERATOR_FINISHED;
- }
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static void viewrotate_cancel(bContext *C, wmOperator *op)
-{
- viewops_data_free(C, op);
-}
-
-void VIEW3D_OT_rotate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Rotate View";
- ot->description = "Rotate the view";
- ot->idname = "VIEW3D_OT_rotate";
-
- /* api callbacks */
- ot->invoke = viewrotate_invoke;
- ot->modal = viewrotate_modal;
- ot->poll = ED_operator_region_view3d_active;
- ot->cancel = viewrotate_cancel;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY;
-
- view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name NDOF Utility Functions
- * \{ */
-
-#ifdef WITH_INPUT_NDOF
-static bool ndof_has_translate(const wmNDOFMotionData *ndof,
- const View3D *v3d,
- const RegionView3D *rv3d)
-{
- return !is_zero_v3(ndof->tvec) && (!ED_view3d_offset_lock_check(v3d, rv3d));
-}
-
-static bool ndof_has_rotate(const wmNDOFMotionData *ndof, const RegionView3D *rv3d)
-{
- return !is_zero_v3(ndof->rvec) && ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0);
-}
-
-/**
- * \param depth_pt: A point to calculate the depth (in perspective mode)
- */
-static float view3d_ndof_pan_speed_calc_ex(RegionView3D *rv3d, const float depth_pt[3])
-{
- float speed = rv3d->pixsize * NDOF_PIXELS_PER_SECOND;
-
- if (rv3d->is_persp) {
- speed *= ED_view3d_calc_zfac(rv3d, depth_pt, NULL);
- }
-
- return speed;
-}
-
-static float view3d_ndof_pan_speed_calc_from_dist(RegionView3D *rv3d, const float dist)
-{
- float viewinv[4];
- float tvec[3];
-
- BLI_assert(dist >= 0.0f);
-
- copy_v3_fl3(tvec, 0.0f, 0.0f, dist);
- /* rv3d->viewinv isn't always valid */
-# if 0
- mul_mat3_m4_v3(rv3d->viewinv, tvec);
-# else
- invert_qt_qt_normalized(viewinv, rv3d->viewquat);
- mul_qt_v3(viewinv, tvec);
-# endif
-
- return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
-}
-
-static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d)
-{
- float tvec[3];
- negate_v3_v3(tvec, rv3d->ofs);
-
- return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
-}
-
-/**
- * Zoom and pan in the same function since sometimes zoom is interpreted as dolly (pan forward).
- *
- * \param has_zoom: zoom, otherwise dolly,
- * often `!rv3d->is_persp` since it doesn't make sense to dolly in ortho.
- */
-static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof,
- ScrArea *area,
- ARegion *region,
- const bool has_translate,
- const bool has_zoom)
-{
- RegionView3D *rv3d = region->regiondata;
- float view_inv[4];
- float pan_vec[3];
-
- if (has_translate == false && has_zoom == false) {
- return;
- }
-
- WM_event_ndof_pan_get(ndof, pan_vec, false);
-
- if (has_zoom) {
- /* zoom with Z */
-
- /* Zoom!
- * velocity should be proportional to the linear velocity attained by rotational motion
- * of same strength [got that?] proportional to `arclength = radius * angle`.
- */
-
- pan_vec[2] = 0.0f;
-
- /* "zoom in" or "translate"? depends on zoom mode in user settings? */
- if (ndof->tvec[2]) {
- float zoom_distance = rv3d->dist * ndof->dt * ndof->tvec[2];
-
- if (U.ndof_flag & NDOF_ZOOM_INVERT) {
- zoom_distance = -zoom_distance;
- }
-
- rv3d->dist += zoom_distance;
- }
- }
- else {
- /* dolly with Z */
-
- /* all callers must check */
- if (has_translate) {
- BLI_assert(ED_view3d_offset_lock_check((View3D *)area->spacedata.first, rv3d) == false);
- }
- }
-
- if (has_translate) {
- const float speed = view3d_ndof_pan_speed_calc(rv3d);
-
- mul_v3_fl(pan_vec, speed * ndof->dt);
-
- /* transform motion from view to world coordinates */
- invert_qt_qt_normalized(view_inv, rv3d->viewquat);
- mul_qt_v3(view_inv, pan_vec);
-
- /* move center of view opposite of hand motion (this is camera mode, not object mode) */
- sub_v3_v3(rv3d->ofs, pan_vec);
-
- if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(area, region);
- }
- }
-}
-
-static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof,
- ScrArea *area,
- ARegion *region,
- ViewOpsData *vod,
- const bool apply_dyn_ofs)
-{
- View3D *v3d = area->spacedata.first;
- RegionView3D *rv3d = region->regiondata;
-
- float view_inv[4];
-
- BLI_assert((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0);
-
- ED_view3d_persp_ensure(vod->depsgraph, v3d, region);
-
- rv3d->view = RV3D_VIEW_USER;
-
- invert_qt_qt_normalized(view_inv, rv3d->viewquat);
-
- if (U.ndof_flag & NDOF_TURNTABLE) {
- float rot[3];
-
- /* Turntable view code adapted for 3D mouse use. */
- float angle, quat[4];
- float xvec[3] = {1, 0, 0};
-
- /* only use XY, ignore Z */
- WM_event_ndof_rotate_get(ndof, rot);
-
- /* Determine the direction of the x vector (for rotating up and down) */
- mul_qt_v3(view_inv, xvec);
-
- /* Perform the up/down rotation */
- angle = ndof->dt * rot[0];
- axis_angle_to_quat(quat, xvec, angle);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
-
- /* Perform the orbital rotation */
- angle = ndof->dt * rot[1];
-
- /* update the onscreen doo-dad */
- rv3d->rot_angle = angle;
- rv3d->rot_axis[0] = 0;
- rv3d->rot_axis[1] = 0;
- rv3d->rot_axis[2] = 1;
-
- axis_angle_to_quat_single(quat, 'Z', angle);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
- }
- else {
- float quat[4];
- float axis[3];
- float angle = WM_event_ndof_to_axis_angle(ndof, axis);
-
- /* transform rotation axis from view to world coordinates */
- mul_qt_v3(view_inv, axis);
-
- /* update the onscreen doo-dad */
- rv3d->rot_angle = angle;
- copy_v3_v3(rv3d->rot_axis, axis);
-
- axis_angle_to_quat(quat, axis, angle);
-
- /* apply rotation */
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
- }
-
- if (apply_dyn_ofs) {
- viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
- }
-}
-
-void view3d_ndof_fly(const wmNDOFMotionData *ndof,
- View3D *v3d,
- RegionView3D *rv3d,
- const bool use_precision,
- const short protectflag,
- bool *r_has_translate,
- bool *r_has_rotate)
-{
- bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
- bool has_rotate = ndof_has_rotate(ndof, rv3d);
-
- float view_inv[4];
- invert_qt_qt_normalized(view_inv, rv3d->viewquat);
-
- rv3d->rot_angle = 0.0f; /* disable onscreen rotation doo-dad */
-
- if (has_translate) {
- /* ignore real 'dist' since fly has its own speed settings,
- * also its overwritten at this point. */
- float speed = view3d_ndof_pan_speed_calc_from_dist(rv3d, 1.0f);
- float trans[3], trans_orig_y;
-
- if (use_precision) {
- speed *= 0.2f;
- }
-
- WM_event_ndof_pan_get(ndof, trans, false);
- mul_v3_fl(trans, speed * ndof->dt);
- trans_orig_y = trans[1];
-
- if (U.ndof_flag & NDOF_FLY_HELICOPTER) {
- trans[1] = 0.0f;
- }
-
- /* transform motion from view to world coordinates */
- mul_qt_v3(view_inv, trans);
-
- if (U.ndof_flag & NDOF_FLY_HELICOPTER) {
- /* replace world z component with device y (yes it makes sense) */
- trans[2] = trans_orig_y;
- }
-
- if (rv3d->persp == RV3D_CAMOB) {
- /* respect camera position locks */
- if (protectflag & OB_LOCK_LOCX) {
- trans[0] = 0.0f;
- }
- if (protectflag & OB_LOCK_LOCY) {
- trans[1] = 0.0f;
- }
- if (protectflag & OB_LOCK_LOCZ) {
- trans[2] = 0.0f;
- }
- }
-
- if (!is_zero_v3(trans)) {
- /* move center of view opposite of hand motion
- * (this is camera mode, not object mode) */
- sub_v3_v3(rv3d->ofs, trans);
- has_translate = true;
- }
- else {
- has_translate = false;
- }
- }
-
- if (has_rotate) {
- const float turn_sensitivity = 1.0f;
-
- float rotation[4];
- float axis[3];
- float angle = turn_sensitivity * WM_event_ndof_to_axis_angle(ndof, axis);
-
- if (fabsf(angle) > 0.0001f) {
- has_rotate = true;
-
- if (use_precision) {
- angle *= 0.2f;
- }
-
- /* transform rotation axis from view to world coordinates */
- mul_qt_v3(view_inv, axis);
-
- /* apply rotation to view */
- axis_angle_to_quat(rotation, axis, angle);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
-
- if (U.ndof_flag & NDOF_LOCK_HORIZON) {
- /* force an upright viewpoint
- * TODO: make this less... sudden */
- float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */
- float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */
-
- /* find new inverse since viewquat has changed */
- invert_qt_qt_normalized(view_inv, rv3d->viewquat);
- /* could apply reverse rotation to existing view_inv to save a few cycles */
-
- /* transform view vectors to world coordinates */
- mul_qt_v3(view_inv, view_horizon);
- mul_qt_v3(view_inv, view_direction);
-
- /* find difference between view & world horizons
- * true horizon lives in world xy plane, so look only at difference in z */
- angle = -asinf(view_horizon[2]);
-
- /* rotate view so view horizon = world horizon */
- axis_angle_to_quat(rotation, view_direction, angle);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
- }
-
- rv3d->view = RV3D_VIEW_USER;
- }
- else {
- has_rotate = false;
- }
- }
-
- *r_has_translate = has_translate;
- *r_has_rotate = has_rotate;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name NDOF Orbit/Translate Operator
- * \{ */
-
-static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- if (event->type != NDOF_MOTION) {
- return OPERATOR_CANCELLED;
- }
-
- const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ViewOpsData *vod;
- View3D *v3d;
- RegionView3D *rv3d;
- char xform_flag = 0;
-
- const wmNDOFMotionData *ndof = event->customdata;
-
- viewops_data_alloc(C, op);
- viewops_data_create(
- C, op, event, viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
- vod = op->customdata;
-
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
-
- v3d = vod->v3d;
- rv3d = vod->rv3d;
-
- /* off by default, until changed later this function */
- rv3d->rot_angle = 0.0f;
-
- ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
-
- if (ndof->progress != P_FINISHING) {
- const bool has_rotation = ndof_has_rotate(ndof, rv3d);
- /* if we can't rotate, fallback to translate (locked axis views) */
- const bool has_translate = ndof_has_translate(ndof, v3d, rv3d) &&
- (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION);
- const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
-
- if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, has_zoom);
- xform_flag |= HAS_TRANSLATE;
- }
-
- if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->area, vod->region, vod, true);
- xform_flag |= HAS_ROTATE;
- }
- }
-
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- if (xform_flag) {
- ED_view3d_camera_lock_autokey(
- v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
- }
-
- ED_region_tag_redraw(vod->region);
-
- viewops_data_free(C, op);
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "NDOF Orbit View";
- ot->description = "Orbit the view using the 3D mouse";
- ot->idname = "VIEW3D_OT_ndof_orbit";
-
- /* api callbacks */
- ot->invoke = ndof_orbit_invoke;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = 0;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name NDOF Orbit/Zoom Operator
- * \{ */
-
-static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- if (event->type != NDOF_MOTION) {
- return OPERATOR_CANCELLED;
- }
-
- const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ViewOpsData *vod;
- View3D *v3d;
- RegionView3D *rv3d;
- char xform_flag = 0;
-
- const wmNDOFMotionData *ndof = event->customdata;
-
- viewops_data_alloc(C, op);
- viewops_data_create(
- C, op, event, viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
-
- vod = op->customdata;
-
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
-
- v3d = vod->v3d;
- rv3d = vod->rv3d;
-
- /* off by default, until changed later this function */
- rv3d->rot_angle = 0.0f;
-
- ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
-
- if (ndof->progress == P_FINISHING) {
- /* pass */
- }
- else if ((rv3d->persp == RV3D_ORTHO) && RV3D_VIEW_IS_AXIS(rv3d->view)) {
- /* if we can't rotate, fallback to translate (locked axis views) */
- const bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
- const bool has_zoom = (ndof->tvec[2] != 0.0f) && ED_view3d_offset_lock_check(v3d, rv3d);
-
- if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, true);
- xform_flag |= HAS_TRANSLATE;
- }
- }
- else {
- /* NOTE: based on feedback from T67579, users want to have pan and orbit enabled at once.
- * It's arguable that orbit shouldn't pan (since we have a pan only operator),
- * so if there are users who like to separate orbit/pan operations - it can be a preference. */
- const bool is_orbit_around_pivot = (U.ndof_flag & NDOF_MODE_ORBIT) ||
- ED_view3d_offset_lock_check(v3d, rv3d);
- const bool has_rotation = ndof_has_rotate(ndof, rv3d);
- bool has_translate, has_zoom;
-
- if (is_orbit_around_pivot) {
- /* Orbit preference or forced lock (Z zooms). */
- has_translate = !is_zero_v2(ndof->tvec) && ndof_has_translate(ndof, v3d, rv3d);
- has_zoom = (ndof->tvec[2] != 0.0f);
- }
- else {
- /* Free preference (Z translates). */
- has_translate = ndof_has_translate(ndof, v3d, rv3d);
- has_zoom = false;
- }
-
- /* Rotation first because dynamic offset resets offset otherwise (and disables panning). */
- if (has_rotation) {
- const float dist_backup = rv3d->dist;
- if (!is_orbit_around_pivot) {
- ED_view3d_distance_set(rv3d, 0.0f);
- }
- view3d_ndof_orbit(ndof, vod->area, vod->region, vod, is_orbit_around_pivot);
- xform_flag |= HAS_ROTATE;
- if (!is_orbit_around_pivot) {
- ED_view3d_distance_set(rv3d, dist_backup);
- }
- }
-
- if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, has_zoom);
- xform_flag |= HAS_TRANSLATE;
- }
- }
-
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- if (xform_flag) {
- ED_view3d_camera_lock_autokey(
- v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
- }
-
- ED_region_tag_redraw(vod->region);
-
- viewops_data_free(C, op);
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "NDOF Orbit View with Zoom";
- ot->description = "Orbit and zoom the view using the 3D mouse";
- ot->idname = "VIEW3D_OT_ndof_orbit_zoom";
-
- /* api callbacks */
- ot->invoke = ndof_orbit_zoom_invoke;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = 0;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name NDOF Pan/Zoom Operator
- * \{ */
-
-static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
-{
- if (event->type != NDOF_MOTION) {
- return OPERATOR_CANCELLED;
- }
-
- const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- const wmNDOFMotionData *ndof = event->customdata;
- char xform_flag = 0;
-
- const bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
- const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
-
- /* we're panning here! so erase any leftover rotation from other operators */
- rv3d->rot_angle = 0.0f;
-
- if (!(has_translate || has_zoom)) {
- return OPERATOR_CANCELLED;
- }
-
- ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
-
- if (ndof->progress != P_FINISHING) {
- ScrArea *area = CTX_wm_area(C);
- ARegion *region = CTX_wm_region(C);
-
- if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, area, region, has_translate, has_zoom);
- xform_flag |= HAS_TRANSLATE;
- }
- }
-
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- if (xform_flag) {
- ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, xform_flag & HAS_TRANSLATE);
- }
-
- ED_region_tag_redraw(CTX_wm_region(C));
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "NDOF Pan View";
- ot->description = "Pan the view with the 3D mouse";
- ot->idname = "VIEW3D_OT_ndof_pan";
-
- /* api callbacks */
- ot->invoke = ndof_pan_invoke;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = 0;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name NDOF Transform All Operator
- * \{ */
-
-/**
- * wraps #ndof_orbit_zoom but never restrict to orbit.
- */
-static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- /* weak!, but it works */
- const int ndof_flag = U.ndof_flag;
- int ret;
-
- U.ndof_flag &= ~NDOF_MODE_ORBIT;
-
- ret = ndof_orbit_zoom_invoke(C, op, event);
-
- U.ndof_flag = ndof_flag;
-
- return ret;
-}
-
-void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "NDOF Transform View";
- ot->description = "Pan and rotate the view with the 3D mouse";
- ot->idname = "VIEW3D_OT_ndof_all";
-
- /* api callbacks */
- ot->invoke = ndof_all_invoke;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = 0;
-}
-
-#endif /* WITH_INPUT_NDOF */
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name View Move (Pan) Operator
- * \{ */
-
-/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
-
-void viewmove_modal_keymap(wmKeyConfig *keyconf)
-{
- static const EnumPropertyItem modal_items[] = {
- {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
-
- {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
- {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
-
- {0, NULL, 0, NULL, NULL},
- };
-
- wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Move Modal");
-
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) {
- return;
- }
-
- keymap = WM_modalkeymap_ensure(keyconf, "View3D Move Modal", modal_items);
-
- /* items for modal map */
- WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
- WM_modalkeymap_add_item(keymap, EVT_ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
-
- /* disabled mode switching for now, can re-implement better, later on */
-#if 0
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
- WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
- WM_modalkeymap_add_item(
- keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
-#endif
-
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_move");
-}
-
-static void viewmove_apply(ViewOpsData *vod, int x, int y)
-{
- if (ED_view3d_offset_lock_check(vod->v3d, vod->rv3d)) {
- vod->rv3d->ofs_lock[0] -= ((vod->prev.event_xy[0] - x) * 2.0f) / (float)vod->region->winx;
- vod->rv3d->ofs_lock[1] -= ((vod->prev.event_xy[1] - y) * 2.0f) / (float)vod->region->winy;
- }
- else if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
- const float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
- vod->rv3d->camdx += (vod->prev.event_xy[0] - x) / (vod->region->winx * zoomfac);
- vod->rv3d->camdy += (vod->prev.event_xy[1] - y) / (vod->region->winy * zoomfac);
- CLAMP(vod->rv3d->camdx, -1.0f, 1.0f);
- CLAMP(vod->rv3d->camdy, -1.0f, 1.0f);
- }
- else {
- float dvec[3];
- float mval_f[2];
-
- mval_f[0] = x - vod->prev.event_xy[0];
- mval_f[1] = y - vod->prev.event_xy[1];
- ED_view3d_win_to_delta(vod->region, mval_f, dvec, vod->init.zfac);
-
- add_v3_v3(vod->rv3d->ofs, dvec);
-
- if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->area, vod->region);
- }
- }
-
- vod->prev.event_xy[0] = x;
- vod->prev.event_xy[1] = y;
-
- ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
-
- ED_region_tag_redraw(vod->region);
-}
-
-static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
-
- ViewOpsData *vod = op->customdata;
- short event_code = VIEW_PASS;
- bool use_autokey = false;
- int ret = OPERATOR_RUNNING_MODAL;
-
- /* execute the events */
- if (event->type == MOUSEMOVE) {
- event_code = VIEW_APPLY;
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case VIEW_MODAL_CONFIRM:
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_ZOOM:
- WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- }
- }
- else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
- event_code = VIEW_CONFIRM;
- }
-
- if (event_code == VIEW_APPLY) {
- viewmove_apply(vod, event->xy[0], event->xy[1]);
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- use_autokey = true;
- }
- }
- else if (event_code == VIEW_CONFIRM) {
- use_autokey = true;
- ret = OPERATOR_FINISHED;
- }
-
- if (use_autokey) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
- }
-
- if (ret & OPERATOR_FINISHED) {
- viewops_data_free(C, op);
- }
-
- return ret;
-}
-
-static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ViewOpsData *vod;
-
- const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
-
- /* makes op->customdata */
- viewops_data_alloc(C, op);
- vod = op->customdata;
- if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_LOCATION) {
- viewops_data_free(C, op);
- return OPERATOR_PASS_THROUGH;
- }
-
- viewops_data_create(C,
- op,
- event,
- (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
- (use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
-
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
-
- if (event->type == MOUSEPAN) {
- /* invert it, trackpad scroll follows same principle as 2d windows this way */
- viewmove_apply(
- vod, 2 * event->xy[0] - event->prev_xy[0], 2 * event->xy[1] - event->prev_xy[1]);
-
- viewops_data_free(C, op);
-
- return OPERATOR_FINISHED;
- }
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static void viewmove_cancel(bContext *C, wmOperator *op)
-{
- viewops_data_free(C, op);
-}
-
-void VIEW3D_OT_move(wmOperatorType *ot)
-{
-
- /* identifiers */
- ot->name = "Pan View";
- ot->description = "Move the view";
- ot->idname = "VIEW3D_OT_move";
-
- /* api callbacks */
- ot->invoke = viewmove_invoke;
- ot->modal = viewmove_modal;
- ot->poll = ED_operator_region_view3d_active;
- ot->cancel = viewmove_cancel;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY;
-
- /* properties */
- view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name View Zoom Operator
- * \{ */
-
-/* #viewdolly_modal_keymap has an exact copy of this, apply fixes to both. */
-void viewzoom_modal_keymap(wmKeyConfig *keyconf)
-{
- static const EnumPropertyItem modal_items[] = {
- {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
-
- {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
- {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
-
- {0, NULL, 0, NULL, NULL},
- };
-
- wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Zoom Modal");
-
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) {
- return;
- }
-
- keymap = WM_modalkeymap_ensure(keyconf, "View3D Zoom Modal", modal_items);
-
- /* disabled mode switching for now, can re-implement better, later on */
-#if 0
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
-#endif
-
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
-}
-
-/**
- * \param zoom_xy: Optionally zoom to window location
- * (coords compatible w/ #wmEvent.xy). Use when not NULL.
- */
-static void view_zoom_to_window_xy_camera(Scene *scene,
- Depsgraph *depsgraph,
- View3D *v3d,
- ARegion *region,
- float dfac,
- const int zoom_xy[2])
-{
- RegionView3D *rv3d = region->regiondata;
- const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
- const float zoomfac_new = clamp_f(
- zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR);
- const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new);
-
- if (zoom_xy != NULL) {
- float zoomfac_px;
- rctf camera_frame_old;
- rctf camera_frame_new;
-
- const float pt_src[2] = {zoom_xy[0], zoom_xy[1]};
- float pt_dst[2];
- float delta_px[2];
-
- ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &camera_frame_old, false);
- BLI_rctf_translate(&camera_frame_old, region->winrct.xmin, region->winrct.ymin);
-
- rv3d->camzoom = camzoom_new;
- CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
-
- ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &camera_frame_new, false);
- BLI_rctf_translate(&camera_frame_new, region->winrct.xmin, region->winrct.ymin);
-
- BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
- sub_v2_v2v2(delta_px, pt_dst, pt_src);
-
- /* translate the camera offset using pixel space delta
- * mapped back to the camera (same logic as panning in camera view) */
- zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f;
-
- rv3d->camdx += delta_px[0] / (region->winx * zoomfac_px);
- rv3d->camdy += delta_px[1] / (region->winy * zoomfac_px);
- CLAMP(rv3d->camdx, -1.0f, 1.0f);
- CLAMP(rv3d->camdy, -1.0f, 1.0f);
- }
- else {
- rv3d->camzoom = camzoom_new;
- CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
- }
-}
-
-/**
- * \param zoom_xy: Optionally zoom to window location
- * (coords compatible w/ #wmEvent.xy). Use when not NULL.
- */
-static void view_zoom_to_window_xy_3d(ARegion *region, float dfac, const int zoom_xy[2])
-{
- RegionView3D *rv3d = region->regiondata;
- const float dist_new = rv3d->dist * dfac;
-
- if (zoom_xy != NULL) {
- float dvec[3];
- float tvec[3];
- float tpos[3];
- float mval_f[2];
-
- float zfac;
-
- negate_v3_v3(tpos, rv3d->ofs);
-
- mval_f[0] = (float)(((zoom_xy[0] - region->winrct.xmin) * 2) - region->winx) / 2.0f;
- mval_f[1] = (float)(((zoom_xy[1] - region->winrct.ymin) * 2) - region->winy) / 2.0f;
-
- /* Project cursor position into 3D space */
- zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL);
- ED_view3d_win_to_delta(region, mval_f, dvec, zfac);
-
- /* Calculate view target position for dolly */
- add_v3_v3v3(tvec, tpos, dvec);
- negate_v3(tvec);
-
- /* Offset to target position and dolly */
- copy_v3_v3(rv3d->ofs, tvec);
- rv3d->dist = dist_new;
-
- /* Calculate final offset */
- madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac);
- }
- else {
- rv3d->dist = dist_new;
- }
-}
-
-static float viewzoom_scale_value(const rcti *winrct,
- const eViewZoom_Style viewzoom,
- const bool zoom_invert,
- const bool zoom_invert_force,
- const int xy_curr[2],
- const int xy_init[2],
- const float val,
- const float val_orig,
- double *r_timer_lastdraw)
-{
- float zfac;
-
- if (viewzoom == USER_ZOOM_CONTINUE) {
- double time = PIL_check_seconds_timer();
- float time_step = (float)(time - *r_timer_lastdraw);
- float fac;
-
- if (U.uiflag & USER_ZOOM_HORIZ) {
- fac = (float)(xy_init[0] - xy_curr[0]);
- }
- else {
- fac = (float)(xy_init[1] - xy_curr[1]);
- }
-
- fac /= U.dpi_fac;
-
- if (zoom_invert != zoom_invert_force) {
- fac = -fac;
- }
-
- zfac = 1.0f + ((fac / 20.0f) * time_step);
- *r_timer_lastdraw = time;
- }
- else if (viewzoom == USER_ZOOM_SCALE) {
- /* method which zooms based on how far you move the mouse */
-
- const int ctr[2] = {
- BLI_rcti_cent_x(winrct),
- BLI_rcti_cent_y(winrct),
- };
- float len_new = (5 * U.dpi_fac) + ((float)len_v2v2_int(ctr, xy_curr) / U.dpi_fac);
- float len_old = (5 * U.dpi_fac) + ((float)len_v2v2_int(ctr, xy_init) / U.dpi_fac);
-
- /* intentionally ignore 'zoom_invert' for scale */
- if (zoom_invert_force) {
- SWAP(float, len_new, len_old);
- }
-
- zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val;
- }
- else { /* USER_ZOOM_DOLLY */
- float len_new = 5 * U.dpi_fac;
- float len_old = 5 * U.dpi_fac;
-
- if (U.uiflag & USER_ZOOM_HORIZ) {
- len_new += (winrct->xmax - (xy_curr[0])) / U.dpi_fac;
- len_old += (winrct->xmax - (xy_init[0])) / U.dpi_fac;
- }
- else {
- len_new += (winrct->ymax - (xy_curr[1])) / U.dpi_fac;
- len_old += (winrct->ymax - (xy_init[1])) / U.dpi_fac;
- }
-
- if (zoom_invert != zoom_invert_force) {
- SWAP(float, len_new, len_old);
- }
-
- zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val;
- }
-
- return zfac;
-}
-
-static float viewzoom_scale_value_offset(const rcti *winrct,
- const eViewZoom_Style viewzoom,
- const bool zoom_invert,
- const bool zoom_invert_force,
- const int xy_curr[2],
- const int xy_init[2],
- const int xy_offset[2],
- const float val,
- const float val_orig,
- double *r_timer_lastdraw)
-{
- const int xy_curr_offset[2] = {
- xy_curr[0] + xy_offset[0],
- xy_curr[1] + xy_offset[1],
- };
- const int xy_init_offset[2] = {
- xy_init[0] + xy_offset[0],
- xy_init[1] + xy_offset[1],
- };
- return viewzoom_scale_value(winrct,
- viewzoom,
- zoom_invert,
- zoom_invert_force,
- xy_curr_offset,
- xy_init_offset,
- val,
- val_orig,
- r_timer_lastdraw);
-}
-
-static void viewzoom_apply_camera(ViewOpsData *vod,
- const int xy[2],
- const eViewZoom_Style viewzoom,
- const bool zoom_invert,
- const bool zoom_to_pos)
-{
- float zfac;
- float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->init.camzoom) * 2.0f;
- float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
-
- zfac = viewzoom_scale_value_offset(&vod->region->winrct,
- viewzoom,
- zoom_invert,
- true,
- xy,
- vod->init.event_xy,
- vod->init.event_xy_offset,
- zoomfac,
- zoomfac_prev,
- &vod->prev.time);
-
- if (!ELEM(zfac, 1.0f, 0.0f)) {
- /* calculate inverted, then invert again (needed because of camera zoom scaling) */
- zfac = 1.0f / zfac;
- view_zoom_to_window_xy_camera(vod->scene,
- vod->depsgraph,
- vod->v3d,
- vod->region,
- zfac,
- zoom_to_pos ? vod->prev.event_xy : NULL);
- }
-
- ED_region_tag_redraw(vod->region);
-}
-
-static void viewzoom_apply_3d(ViewOpsData *vod,
- const int xy[2],
- const eViewZoom_Style viewzoom,
- const bool zoom_invert,
- const bool zoom_to_pos)
-{
- float zfac;
- float dist_range[2];
-
- ED_view3d_dist_range_get(vod->v3d, dist_range);
-
- zfac = viewzoom_scale_value_offset(&vod->region->winrct,
- viewzoom,
- zoom_invert,
- false,
- xy,
- vod->init.event_xy,
- vod->init.event_xy_offset,
- vod->rv3d->dist,
- vod->init.dist,
- &vod->prev.time);
-
- if (zfac != 1.0f) {
- const float zfac_min = dist_range[0] / vod->rv3d->dist;
- const float zfac_max = dist_range[1] / vod->rv3d->dist;
- CLAMP(zfac, zfac_min, zfac_max);
-
- view_zoom_to_window_xy_3d(vod->region, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
- }
-
- /* these limits were in old code too */
- CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]);
-
- if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->area, vod->region);
- }
-
- ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
-
- ED_region_tag_redraw(vod->region);
-}
-
-static void viewzoom_apply(ViewOpsData *vod,
- const int xy[2],
- const eViewZoom_Style viewzoom,
- const bool zoom_invert,
- const bool zoom_to_pos)
-{
- if ((vod->rv3d->persp == RV3D_CAMOB) &&
- (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0) {
- viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
- }
- else {
- viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
- }
-}
-
-static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ViewOpsData *vod = op->customdata;
- short event_code = VIEW_PASS;
- bool use_autokey = false;
- int ret = OPERATOR_RUNNING_MODAL;
-
- /* execute the events */
- if (event->type == TIMER && event->customdata == vod->timer) {
- /* continuous zoom */
- event_code = VIEW_APPLY;
- }
- else if (event->type == MOUSEMOVE) {
- event_code = VIEW_APPLY;
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case VIEW_MODAL_CONFIRM:
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- }
- }
- else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
- event_code = VIEW_CONFIRM;
- }
-
- if (event_code == VIEW_APPLY) {
- const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
- viewzoom_apply(vod,
- event->xy,
- (eViewZoom_Style)U.viewzoom,
- (U.uiflag & USER_ZOOM_INVERT) != 0,
- (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- use_autokey = true;
- }
- }
- else if (event_code == VIEW_CONFIRM) {
- use_autokey = true;
- ret = OPERATOR_FINISHED;
- }
-
- if (use_autokey) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
- }
-
- if (ret & OPERATOR_FINISHED) {
- viewops_data_free(C, op);
- }
-
- return ret;
-}
-
-static int viewzoom_exec(bContext *C, wmOperator *op)
-{
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d;
- RegionView3D *rv3d;
- ScrArea *area;
- ARegion *region;
- bool use_cam_zoom;
- float dist_range[2];
-
- const int delta = RNA_int_get(op->ptr, "delta");
- const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
-
- if (op->customdata) {
- ViewOpsData *vod = op->customdata;
-
- area = vod->area;
- region = vod->region;
- }
- else {
- area = CTX_wm_area(C);
- region = CTX_wm_region(C);
- }
-
- v3d = area->spacedata.first;
- rv3d = region->regiondata;
-
- use_cam_zoom = (rv3d->persp == RV3D_CAMOB) &&
- !(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
-
- int zoom_xy_buf[2];
- const int *zoom_xy = NULL;
- if (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
- zoom_xy_buf[0] = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") :
- region->winx / 2;
- zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") :
- region->winy / 2;
- zoom_xy = zoom_xy_buf;
- }
-
- ED_view3d_dist_range_get(v3d, dist_range);
-
- if (delta < 0) {
- const float step = 1.2f;
- /* this min and max is also in viewmove() */
- if (use_cam_zoom) {
- view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy);
- }
- else {
- if (rv3d->dist < dist_range[1]) {
- view_zoom_to_window_xy_3d(region, step, zoom_xy);
- }
- }
- }
- else {
- const float step = 1.0f / 1.2f;
- if (use_cam_zoom) {
- view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy);
- }
- else {
- if (rv3d->dist > dist_range[0]) {
- view_zoom_to_window_xy_3d(region, step, zoom_xy);
- }
- }
- }
-
- if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(area, region);
- }
-
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
-
- ED_region_tag_redraw(region);
-
- viewops_data_free(C, op);
-
- return OPERATOR_FINISHED;
-}
-
-/* viewdolly_invoke() copied this function, changes here may apply there */
-static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ViewOpsData *vod;
-
- const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
-
- /* makes op->customdata */
- viewops_data_alloc(C, op);
- viewops_data_create(C,
- op,
- event,
- (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
- (use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
- vod = op->customdata;
-
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
-
- /* if one or the other zoom position aren't set, set from event */
- if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
- RNA_int_set(op->ptr, "mx", event->xy[0]);
- RNA_int_set(op->ptr, "my", event->xy[1]);
- }
-
- if (RNA_struct_property_is_set(op->ptr, "delta")) {
- viewzoom_exec(C, op);
- }
- else {
- if (ELEM(event->type, MOUSEZOOM, MOUSEPAN)) {
-
- if (U.uiflag & USER_ZOOM_HORIZ) {
- vod->init.event_xy[0] = vod->prev.event_xy[0] = event->xy[0];
- }
- else {
- /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
- vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->xy[0] -
- event->prev_xy[0];
- }
- viewzoom_apply(vod,
- event->prev_xy,
- USER_ZOOM_DOLLY,
- (U.uiflag & USER_ZOOM_INVERT) != 0,
- (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
-
- viewops_data_free(C, op);
- return OPERATOR_FINISHED;
- }
-
- if (U.viewzoom == USER_ZOOM_CONTINUE) {
- /* needs a timer to continue redrawing */
- vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
- vod->prev.time = PIL_check_seconds_timer();
- }
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- return OPERATOR_FINISHED;
-}
-
-static void viewzoom_cancel(bContext *C, wmOperator *op)
-{
- viewops_data_free(C, op);
-}
-
-void VIEW3D_OT_zoom(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Zoom View";
- ot->description = "Zoom in/out in the view";
- ot->idname = "VIEW3D_OT_zoom";
-
- /* api callbacks */
- ot->invoke = viewzoom_invoke;
- ot->exec = viewzoom_exec;
- ot->modal = viewzoom_modal;
- ot->poll = view3d_zoom_or_dolly_poll;
- ot->cancel = viewzoom_cancel;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY;
-
- /* properties */
- view3d_operator_properties_common(
- ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name View Dolly Operator
- *
- * Like zoom but translates the view offset along the view direction
- * which avoids #RegionView3D.dist approaching zero.
- * \{ */
-
-/* This is an exact copy of #viewzoom_modal_keymap. */
-void viewdolly_modal_keymap(wmKeyConfig *keyconf)
-{
- static const EnumPropertyItem modal_items[] = {
- {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
-
- {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
- {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
-
- {0, NULL, 0, NULL, NULL},
- };
-
- wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Dolly Modal");
-
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) {
- return;
- }
-
- keymap = WM_modalkeymap_ensure(keyconf, "View3D Dolly Modal", modal_items);
-
- /* disabled mode switching for now, can re-implement better, later on */
-#if 0
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
-#endif
-
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly");
-}
-
-static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
-{
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- if (ED_view3d_offset_lock_check(v3d, rv3d)) {
- BKE_report(op->reports, RPT_WARNING, "Cannot dolly when the view offset is locked");
- return true;
- }
- return false;
-}
-
-static void view_dolly_to_vector_3d(ARegion *region,
- const float orig_ofs[3],
- const float dvec[3],
- float dfac)
-{
- RegionView3D *rv3d = region->regiondata;
- madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac));
-}
-
-static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const bool zoom_invert)
-{
- float zfac = 1.0;
-
- {
- float len1, len2;
-
- if (U.uiflag & USER_ZOOM_HORIZ) {
- len1 = (vod->region->winrct.xmax - xy[0]) + 5;
- len2 = (vod->region->winrct.xmax - vod->init.event_xy[0]) + 5;
- }
- else {
- len1 = (vod->region->winrct.ymax - xy[1]) + 5;
- len2 = (vod->region->winrct.ymax - vod->init.event_xy[1]) + 5;
- }
- if (zoom_invert) {
- SWAP(float, len1, len2);
- }
-
- zfac = 1.0f + ((len1 - len2) * 0.01f * vod->rv3d->dist);
- }
-
- if (zfac != 1.0f) {
- view_dolly_to_vector_3d(vod->region, vod->init.ofs, vod->init.mousevec, zfac);
- }
-
- if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->area, vod->region);
- }
-
- ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
-
- ED_region_tag_redraw(vod->region);
-}
-
-static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ViewOpsData *vod = op->customdata;
- short event_code = VIEW_PASS;
- bool use_autokey = false;
- int ret = OPERATOR_RUNNING_MODAL;
-
- /* execute the events */
- if (event->type == MOUSEMOVE) {
- event_code = VIEW_APPLY;
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case VIEW_MODAL_CONFIRM:
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- }
- }
- else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
- event_code = VIEW_CONFIRM;
- }
-
- if (event_code == VIEW_APPLY) {
- viewdolly_apply(vod, event->xy, (U.uiflag & USER_ZOOM_INVERT) != 0);
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- use_autokey = true;
- }
- }
- else if (event_code == VIEW_CONFIRM) {
- use_autokey = true;
- ret = OPERATOR_FINISHED;
- }
-
- if (use_autokey) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
- }
-
- if (ret & OPERATOR_FINISHED) {
- viewops_data_free(C, op);
- }
-
- return ret;
-}
-
-static int viewdolly_exec(bContext *C, wmOperator *op)
-{
- View3D *v3d;
- RegionView3D *rv3d;
- ScrArea *area;
- ARegion *region;
- float mousevec[3];
-
- const int delta = RNA_int_get(op->ptr, "delta");
-
- if (op->customdata) {
- ViewOpsData *vod = op->customdata;
-
- area = vod->area;
- region = vod->region;
- copy_v3_v3(mousevec, vod->init.mousevec);
- }
- else {
- area = CTX_wm_area(C);
- region = CTX_wm_region(C);
- negate_v3_v3(mousevec, ((RegionView3D *)region->regiondata)->viewinv[2]);
- normalize_v3(mousevec);
- }
-
- v3d = area->spacedata.first;
- rv3d = region->regiondata;
-
- const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
-
- /* overwrite the mouse vector with the view direction (zoom into the center) */
- if ((use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
- normalize_v3_v3(mousevec, rv3d->viewinv[2]);
- negate_v3(mousevec);
- }
-
- view_dolly_to_vector_3d(region, rv3d->ofs, mousevec, delta < 0 ? 1.8f : 0.2f);
-
- if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(area, region);
- }
-
- ED_view3d_camera_lock_sync(CTX_data_ensure_evaluated_depsgraph(C), v3d, rv3d);
-
- ED_region_tag_redraw(region);
-
- viewops_data_free(C, op);
-
- return OPERATOR_FINISHED;
-}
-
-/* copied from viewzoom_invoke(), changes here may apply there */
-static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ViewOpsData *vod;
-
- if (viewdolly_offset_lock_check(C, op)) {
- return OPERATOR_CANCELLED;
- }
-
- /* makes op->customdata */
- viewops_data_alloc(C, op);
- vod = op->customdata;
-
- /* poll should check but in some cases fails, see poll func for details */
- if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_ROTATION) {
- viewops_data_free(C, op);
- return OPERATOR_PASS_THROUGH;
- }
-
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
-
- /* needs to run before 'viewops_data_create' so the backup 'rv3d->ofs' is correct */
- /* switch from camera view when: */
- if (vod->rv3d->persp != RV3D_PERSP) {
- if (vod->rv3d->persp == RV3D_CAMOB) {
- /* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
- const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ED_view3d_persp_switch_from_camera(depsgraph, vod->v3d, vod->rv3d, RV3D_PERSP);
- }
- else {
- vod->rv3d->persp = RV3D_PERSP;
- }
- ED_region_tag_redraw(vod->region);
- }
-
- const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
-
- viewops_data_create(C,
- op,
- event,
- (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
- (use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
-
- /* if one or the other zoom position aren't set, set from event */
- if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
- RNA_int_set(op->ptr, "mx", event->xy[0]);
- RNA_int_set(op->ptr, "my", event->xy[1]);
- }
-
- if (RNA_struct_property_is_set(op->ptr, "delta")) {
- viewdolly_exec(C, op);
- }
- else {
- /* overwrite the mouse vector with the view direction (zoom into the center) */
- if ((use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
- negate_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
- normalize_v3(vod->init.mousevec);
- }
-
- if (event->type == MOUSEZOOM) {
- /* Bypass Zoom invert flag for track pads (pass false always) */
-
- if (U.uiflag & USER_ZOOM_HORIZ) {
- vod->init.event_xy[0] = vod->prev.event_xy[0] = event->xy[0];
- }
- else {
- /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
- vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->xy[0] -
- event->prev_xy[0];
- }
- viewdolly_apply(vod, event->prev_xy, (U.uiflag & USER_ZOOM_INVERT) == 0);
-
- viewops_data_free(C, op);
- return OPERATOR_FINISHED;
- }
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
- return OPERATOR_FINISHED;
-}
-
-static void viewdolly_cancel(bContext *C, wmOperator *op)
-{
- viewops_data_free(C, op);
-}
-
-void VIEW3D_OT_dolly(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Dolly View";
- ot->description = "Dolly in/out in the view";
- ot->idname = "VIEW3D_OT_dolly";
-
- /* api callbacks */
- ot->invoke = viewdolly_invoke;
- ot->exec = viewdolly_exec;
- ot->modal = viewdolly_modal;
- ot->poll = ED_operator_region_view3d_active;
- ot->cancel = viewdolly_cancel;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY;
-
- /* properties */
- view3d_operator_properties_common(
- ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name View All Operator
- *
- * Move & Zoom the view to fit all of its contents.
- * \{ */
-
-static bool view3d_object_skip_minmax(const View3D *v3d,
- const RegionView3D *rv3d,
- const Object *ob,
- const bool skip_camera,
- bool *r_only_center)
-{
- BLI_assert(ob->id.orig_id == NULL);
- *r_only_center = false;
-
- if (skip_camera && (ob == v3d->camera)) {
- return true;
- }
-
- if ((ob->type == OB_EMPTY) && (ob->empty_drawtype == OB_EMPTY_IMAGE) &&
- !BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d)) {
- *r_only_center = true;
- return false;
- }
-
- return false;
-}
-
-static void view3d_object_calc_minmax(Depsgraph *depsgraph,
- Scene *scene,
- Object *ob_eval,
- const bool only_center,
- float min[3],
- float max[3])
-{
- /* Account for duplis. */
- if (BKE_object_minmax_dupli(depsgraph, scene, ob_eval, min, max, false) == 0) {
- /* Use if duplis aren't found. */
- if (only_center) {
- minmax_v3v3_v3(min, max, ob_eval->obmat[3]);
- }
- else {
- BKE_object_minmax(ob_eval, min, max, false);
- }
- }
-}
-
-static void view3d_from_minmax(bContext *C,
- View3D *v3d,
- ARegion *region,
- const float min[3],
- const float max[3],
- bool ok_dist,
- const int smooth_viewtx)
-{
- RegionView3D *rv3d = region->regiondata;
- float afm[3];
- float size;
-
- ED_view3d_smooth_view_force_finish(C, v3d, region);
-
- /* SMOOTHVIEW */
- float new_ofs[3];
- float new_dist;
-
- sub_v3_v3v3(afm, max, min);
- size = max_fff(afm[0], afm[1], afm[2]);
-
- if (ok_dist) {
- char persp;
-
- if (rv3d->is_persp) {
- if (rv3d->persp == RV3D_CAMOB && ED_view3d_camera_lock_check(v3d, rv3d)) {
- persp = RV3D_CAMOB;
- }
- else {
- persp = RV3D_PERSP;
- }
- }
- else { /* ortho */
- if (size < 0.0001f) {
- /* bounding box was a single point so do not zoom */
- ok_dist = false;
- }
- else {
- /* adjust zoom so it looks nicer */
- persp = RV3D_ORTHO;
- }
- }
-
- if (ok_dist) {
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- new_dist = ED_view3d_radius_to_dist(
- v3d, region, depsgraph, persp, true, (size / 2) * VIEW3D_MARGIN);
- if (rv3d->is_persp) {
- /* don't zoom closer than the near clipping plane */
- new_dist = max_ff(new_dist, v3d->clip_start * 1.5f);
- }
- }
- }
-
- mid_v3_v3v3(new_ofs, min, max);
- negate_v3(new_ofs);
-
- if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) {
- rv3d->persp = RV3D_PERSP;
- ED_view3d_smooth_view(C,
- v3d,
- region,
- smooth_viewtx,
- &(const V3D_SmoothParams){
- .camera_old = v3d->camera,
- .ofs = new_ofs,
- .dist = ok_dist ? &new_dist : NULL,
- });
- }
- else {
- ED_view3d_smooth_view(C,
- v3d,
- region,
- smooth_viewtx,
- &(const V3D_SmoothParams){
- .ofs = new_ofs,
- .dist = ok_dist ? &new_dist : NULL,
- });
- }
-
- /* Smooth-view does view-lock #RV3D_BOXVIEW copy. */
-}
-
-/**
- * Same as #view3d_from_minmax but for all regions (except cameras).
- */
-static void view3d_from_minmax_multi(bContext *C,
- View3D *v3d,
- const float min[3],
- const float max[3],
- const bool ok_dist,
- const int smooth_viewtx)
-{
- ScrArea *area = CTX_wm_area(C);
- ARegion *region;
- for (region = area->regionbase.first; region; region = region->next) {
- if (region->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = region->regiondata;
- /* when using all regions, don't jump out of camera view,
- * but _do_ allow locked cameras to be moved */
- if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
- view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx);
- }
- }
- }
-}
-
-static int view3d_all_exec(bContext *C, wmOperator *op)
-{
- ARegion *region = CTX_wm_region(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
- Base *base_eval;
- const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
- const bool skip_camera = (ED_view3d_camera_lock_check(v3d, region->regiondata) ||
- /* any one of the regions may be locked */
- (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
- const bool center = RNA_boolean_get(op->ptr, "center");
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- float min[3], max[3];
- bool changed = false;
-
- if (center) {
- /* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */
- View3DCursor *cursor = &scene->cursor;
- zero_v3(min);
- zero_v3(max);
- zero_v3(cursor->location);
- float mat3[3][3];
- unit_m3(mat3);
- BKE_scene_cursor_mat3_to_rot(cursor, mat3, false);
- }
- else {
- INIT_MINMAX(min, max);
- }
-
- for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
- if (BASE_VISIBLE(v3d, base_eval)) {
- bool only_center = false;
- Object *ob = DEG_get_original_object(base_eval->object);
- if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) {
- continue;
- }
- view3d_object_calc_minmax(depsgraph, scene, base_eval->object, only_center, min, max);
- changed = true;
- }
- }
-
- if (center) {
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- WM_msg_publish_rna_prop(mbus, &scene->id, &scene->cursor, View3DCursor, location);
-
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- }
-
- if (!changed) {
- ED_region_tag_redraw(region);
- /* TODO: should this be cancel?
- * I think no, because we always move the cursor, with or without
- * object, but in this case there is no change in the scene,
- * only the cursor so I choice a ED_region_tag like
- * view3d_smooth_view do for the center_cursor.
- * See bug T22640.
- */
- return OPERATOR_FINISHED;
- }
-
- if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
- /* This is an approximation, see function documentation for details. */
- ED_view3d_clipping_clamp_minmax(rv3d, min, max);
- }
-
- if (use_all_regions) {
- view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx);
- }
- else {
- view3d_from_minmax(C, v3d, region, min, max, true, smooth_viewtx);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_view_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Frame All";
- ot->description = "View all objects in scene";
- ot->idname = "VIEW3D_OT_view_all";
-
- /* api callbacks */
- ot->exec = view3d_all_exec;
- ot->poll = ED_operator_region_view3d_active;
-
- /* flags */
- ot->flag = 0;
-
- /* properties */
- view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
- RNA_def_boolean(ot->srna, "center", 0, "Center", "");
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Frame Selected Operator
- *
- * Move & Zoom the view to fit selected contents.
- * \{ */
-
-static int viewselected_exec(bContext *C, wmOperator *op)
-{
- ARegion *region = CTX_wm_region(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
- Object *ob_eval = OBACT(view_layer_eval);
- Object *obedit = CTX_data_edit_object(C);
- const bGPdata *gpd_eval = ob_eval && (ob_eval->type == OB_GPENCIL) ? ob_eval->data : NULL;
- const bool is_gp_edit = gpd_eval ? GPENCIL_ANY_MODE(gpd_eval) : false;
- const bool is_face_map = ((is_gp_edit == false) && region->gizmo_map &&
- WM_gizmomap_is_any_selected(region->gizmo_map));
- float min[3], max[3];
- bool ok = false, ok_dist = true;
- const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
- const bool skip_camera = (ED_view3d_camera_lock_check(v3d, region->regiondata) ||
- /* any one of the regions may be locked */
- (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- INIT_MINMAX(min, max);
- if (is_face_map) {
- ob_eval = NULL;
- }
-
- if (ob_eval && (ob_eval->mode & OB_MODE_WEIGHT_PAINT)) {
- /* hard-coded exception, we look for the one selected armature */
- /* this is weak code this way, we should make a generic
- * active/selection callback interface once... */
- Base *base_eval;
- for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
- if (BASE_SELECTED_EDITABLE(v3d, base_eval)) {
- if (base_eval->object->type == OB_ARMATURE) {
- if (base_eval->object->mode & OB_MODE_POSE) {
- break;
- }
- }
- }
- }
- if (base_eval) {
- ob_eval = base_eval->object;
- }
- }
-
- if (is_gp_edit) {
- CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
- /* we're only interested in selected points here... */
- if ((gps->flag & GP_STROKE_SELECT) && (gps->flag & GP_STROKE_3DSPACE)) {
- ok |= BKE_gpencil_stroke_minmax(gps, true, min, max);
- }
- if (gps->editcurve != NULL) {
- for (int i = 0; i < gps->editcurve->tot_curve_points; i++) {
- BezTriple *bezt = &gps->editcurve->curve_points[i].bezt;
- if ((bezt->f1 & SELECT)) {
- minmax_v3v3_v3(min, max, bezt->vec[0]);
- ok = true;
- }
- if ((bezt->f2 & SELECT)) {
- minmax_v3v3_v3(min, max, bezt->vec[1]);
- ok = true;
- }
- if ((bezt->f3 & SELECT)) {
- minmax_v3v3_v3(min, max, bezt->vec[2]);
- ok = true;
- }
- }
- }
- }
- CTX_DATA_END;
-
- if ((ob_eval) && (ok)) {
- mul_m4_v3(ob_eval->obmat, min);
- mul_m4_v3(ob_eval->obmat, max);
- }
- }
- else if (is_face_map) {
- ok = WM_gizmomap_minmax(region->gizmo_map, true, true, min, max);
- }
- else if (obedit) {
- /* only selected */
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, v3d, obedit->type, obedit->mode, ob_eval_iter) {
- ok |= ED_view3d_minmax_verts(ob_eval_iter, min, max);
- }
- FOREACH_OBJECT_IN_MODE_END;
- }
- else if (ob_eval && (ob_eval->mode & OB_MODE_POSE)) {
- FOREACH_OBJECT_IN_MODE_BEGIN (
- view_layer_eval, v3d, ob_eval->type, ob_eval->mode, ob_eval_iter) {
- ok |= BKE_pose_minmax(ob_eval_iter, min, max, true, true);
- }
- FOREACH_OBJECT_IN_MODE_END;
- }
- else if (BKE_paint_select_face_test(ob_eval)) {
- ok = paintface_minmax(ob_eval, min, max);
- }
- else if (ob_eval && (ob_eval->mode & OB_MODE_PARTICLE_EDIT)) {
- ok = PE_minmax(depsgraph, scene, CTX_data_view_layer(C), min, max);
- }
- else if (ob_eval && (ob_eval->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT |
- OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
- BKE_paint_stroke_get_average(scene, ob_eval, min);
- copy_v3_v3(max, min);
- ok = true;
- ok_dist = 0; /* don't zoom */
- }
- else {
- Base *base_eval;
- for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
- if (BASE_SELECTED(v3d, base_eval)) {
- bool only_center = false;
- Object *ob = DEG_get_original_object(base_eval->object);
- if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) {
- continue;
- }
- view3d_object_calc_minmax(depsgraph, scene, base_eval->object, only_center, min, max);
- ok = 1;
- }
- }
- }
-
- if (ok == 0) {
- return OPERATOR_FINISHED;
- }
-
- if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
- /* This is an approximation, see function documentation for details. */
- ED_view3d_clipping_clamp_minmax(rv3d, min, max);
- }
-
- if (use_all_regions) {
- view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx);
- }
- else {
- view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_view_selected(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Frame Selected";
- ot->description = "Move the view to the selection center";
- ot->idname = "VIEW3D_OT_view_selected";
-
- /* api callbacks */
- ot->exec = viewselected_exec;
- ot->poll = view3d_zoom_or_dolly_poll;
-
- /* flags */
- ot->flag = 0;
-
- /* properties */
- view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
-}
-
-/** \} */
-
/* -------------------------------------------------------------------- */
/** \name View Lock Clear Operator
* \{ */
@@ -3256,103 +179,6 @@ void VIEW3D_OT_view_lock_to_active(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name View Center Cursor Operator
- * \{ */
-
-static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
-{
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Scene *scene = CTX_data_scene(C);
-
- if (rv3d) {
- ARegion *region = CTX_wm_region(C);
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- ED_view3d_smooth_view_force_finish(C, v3d, region);
-
- /* non camera center */
- float new_ofs[3];
- negate_v3_v3(new_ofs, scene->cursor.location);
- ED_view3d_smooth_view(
- C, v3d, region, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs});
-
- /* Smooth view does view-lock #RV3D_BOXVIEW copy. */
- }
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Center View to Cursor";
- ot->description = "Center the view so that the cursor is in the middle of the view";
- ot->idname = "VIEW3D_OT_view_center_cursor";
-
- /* api callbacks */
- ot->exec = viewcenter_cursor_exec;
- ot->poll = view3d_pan_poll;
-
- /* flags */
- ot->flag = 0;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name View Center Pick Operator
- * \{ */
-
-static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- ARegion *region = CTX_wm_region(C);
-
- if (rv3d) {
- struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- float new_ofs[3];
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- ED_view3d_smooth_view_force_finish(C, v3d, region);
-
- view3d_operator_needs_opengl(C);
-
- if (ED_view3d_autodist(depsgraph, region, v3d, event->mval, new_ofs, false, NULL)) {
- /* pass */
- }
- else {
- /* fallback to simple pan */
- negate_v3_v3(new_ofs, rv3d->ofs);
- ED_view3d_win_to_3d_int(v3d, region, new_ofs, event->mval, new_ofs);
- }
- negate_v3(new_ofs);
- ED_view3d_smooth_view(
- C, v3d, region, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs});
- }
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Center View to Mouse";
- ot->description = "Center the view to the Z-depth position under the mouse cursor";
- ot->idname = "VIEW3D_OT_view_center_pick";
-
- /* api callbacks */
- ot->invoke = viewcenter_pick_invoke;
- ot->poll = view3d_pan_poll;
-
- /* flags */
- ot->flag = 0;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Frame Camera Bounds Operator
* \{ */
@@ -3591,189 +417,6 @@ void VIEW3D_OT_clear_render_border(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Border Zoom Operator
- * \{ */
-
-static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
-{
- ARegion *region = CTX_wm_region(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- /* Zooms in on a border drawn by the user */
- rcti rect;
- float dvec[3], vb[2], xscale, yscale;
- float dist_range[2];
-
- /* SMOOTHVIEW */
- float new_dist;
- float new_ofs[3];
-
- /* ZBuffer depth vars */
- float depth_close = FLT_MAX;
- float cent[2], p[3];
-
- /* NOTE: otherwise opengl won't work. */
- view3d_operator_needs_opengl(C);
-
- /* get box select values using rna */
- WM_operator_properties_border_to_rcti(op, &rect);
-
- /* check if zooming in/out view */
- const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out");
-
- ED_view3d_dist_range_get(v3d, dist_range);
-
- ED_view3d_depth_override(
- CTX_data_ensure_evaluated_depsgraph(C), region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, NULL);
- {
- /* avoid allocating the whole depth buffer */
- ViewDepths depth_temp = {0};
-
- /* avoid view3d_update_depths() for speed. */
- view3d_depths_rect_create(region, &rect, &depth_temp);
-
- /* find the closest Z pixel */
- depth_close = view3d_depth_near(&depth_temp);
-
- MEM_SAFE_FREE(depth_temp.depths);
- }
-
- /* Resize border to the same ratio as the window. */
- {
- const float region_aspect = (float)region->winx / (float)region->winy;
- if (((float)BLI_rcti_size_x(&rect) / (float)BLI_rcti_size_y(&rect)) < region_aspect) {
- BLI_rcti_resize_x(&rect, (int)(BLI_rcti_size_y(&rect) * region_aspect));
- }
- else {
- BLI_rcti_resize_y(&rect, (int)(BLI_rcti_size_x(&rect) / region_aspect));
- }
- }
-
- cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
- cent[1] = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
-
- if (rv3d->is_persp) {
- float p_corner[3];
-
- /* no depths to use, we can't do anything! */
- if (depth_close == FLT_MAX) {
- BKE_report(op->reports, RPT_ERROR, "Depth too large");
- return OPERATOR_CANCELLED;
- }
- /* convert border to 3d coordinates */
- if ((!ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p)) ||
- (!ED_view3d_unproject_v3(region, rect.xmin, rect.ymin, depth_close, p_corner))) {
- return OPERATOR_CANCELLED;
- }
-
- sub_v3_v3v3(dvec, p, p_corner);
- negate_v3_v3(new_ofs, p);
-
- new_dist = len_v3(dvec);
-
- /* Account for the lens, without this a narrow lens zooms in too close. */
- new_dist *= (v3d->lens / DEFAULT_SENSOR_WIDTH);
-
- /* ignore dist_range min */
- dist_range[0] = v3d->clip_start * 1.5f;
- }
- else { /* orthographic */
- /* find the current window width and height */
- vb[0] = region->winx;
- vb[1] = region->winy;
-
- new_dist = rv3d->dist;
-
- /* convert the drawn rectangle into 3d space */
- if (depth_close != FLT_MAX &&
- ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p)) {
- negate_v3_v3(new_ofs, p);
- }
- else {
- float mval_f[2];
- float zfac;
-
- /* We can't use the depth, fallback to the old way that doesn't set the center depth */
- copy_v3_v3(new_ofs, rv3d->ofs);
-
- {
- float tvec[3];
- negate_v3_v3(tvec, new_ofs);
- zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
- }
-
- mval_f[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f;
- mval_f[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f;
- ED_view3d_win_to_delta(region, mval_f, dvec, zfac);
- /* center the view to the center of the rectangle */
- sub_v3_v3(new_ofs, dvec);
- }
-
- /* work out the ratios, so that everything selected fits when we zoom */
- xscale = (BLI_rcti_size_x(&rect) / vb[0]);
- yscale = (BLI_rcti_size_y(&rect) / vb[1]);
- new_dist *= max_ff(xscale, yscale);
- }
-
- if (!zoom_in) {
- sub_v3_v3v3(dvec, new_ofs, rv3d->ofs);
- new_dist = rv3d->dist * (rv3d->dist / new_dist);
- add_v3_v3v3(new_ofs, rv3d->ofs, dvec);
- }
-
- /* clamp after because we may have been zooming out */
- CLAMP(new_dist, dist_range[0], dist_range[1]);
-
- /* TODO(campbell): 'is_camera_lock' not currently working well. */
- const bool is_camera_lock = ED_view3d_camera_lock_check(v3d, rv3d);
- if ((rv3d->persp == RV3D_CAMOB) && (is_camera_lock == false)) {
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, RV3D_PERSP);
- }
-
- ED_view3d_smooth_view(C,
- v3d,
- region,
- smooth_viewtx,
- &(const V3D_SmoothParams){
- .ofs = new_ofs,
- .dist = &new_dist,
- });
-
- if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(CTX_wm_area(C), region);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_zoom_border(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Zoom to Border";
- ot->description = "Zoom in the view to the nearest object contained in the border";
- ot->idname = "VIEW3D_OT_zoom_border";
-
- /* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
- ot->exec = view3d_zoom_border_exec;
- ot->modal = WM_gesture_box_modal;
- ot->cancel = WM_gesture_box_cancel;
-
- ot->poll = view3d_zoom_or_dolly_poll;
-
- /* flags */
- ot->flag = 0;
-
- /* properties */
- WM_operator_properties_gesture_box_zoom(ot);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Set Camera Zoom 1:1 Operator
*
* Sets the view to 1:1 camera/render-pixel.
@@ -3830,838 +473,6 @@ void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name View Axis Operator
- * \{ */
-
-static const EnumPropertyItem prop_view_items[] = {
- {RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View from the left"},
- {RV3D_VIEW_RIGHT, "RIGHT", ICON_TRIA_RIGHT, "Right", "View from the right"},
- {RV3D_VIEW_BOTTOM, "BOTTOM", ICON_TRIA_DOWN, "Bottom", "View from the bottom"},
- {RV3D_VIEW_TOP, "TOP", ICON_TRIA_UP, "Top", "View from the top"},
- {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View from the front"},
- {RV3D_VIEW_BACK, "BACK", 0, "Back", "View from the back"},
- {0, NULL, 0, NULL, NULL},
-};
-
-/* would like to make this a generic function - outside of transform */
-
-/**
- * \param align_to_quat: When not NULL, set the axis relative to this rotation.
- */
-static void axis_set_view(bContext *C,
- View3D *v3d,
- ARegion *region,
- const float quat_[4],
- char view,
- char view_axis_roll,
- int perspo,
- const float *align_to_quat,
- const int smooth_viewtx)
-{
- RegionView3D *rv3d = region->regiondata; /* no NULL check is needed, poll checks */
- float quat[4];
- const short orig_persp = rv3d->persp;
-
- normalize_qt_qt(quat, quat_);
-
- if (align_to_quat) {
- mul_qt_qtqt(quat, quat, align_to_quat);
- rv3d->view = view = RV3D_VIEW_USER;
- rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
- }
-
- if (align_to_quat == NULL) {
- rv3d->view = view;
- rv3d->view_axis_roll = view_axis_roll;
- }
-
- if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) {
- ED_region_tag_redraw(region);
- return;
- }
-
- if (U.uiflag & USER_AUTOPERSP) {
- rv3d->persp = RV3D_VIEW_IS_AXIS(view) ? RV3D_ORTHO : perspo;
- }
- else if (rv3d->persp == RV3D_CAMOB) {
- rv3d->persp = perspo;
- }
-
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
- /* to camera */
- ED_view3d_smooth_view(C,
- v3d,
- region,
- smooth_viewtx,
- &(const V3D_SmoothParams){
- .camera_old = v3d->camera,
- .ofs = rv3d->ofs,
- .quat = quat,
- });
- }
- else if (orig_persp == RV3D_CAMOB && v3d->camera) {
- /* from camera */
- float ofs[3], dist;
-
- copy_v3_v3(ofs, rv3d->ofs);
- dist = rv3d->dist;
-
- /* so we animate _from_ the camera location */
- Object *camera_eval = DEG_get_evaluated_object(CTX_data_ensure_evaluated_depsgraph(C),
- v3d->camera);
- ED_view3d_from_object(camera_eval, rv3d->ofs, NULL, &rv3d->dist, NULL);
-
- ED_view3d_smooth_view(C,
- v3d,
- region,
- smooth_viewtx,
- &(const V3D_SmoothParams){
- .camera_old = camera_eval,
- .ofs = ofs,
- .quat = quat,
- .dist = &dist,
- });
- }
- else {
- /* rotate around selection */
- const float *dyn_ofs_pt = NULL;
- float dyn_ofs[3];
-
- if (U.uiflag & USER_ORBIT_SELECTION) {
- if (view3d_orbit_calc_center(C, dyn_ofs)) {
- negate_v3(dyn_ofs);
- dyn_ofs_pt = dyn_ofs;
- }
- }
-
- /* no camera involved */
- ED_view3d_smooth_view(C,
- v3d,
- region,
- smooth_viewtx,
- &(const V3D_SmoothParams){
- .quat = quat,
- .dyn_ofs = dyn_ofs_pt,
- });
- }
-}
-
-static int view_axis_exec(bContext *C, wmOperator *op)
-{
- View3D *v3d;
- ARegion *region;
- RegionView3D *rv3d;
- static int perspo = RV3D_PERSP;
- int viewnum;
- int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- /* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &region);
- rv3d = region->regiondata;
-
- ED_view3d_smooth_view_force_finish(C, v3d, region);
-
- viewnum = RNA_enum_get(op->ptr, "type");
-
- float align_quat_buf[4];
- float *align_quat = NULL;
-
- if (RNA_boolean_get(op->ptr, "align_active")) {
- /* align to active object */
- Object *obact = CTX_data_active_object(C);
- if (obact != NULL) {
- float twmat[3][3];
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
- /* same as transform gizmo when normal is set */
- ED_getTransformOrientationMatrix(view_layer, v3d, obact, obedit, V3D_AROUND_ACTIVE, twmat);
- align_quat = align_quat_buf;
- mat3_to_quat(align_quat, twmat);
- invert_qt_normalized(align_quat);
- }
- }
-
- if (RNA_boolean_get(op->ptr, "relative")) {
- float quat_rotate[4];
- float quat_test[4];
-
- if (viewnum == RV3D_VIEW_LEFT) {
- axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], -M_PI / 2.0f);
- }
- else if (viewnum == RV3D_VIEW_RIGHT) {
- axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], M_PI / 2.0f);
- }
- else if (viewnum == RV3D_VIEW_TOP) {
- axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], -M_PI / 2.0f);
- }
- else if (viewnum == RV3D_VIEW_BOTTOM) {
- axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI / 2.0f);
- }
- else if (viewnum == RV3D_VIEW_FRONT) {
- unit_qt(quat_rotate);
- }
- else if (viewnum == RV3D_VIEW_BACK) {
- axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI);
- }
- else {
- BLI_assert(0);
- }
-
- mul_qt_qtqt(quat_test, rv3d->viewquat, quat_rotate);
-
- float angle_best = FLT_MAX;
- int view_best = -1;
- int view_axis_roll_best = -1;
- for (int i = RV3D_VIEW_FRONT; i <= RV3D_VIEW_BOTTOM; i++) {
- for (int j = RV3D_VIEW_AXIS_ROLL_0; j <= RV3D_VIEW_AXIS_ROLL_270; j++) {
- float quat_axis[4];
- ED_view3d_quat_from_axis_view(i, j, quat_axis);
- if (align_quat) {
- mul_qt_qtqt(quat_axis, quat_axis, align_quat);
- }
- const float angle_test = fabsf(angle_signed_qtqt(quat_axis, quat_test));
- if (angle_best > angle_test) {
- angle_best = angle_test;
- view_best = i;
- view_axis_roll_best = j;
- }
- }
- }
- if (view_best == -1) {
- view_best = RV3D_VIEW_FRONT;
- view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
- }
-
- /* Disallow non-upright views in turn-table modes,
- * it's too difficult to navigate out of them. */
- if ((U.flag & USER_TRACKBALL) == 0) {
- if (!ELEM(view_best, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
- view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
- }
- }
-
- viewnum = view_best;
- view_axis_roll = view_axis_roll_best;
- }
-
- /* Use this to test if we started out with a camera */
- const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo;
- float quat[4];
- ED_view3d_quat_from_axis_view(viewnum, view_axis_roll, quat);
- axis_set_view(
- C, v3d, region, quat, viewnum, view_axis_roll, nextperspo, align_quat, smooth_viewtx);
-
- perspo = rv3d->persp;
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_view_axis(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "View Axis";
- ot->description = "Use a preset viewpoint";
- ot->idname = "VIEW3D_OT_view_axis";
-
- /* api callbacks */
- ot->exec = view_axis_exec;
- ot->poll = ED_operator_rv3d_user_region_poll;
-
- /* flags */
- ot->flag = 0;
-
- ot->prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "Preset viewpoint to use");
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(
- ot->srna, "align_active", 0, "Align Active", "Align to the active object's axis");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(
- ot->srna, "relative", 0, "Relative", "Rotate relative to the current orientation");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name View Camera Operator
- * \{ */
-
-static int view_camera_exec(bContext *C, wmOperator *op)
-{
- View3D *v3d;
- ARegion *region;
- RegionView3D *rv3d;
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- /* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &region);
- rv3d = region->regiondata;
-
- ED_view3d_smooth_view_force_finish(C, v3d, region);
-
- if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Scene *scene = CTX_data_scene(C);
-
- if (rv3d->persp != RV3D_CAMOB) {
- Object *ob = OBACT(view_layer);
-
- if (!rv3d->smooth_timer) {
- /* store settings of current view before allowing overwriting with camera view
- * only if we're not currently in a view transition */
-
- ED_view3d_lastview_store(rv3d);
- }
-
- /* first get the default camera for the view lock type */
- if (v3d->scenelock) {
- /* sets the camera view if available */
- v3d->camera = scene->camera;
- }
- else {
- /* use scene camera if one is not set (even though we're unlocked) */
- if (v3d->camera == NULL) {
- v3d->camera = scene->camera;
- }
- }
-
- /* if the camera isn't found, check a number of options */
- if (v3d->camera == NULL && ob && ob->type == OB_CAMERA) {
- v3d->camera = ob;
- }
-
- if (v3d->camera == NULL) {
- v3d->camera = BKE_view_layer_camera_find(view_layer);
- }
-
- /* couldn't find any useful camera, bail out */
- if (v3d->camera == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- /* important these don't get out of sync for locked scenes */
- if (v3d->scenelock && scene->camera != v3d->camera) {
- scene->camera = v3d->camera;
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- }
-
- /* finally do snazzy view zooming */
- rv3d->persp = RV3D_CAMOB;
- ED_view3d_smooth_view(C,
- v3d,
- region,
- smooth_viewtx,
- &(const V3D_SmoothParams){
- .camera = v3d->camera,
- .ofs = rv3d->ofs,
- .quat = rv3d->viewquat,
- .dist = &rv3d->dist,
- .lens = &v3d->lens,
- });
- }
- else {
- /* return to settings of last view */
- /* does view3d_smooth_view too */
- axis_set_view(C,
- v3d,
- region,
- rv3d->lviewquat,
- rv3d->lview,
- rv3d->lview_axis_roll,
- rv3d->lpersp,
- NULL,
- smooth_viewtx);
- }
- }
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_view_camera(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "View Camera";
- ot->description = "Toggle the camera view";
- ot->idname = "VIEW3D_OT_view_camera";
-
- /* api callbacks */
- ot->exec = view_camera_exec;
- ot->poll = ED_operator_rv3d_user_region_poll;
-
- /* flags */
- ot->flag = 0;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name View Orbit Operator
- *
- * Rotate (orbit) in incremental steps. For interactive orbit see #VIEW3D_OT_rotate.
- * \{ */
-
-enum {
- V3D_VIEW_STEPLEFT = 1,
- V3D_VIEW_STEPRIGHT,
- V3D_VIEW_STEPDOWN,
- V3D_VIEW_STEPUP,
-};
-
-static const EnumPropertyItem prop_view_orbit_items[] = {
- {V3D_VIEW_STEPLEFT, "ORBITLEFT", 0, "Orbit Left", "Orbit the view around to the left"},
- {V3D_VIEW_STEPRIGHT, "ORBITRIGHT", 0, "Orbit Right", "Orbit the view around to the right"},
- {V3D_VIEW_STEPUP, "ORBITUP", 0, "Orbit Up", "Orbit the view up"},
- {V3D_VIEW_STEPDOWN, "ORBITDOWN", 0, "Orbit Down", "Orbit the view down"},
- {0, NULL, 0, NULL, NULL},
-};
-
-static int vieworbit_exec(bContext *C, wmOperator *op)
-{
- View3D *v3d;
- ARegion *region;
- RegionView3D *rv3d;
- int orbitdir;
- char view_opposite;
- PropertyRNA *prop_angle = RNA_struct_find_property(op->ptr, "angle");
- float angle = RNA_property_is_set(op->ptr, prop_angle) ?
- RNA_property_float_get(op->ptr, prop_angle) :
- DEG2RADF(U.pad_rot_angle);
-
- /* no NULL check is needed, poll checks */
- v3d = CTX_wm_view3d(C);
- region = CTX_wm_region(C);
- rv3d = region->regiondata;
-
- /* support for switching to the opposite view (even when in locked views) */
- view_opposite = (fabsf(angle) == (float)M_PI) ? ED_view3d_axis_view_opposite(rv3d->view) :
- RV3D_VIEW_USER;
- orbitdir = RNA_enum_get(op->ptr, "type");
-
- if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) && (view_opposite == RV3D_VIEW_USER)) {
- /* no NULL check is needed, poll checks */
- ED_view3d_context_user_region(C, &v3d, &region);
- rv3d = region->regiondata;
- }
-
- ED_view3d_smooth_view_force_finish(C, v3d, region);
-
- if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0 || (view_opposite != RV3D_VIEW_USER)) {
- if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
- int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- float quat_mul[4];
- float quat_new[4];
-
- if (view_opposite == RV3D_VIEW_USER) {
- const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ED_view3d_persp_ensure(depsgraph, v3d, region);
- }
-
- if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
- if (orbitdir == V3D_VIEW_STEPRIGHT) {
- angle = -angle;
- }
-
- /* z-axis */
- axis_angle_to_quat_single(quat_mul, 'Z', angle);
- }
- else {
-
- if (orbitdir == V3D_VIEW_STEPDOWN) {
- angle = -angle;
- }
-
- /* horizontal axis */
- axis_angle_to_quat(quat_mul, rv3d->viewinv[0], angle);
- }
-
- mul_qt_qtqt(quat_new, rv3d->viewquat, quat_mul);
-
- /* avoid precision loss over time */
- normalize_qt(quat_new);
-
- if (view_opposite != RV3D_VIEW_USER) {
- rv3d->view = view_opposite;
- /* avoid float in-precision, just get a new orientation */
- ED_view3d_quat_from_axis_view(view_opposite, rv3d->view_axis_roll, quat_new);
- }
- else {
- rv3d->view = RV3D_VIEW_USER;
- }
-
- float dyn_ofs[3], *dyn_ofs_pt = NULL;
-
- if (U.uiflag & USER_ORBIT_SELECTION) {
- if (view3d_orbit_calc_center(C, dyn_ofs)) {
- negate_v3(dyn_ofs);
- dyn_ofs_pt = dyn_ofs;
- }
- }
-
- ED_view3d_smooth_view(C,
- v3d,
- region,
- smooth_viewtx,
- &(const V3D_SmoothParams){
- .quat = quat_new,
- .dyn_ofs = dyn_ofs_pt,
- });
-
- return OPERATOR_FINISHED;
- }
- }
-
- return OPERATOR_CANCELLED;
-}
-
-void VIEW3D_OT_view_orbit(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "View Orbit";
- ot->description = "Orbit the view";
- ot->idname = "VIEW3D_OT_view_orbit";
-
- /* api callbacks */
- ot->exec = vieworbit_exec;
- ot->poll = ED_operator_rv3d_user_region_poll;
-
- /* flags */
- ot->flag = 0;
-
- /* properties */
- prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- ot->prop = RNA_def_enum(
- ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name View Roll Operator
- * \{ */
-
-static void view_roll_angle(
- ARegion *region, float quat[4], const float orig_quat[4], const float dvec[3], float angle)
-{
- RegionView3D *rv3d = region->regiondata;
- float quat_mul[4];
-
- /* camera axis */
- axis_angle_normalized_to_quat(quat_mul, dvec, angle);
-
- mul_qt_qtqt(quat, orig_quat, quat_mul);
-
- /* avoid precision loss over time */
- normalize_qt(quat);
-
- rv3d->view = RV3D_VIEW_USER;
-}
-
-static void viewroll_apply(ViewOpsData *vod, int x, int y)
-{
- float angle = BLI_dial_angle(vod->init.dial, (const float[2]){x, y});
-
- if (angle != 0.0f) {
- view_roll_angle(vod->region, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle);
- }
-
- if (vod->use_dyn_ofs) {
- view3d_orbit_apply_dyn_ofs(
- vod->rv3d->ofs, vod->init.ofs, vod->init.quat, vod->rv3d->viewquat, vod->dyn_ofs);
- }
-
- if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->area, vod->region);
- }
-
- ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
-
- ED_region_tag_redraw(vod->region);
-}
-
-static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ViewOpsData *vod = op->customdata;
- short event_code = VIEW_PASS;
- bool use_autokey = false;
- int ret = OPERATOR_RUNNING_MODAL;
-
- /* execute the events */
- if (event->type == MOUSEMOVE) {
- event_code = VIEW_APPLY;
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case VIEW_MODAL_CONFIRM:
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
- event_code = VIEW_CONFIRM;
- break;
- }
- }
- else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
- /* Note this does not remove auto-keys on locked cameras. */
- copy_qt_qt(vod->rv3d->viewquat, vod->init.quat);
- ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
- viewops_data_free(C, op);
- return OPERATOR_CANCELLED;
- }
- else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
- event_code = VIEW_CONFIRM;
- }
-
- if (event_code == VIEW_APPLY) {
- viewroll_apply(vod, event->xy[0], event->xy[1]);
- if (ED_screen_animation_playing(CTX_wm_manager(C))) {
- use_autokey = true;
- }
- }
- else if (event_code == VIEW_CONFIRM) {
- use_autokey = true;
- ret = OPERATOR_FINISHED;
- }
-
- if (use_autokey) {
- ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false);
- }
-
- if (ret & OPERATOR_FINISHED) {
- viewops_data_free(C, op);
- }
-
- return ret;
-}
-
-static const EnumPropertyItem prop_view_roll_items[] = {
- {0, "ANGLE", 0, "Roll Angle", "Roll the view using an angle value"},
- {V3D_VIEW_STEPLEFT, "LEFT", 0, "Roll Left", "Roll the view around to the left"},
- {V3D_VIEW_STEPRIGHT, "RIGHT", 0, "Roll Right", "Roll the view around to the right"},
- {0, NULL, 0, NULL, NULL},
-};
-
-static int viewroll_exec(bContext *C, wmOperator *op)
-{
- View3D *v3d;
- RegionView3D *rv3d;
- ARegion *region;
-
- if (op->customdata) {
- ViewOpsData *vod = op->customdata;
- region = vod->region;
- v3d = vod->v3d;
- }
- else {
- ED_view3d_context_user_region(C, &v3d, &region);
- }
-
- rv3d = region->regiondata;
- if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
-
- ED_view3d_smooth_view_force_finish(C, v3d, region);
-
- int type = RNA_enum_get(op->ptr, "type");
- float angle = (type == 0) ? RNA_float_get(op->ptr, "angle") : DEG2RADF(U.pad_rot_angle);
- float mousevec[3];
- float quat_new[4];
-
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
-
- if (type == V3D_VIEW_STEPLEFT) {
- angle = -angle;
- }
-
- normalize_v3_v3(mousevec, rv3d->viewinv[2]);
- negate_v3(mousevec);
- view_roll_angle(region, quat_new, rv3d->viewquat, mousevec, angle);
-
- const float *dyn_ofs_pt = NULL;
- float dyn_ofs[3];
- if (U.uiflag & USER_ORBIT_SELECTION) {
- if (view3d_orbit_calc_center(C, dyn_ofs)) {
- negate_v3(dyn_ofs);
- dyn_ofs_pt = dyn_ofs;
- }
- }
-
- ED_view3d_smooth_view(C,
- v3d,
- region,
- smooth_viewtx,
- &(const V3D_SmoothParams){
- .quat = quat_new,
- .dyn_ofs = dyn_ofs_pt,
- });
-
- viewops_data_free(C, op);
- return OPERATOR_FINISHED;
- }
-
- viewops_data_free(C, op);
- return OPERATOR_CANCELLED;
-}
-
-static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ViewOpsData *vod;
-
- bool use_angle = RNA_enum_get(op->ptr, "type") != 0;
-
- if (use_angle || RNA_struct_property_is_set(op->ptr, "angle")) {
- viewroll_exec(C, op);
- }
- else {
- /* makes op->customdata */
- viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, viewops_flag_from_prefs());
- vod = op->customdata;
- vod->init.dial = BLI_dial_init((const float[2]){BLI_rcti_cent_x(&vod->region->winrct),
- BLI_rcti_cent_y(&vod->region->winrct)},
- FLT_EPSILON);
-
- ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
-
- /* overwrite the mouse vector with the view direction */
- normalize_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
- negate_v3(vod->init.mousevec);
-
- if (event->type == MOUSEROTATE) {
- vod->init.event_xy[0] = vod->prev.event_xy[0] = event->xy[0];
- viewroll_apply(vod, event->prev_xy[0], event->prev_xy[1]);
-
- viewops_data_free(C, op);
- return OPERATOR_FINISHED;
- }
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
- }
- return OPERATOR_FINISHED;
-}
-
-static void viewroll_cancel(bContext *C, wmOperator *op)
-{
- viewops_data_free(C, op);
-}
-
-void VIEW3D_OT_view_roll(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "View Roll";
- ot->description = "Roll the view";
- ot->idname = "VIEW3D_OT_view_roll";
-
- /* api callbacks */
- ot->invoke = viewroll_invoke;
- ot->exec = viewroll_exec;
- ot->modal = viewroll_modal;
- ot->poll = ED_operator_rv3d_user_region_poll;
- ot->cancel = viewroll_cancel;
-
- /* flags */
- ot->flag = 0;
-
- /* properties */
- ot->prop = prop = RNA_def_float(
- ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_enum(ot->srna,
- "type",
- prop_view_roll_items,
- 0,
- "Roll Angle Source",
- "How roll angle is calculated");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-}
-
-enum {
- V3D_VIEW_PANLEFT = 1,
- V3D_VIEW_PANRIGHT,
- V3D_VIEW_PANDOWN,
- V3D_VIEW_PANUP,
-};
-
-static const EnumPropertyItem prop_view_pan_items[] = {
- {V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the left"},
- {V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the right"},
- {V3D_VIEW_PANUP, "PANUP", 0, "Pan Up", "Pan the view up"},
- {V3D_VIEW_PANDOWN, "PANDOWN", 0, "Pan Down", "Pan the view down"},
- {0, NULL, 0, NULL, NULL},
-};
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name View Pan Operator
- *
- * Move (pan) in incremental steps. For interactive pan see #VIEW3D_OT_move.
- * \{ */
-
-static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- int x = 0, y = 0;
- int pandir = RNA_enum_get(op->ptr, "type");
-
- if (pandir == V3D_VIEW_PANRIGHT) {
- x = -32;
- }
- else if (pandir == V3D_VIEW_PANLEFT) {
- x = 32;
- }
- else if (pandir == V3D_VIEW_PANUP) {
- y = -25;
- }
- else if (pandir == V3D_VIEW_PANDOWN) {
- y = 25;
- }
-
- viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT));
- ViewOpsData *vod = op->customdata;
-
- viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y);
-
- viewops_data_free(C, op);
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_view_pan(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Pan View Direction";
- ot->description = "Pan the view in a given direction";
- ot->idname = "VIEW3D_OT_view_pan";
-
- /* api callbacks */
- ot->invoke = viewpan_invoke;
- ot->poll = view3d_pan_poll;
-
- /* flags */
- ot->flag = 0;
-
- /* Properties */
- ot->prop = RNA_def_enum(
- ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan");
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name View Toggle Perspective/Orthographic Operator
* \{ */
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 607ca110d0f..7f872c9b1af 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -52,8 +52,6 @@
#include "view3d_intern.h"
-static void do_view3d_header_buttons(bContext *C, void *arg, int event);
-
#define B_SEL_VERT 110
#define B_SEL_EDGE 111
#define B_SEL_FACE 112
@@ -98,101 +96,45 @@ void VIEW3D_OT_toggle_matcap_flip(wmOperatorType *ot)
/** \name UI Templates
* \{ */
-static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
-{
- wmWindow *win = CTX_wm_window(C);
- const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift;
-
- /* watch it: if area->win does not exist, check that when calling direct drawing routines */
-
- switch (event) {
- case B_SEL_VERT:
- if (EDBM_selectmode_toggle_multi(C, SCE_SELECT_VERTEX, -1, shift, ctrl)) {
- ED_undo_push(C, "Selectmode Set: Vertex");
- }
- break;
- case B_SEL_EDGE:
- if (EDBM_selectmode_toggle_multi(C, SCE_SELECT_EDGE, -1, shift, ctrl)) {
- ED_undo_push(C, "Selectmode Set: Edge");
- }
- break;
- case B_SEL_FACE:
- if (EDBM_selectmode_toggle_multi(C, SCE_SELECT_FACE, -1, shift, ctrl)) {
- ED_undo_push(C, "Selectmode Set: Face");
- }
- break;
- default:
- break;
- }
-}
-
void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
- uiBlock *block = uiLayoutGetBlock(layout);
-
- UI_block_func_handle_set(block, do_view3d_header_buttons, NULL);
-
- if (obedit && (obedit->type == OB_MESH)) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- uiLayout *row;
- uiBut *but;
-
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
- but = uiDefIconButBitS(
- block,
- UI_BTYPE_TOGGLE,
- SCE_SELECT_VERTEX,
- B_SEL_VERT,
- ICON_VERTEXSEL,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- &em->selectmode,
- 1.0,
- 0.0,
- 0,
- 0,
- TIP_("Vertex select - Shift-Click for multiple modes, Ctrl-Click contracts selection"));
- UI_but_flag_disable(but, UI_BUT_UNDO);
- but = uiDefIconButBitS(
- block,
- UI_BTYPE_TOGGLE,
- SCE_SELECT_EDGE,
- B_SEL_EDGE,
- ICON_EDGESEL,
- 0,
- 0,
- ceilf(UI_UNIT_X - U.pixelsize),
- UI_UNIT_Y,
- &em->selectmode,
- 1.0,
- 0.0,
- 0,
- 0,
- TIP_("Edge select - Shift-Click for multiple modes, "
- "Ctrl-Click expands/contracts selection depending on the current mode"));
- UI_but_flag_disable(but, UI_BUT_UNDO);
- but = uiDefIconButBitS(
- block,
- UI_BTYPE_TOGGLE,
- SCE_SELECT_FACE,
- B_SEL_FACE,
- ICON_FACESEL,
- 0,
- 0,
- ceilf(UI_UNIT_X - U.pixelsize),
- UI_UNIT_Y,
- &em->selectmode,
- 1.0,
- 0.0,
- 0,
- 0,
- TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"));
- UI_but_flag_disable(but, UI_BUT_UNDO);
+ if (!obedit || obedit->type != OB_MESH) {
+ return;
}
+
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ uiLayout *row = uiLayoutRow(layout, true);
+
+ PointerRNA op_ptr;
+ wmOperatorType *ot = WM_operatortype_find("MESH_OT_select_mode", true);
+ uiItemFullO_ptr(row,
+ ot,
+ "",
+ ICON_VERTEXSEL,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ (em->selectmode & SCE_SELECT_VERTEX) ? UI_ITEM_O_DEPRESS : 0,
+ &op_ptr);
+ RNA_enum_set(&op_ptr, "type", SCE_SELECT_VERTEX);
+ uiItemFullO_ptr(row,
+ ot,
+ "",
+ ICON_EDGESEL,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ (em->selectmode & SCE_SELECT_EDGE) ? UI_ITEM_O_DEPRESS : 0,
+ &op_ptr);
+ RNA_enum_set(&op_ptr, "type", SCE_SELECT_EDGE);
+ uiItemFullO_ptr(row,
+ ot,
+ "",
+ ICON_FACESEL,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ (em->selectmode & SCE_SELECT_FACE) ? UI_ITEM_O_DEPRESS : 0,
+ &op_ptr);
+ RNA_enum_set(&op_ptr, "type", SCE_SELECT_FACE);
}
static void uiTemplatePaintModeSelection(uiLayout *layout, struct bContext *C)
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 6a1a09df316..b443ebeed94 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -32,6 +32,8 @@ struct ARegionType;
struct BoundBox;
struct Depsgraph;
struct Object;
+struct Scene;
+struct ViewContext;
struct ViewLayer;
struct bContext;
struct wmGizmoGroupType;
@@ -40,13 +42,6 @@ struct wmKeyConfig;
struct wmOperatorType;
struct wmWindowManager;
-/* drawing flags: */
-enum {
- DRAW_PICKING = (1 << 0),
- DRAW_CONSTCOLOR = (1 << 1),
- DRAW_SCENESET = (1 << 2),
-};
-
/* view3d_header.c */
void VIEW3D_OT_toggle_matcap_flip(struct wmOperatorType *ot);
@@ -54,84 +49,24 @@ void VIEW3D_OT_toggle_matcap_flip(struct wmOperatorType *ot);
void view3d_operatortypes(void);
/* view3d_edit.c */
-void VIEW3D_OT_zoom(struct wmOperatorType *ot);
-void VIEW3D_OT_dolly(struct wmOperatorType *ot);
void VIEW3D_OT_zoom_camera_1_to_1(struct wmOperatorType *ot);
-void VIEW3D_OT_move(struct wmOperatorType *ot);
-void VIEW3D_OT_rotate(struct wmOperatorType *ot);
-#ifdef WITH_INPUT_NDOF
-void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot);
-void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot);
-void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot);
-void VIEW3D_OT_ndof_all(struct wmOperatorType *ot);
-#endif /* WITH_INPUT_NDOF */
-void VIEW3D_OT_view_all(struct wmOperatorType *ot);
-void VIEW3D_OT_view_axis(struct wmOperatorType *ot);
-void VIEW3D_OT_view_camera(struct wmOperatorType *ot);
-void VIEW3D_OT_view_selected(struct wmOperatorType *ot);
void VIEW3D_OT_view_lock_clear(struct wmOperatorType *ot);
void VIEW3D_OT_view_lock_to_active(struct wmOperatorType *ot);
-void VIEW3D_OT_view_center_cursor(struct wmOperatorType *ot);
-void VIEW3D_OT_view_center_pick(struct wmOperatorType *ot);
void VIEW3D_OT_view_center_camera(struct wmOperatorType *ot);
void VIEW3D_OT_view_center_lock(struct wmOperatorType *ot);
-void VIEW3D_OT_view_pan(struct wmOperatorType *ot);
void VIEW3D_OT_view_persportho(struct wmOperatorType *ot);
void VIEW3D_OT_navigate(struct wmOperatorType *ot);
void VIEW3D_OT_background_image_add(struct wmOperatorType *ot);
void VIEW3D_OT_background_image_remove(struct wmOperatorType *ot);
void VIEW3D_OT_drop_world(struct wmOperatorType *ot);
-void VIEW3D_OT_view_orbit(struct wmOperatorType *ot);
-void VIEW3D_OT_view_roll(struct wmOperatorType *ot);
void VIEW3D_OT_clip_border(struct wmOperatorType *ot);
void VIEW3D_OT_cursor3d(struct wmOperatorType *ot);
void VIEW3D_OT_render_border(struct wmOperatorType *ot);
void VIEW3D_OT_clear_render_border(struct wmOperatorType *ot);
-void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_shading(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_xray(struct wmOperatorType *ot);
-/**
- * For home, center etc.
- */
-void view3d_boxview_copy(struct ScrArea *area, struct ARegion *region);
-/**
- * Sync center/zoom view of region to others, for view transforms.
- */
-void view3d_boxview_sync(struct ScrArea *area, struct ARegion *region);
-
-void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
- const float ofs_old[3],
- const float viewquat_old[4],
- const float viewquat_new[4],
- const float dyn_ofs[3]);
-
-#ifdef WITH_INPUT_NDOF
-struct wmNDOFMotionData;
-
-/**
- * Called from both fly mode and walk mode,
- */
-void view3d_ndof_fly(const struct wmNDOFMotionData *ndof,
- struct View3D *v3d,
- struct RegionView3D *rv3d,
- bool use_precision,
- short protectflag,
- bool *r_has_translate,
- bool *r_has_rotate);
-#endif /* WITH_INPUT_NDOF */
-
-/* view3d_navigate_fly.c */
-
-void view3d_keymap(struct wmKeyConfig *keyconf);
-void VIEW3D_OT_fly(struct wmOperatorType *ot);
-
-/* view3d_navigate_walk.c */
-
-void VIEW3D_OT_walk(struct wmOperatorType *ot);
-
/* view3d_draw.c */
-
void view3d_main_region_draw(const struct bContext *C, struct ARegion *region);
/**
* Information drawn on top of the solid plates and composed data.
@@ -141,16 +76,16 @@ void view3d_draw_region_info(const struct bContext *C, struct ARegion *region);
/* view3d_draw_legacy.c */
void ED_view3d_draw_select_loop(struct Depsgraph *depsgraph,
- ViewContext *vc,
- Scene *scene,
+ struct ViewContext *vc,
+ struct Scene *scene,
struct ViewLayer *view_layer,
- View3D *v3d,
+ struct View3D *v3d,
struct ARegion *region,
bool use_obedit_skip,
bool use_nearest);
void ED_view3d_draw_depth_loop(struct Depsgraph *depsgraph,
- Scene *scene,
+ struct Scene *scene,
struct ARegion *region,
View3D *v3d);
@@ -168,57 +103,27 @@ void VIEW3D_OT_select_lasso(struct wmOperatorType *ot);
void VIEW3D_OT_select_menu(struct wmOperatorType *ot);
void VIEW3D_OT_bone_select_menu(struct wmOperatorType *ot);
-/* view3d_view.c */
-void VIEW3D_OT_smoothview(struct wmOperatorType *ot);
-void VIEW3D_OT_camera_to_view(struct wmOperatorType *ot);
-void VIEW3D_OT_camera_to_view_selected(struct wmOperatorType *ot);
-void VIEW3D_OT_object_as_camera(struct wmOperatorType *ot);
-void VIEW3D_OT_localview(struct wmOperatorType *ot);
-void VIEW3D_OT_localview_remove_from(struct wmOperatorType *ot);
+/* view3d_utils.c */
+/**
+ * For home, center etc.
+ */
+void view3d_boxview_copy(struct ScrArea *area, struct ARegion *region);
+/**
+ * Sync center/zoom view of region to others, for view transforms.
+ */
+void view3d_boxview_sync(struct ScrArea *area, struct ARegion *region);
bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d,
const struct BoundBox *bb,
float obmat[4][4]);
bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const struct BoundBox *bb);
-/**
- * Parameters for setting the new 3D Viewport state.
- *
- * Each of the struct members may be NULL to signify they aren't to be adjusted.
- */
-typedef struct V3D_SmoothParams {
- struct Object *camera_old, *camera;
- const float *ofs, *quat, *dist, *lens;
-
- /** Alternate rotation center, when set `ofs` must be NULL. */
- const float *dyn_ofs;
-} V3D_SmoothParams;
-
-/**
- * The arguments are the desired situation.
- */
-void ED_view3d_smooth_view_ex(const struct Depsgraph *depsgraph,
- struct wmWindowManager *wm,
- struct wmWindow *win,
- struct ScrArea *area,
- struct View3D *v3d,
- struct ARegion *region,
- int smooth_viewtx,
- const V3D_SmoothParams *sview);
-
-void ED_view3d_smooth_view(struct bContext *C,
- struct View3D *v3d,
- struct ARegion *region,
- int smooth_viewtx,
- const V3D_SmoothParams *sview);
-
-/**
- * Apply the smooth-view immediately, use when we need to start a new view operation.
- * (so we don't end up half-applying a view operation when pressing keys quickly).
- */
-void ED_view3d_smooth_view_force_finish(struct bContext *C,
- struct View3D *v3d,
- struct ARegion *region);
+/* view3d_view.c */
+void VIEW3D_OT_camera_to_view(struct wmOperatorType *ot);
+void VIEW3D_OT_camera_to_view_selected(struct wmOperatorType *ot);
+void VIEW3D_OT_object_as_camera(struct wmOperatorType *ot);
+void VIEW3D_OT_localview(struct wmOperatorType *ot);
+void VIEW3D_OT_localview_remove_from(struct wmOperatorType *ot);
/**
* \param rect: optional for picking (can be NULL).
@@ -247,12 +152,7 @@ void view3d_viewmatrix_set(struct Depsgraph *depsgraph,
/* Called in transform_ops.c, on each regeneration of key-maps. */
-void fly_modal_keymap(struct wmKeyConfig *keyconf);
-void walk_modal_keymap(struct wmKeyConfig *keyconf);
-void viewrotate_modal_keymap(struct wmKeyConfig *keyconf);
-void viewmove_modal_keymap(struct wmKeyConfig *keyconf);
-void viewzoom_modal_keymap(struct wmKeyConfig *keyconf);
-void viewdolly_modal_keymap(struct wmKeyConfig *keyconf);
+/* view3d_placement.c */
void viewplace_modal_keymap(struct wmKeyConfig *keyconf);
/* view3d_buttons.c */
@@ -267,7 +167,7 @@ void view3d_buttons_register(struct ARegionType *art);
* the view for first-person style navigation.
*/
struct View3DCameraControl *ED_view3d_cameracontrol_acquire(struct Depsgraph *depsgraph,
- Scene *scene,
+ struct Scene *scene,
View3D *v3d,
RegionView3D *rv3d);
/**
diff --git a/source/blender/editors/space_view3d/view3d_navigate.c b/source/blender/editors/space_view3d/view3d_navigate.c
new file mode 100644
index 00000000000..98eef94d5fb
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_navigate.c
@@ -0,0 +1,1593 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup spview3d
+ */
+
+#include "DNA_curve_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_rect.h"
+
+#include "BKE_armature.h"
+#include "BKE_context.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_layer.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_vfont.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "ED_mesh.h"
+#include "ED_particle.h"
+#include "ED_screen.h"
+#include "ED_transform.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_resources.h"
+
+#include "view3d_intern.h"
+
+#include "view3d_navigate.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name Navigation Polls
+ * \{ */
+
+static bool view3d_navigation_poll_impl(bContext *C, const char viewlock)
+{
+ if (!ED_operator_region_view3d_active(C)) {
+ return false;
+ }
+
+ const RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ return !(RV3D_LOCK_FLAGS(rv3d) & viewlock);
+}
+
+bool view3d_location_poll(bContext *C)
+{
+ return view3d_navigation_poll_impl(C, RV3D_LOCK_LOCATION);
+}
+
+bool view3d_rotation_poll(bContext *C)
+{
+ return view3d_navigation_poll_impl(C, RV3D_LOCK_ROTATION);
+}
+
+bool view3d_zoom_or_dolly_poll(bContext *C)
+{
+ return view3d_navigation_poll_impl(C, RV3D_LOCK_ZOOM_AND_DOLLY);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Generic View Operator Properties
+ * \{ */
+
+void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3D_OpPropFlag flag)
+{
+ if (flag & V3D_OP_PROP_MOUSE_CO) {
+ PropertyRNA *prop;
+ prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Region Position X", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Region Position Y", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+ if (flag & V3D_OP_PROP_DELTA) {
+ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
+ }
+ if (flag & V3D_OP_PROP_USE_ALL_REGIONS) {
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(
+ ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ }
+ if (flag & V3D_OP_PROP_USE_MOUSE_INIT) {
+ WM_operator_properties_use_cursor_init(ot);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Generic View Operator Custom-Data
+ * \{ */
+
+void calctrackballvec(const rcti *rect, const int event_xy[2], float r_dir[3])
+{
+ const float radius = V3D_OP_TRACKBALLSIZE;
+ const float t = radius / (float)M_SQRT2;
+ const float size[2] = {BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)};
+ /* Aspect correct so dragging in a non-square view doesn't squash the direction.
+ * So diagonal motion rotates the same direction the cursor is moving. */
+ const float size_min = min_ff(size[0], size[1]);
+ const float aspect[2] = {size_min / size[0], size_min / size[1]};
+
+ /* Normalize x and y. */
+ r_dir[0] = (event_xy[0] - BLI_rcti_cent_x(rect)) / ((size[0] * aspect[0]) / 2.0);
+ r_dir[1] = (event_xy[1] - BLI_rcti_cent_y(rect)) / ((size[1] * aspect[1]) / 2.0);
+ const float d = len_v2(r_dir);
+ if (d < t) {
+ /* Inside sphere. */
+ r_dir[2] = sqrtf(square_f(radius) - square_f(d));
+ }
+ else {
+ /* On hyperbola. */
+ r_dir[2] = square_f(t) / d;
+ }
+}
+
+void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
+ const float ofs_old[3],
+ const float viewquat_old[4],
+ const float viewquat_new[4],
+ const float dyn_ofs[3])
+{
+ float q[4];
+ invert_qt_qt_normalized(q, viewquat_old);
+ mul_qt_qtqt(q, q, viewquat_new);
+
+ invert_qt_normalized(q);
+
+ sub_v3_v3v3(r_ofs, ofs_old, dyn_ofs);
+ mul_qt_v3(q, r_ofs);
+ add_v3_v3(r_ofs, dyn_ofs);
+}
+
+void viewrotate_apply_dyn_ofs(ViewOpsData *vod, const float viewquat_new[4])
+{
+ if (vod->use_dyn_ofs) {
+ RegionView3D *rv3d = vod->rv3d;
+ view3d_orbit_apply_dyn_ofs(
+ rv3d->ofs, vod->init.ofs, vod->init.quat, viewquat_new, vod->dyn_ofs);
+ }
+}
+
+bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
+{
+ static float lastofs[3] = {0, 0, 0};
+ bool is_set = false;
+
+ const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *ob_act_eval = OBACT(view_layer_eval);
+ Object *ob_act = DEG_get_original_object(ob_act_eval);
+
+ if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) &&
+ /* with weight-paint + pose-mode, fall through to using calculateTransformCenter */
+ ((ob_act->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(ob_act)) == 0) {
+ /* in case of sculpting use last average stroke position as a rotation
+ * center, in other cases it's not clear what rotation center shall be
+ * so just rotate around object origin
+ */
+ if (ob_act->mode &
+ (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
+ float stroke[3];
+ BKE_paint_stroke_get_average(scene, ob_act_eval, stroke);
+ copy_v3_v3(lastofs, stroke);
+ }
+ else {
+ copy_v3_v3(lastofs, ob_act_eval->obmat[3]);
+ }
+ is_set = true;
+ }
+ else if (ob_act && (ob_act->mode & OB_MODE_EDIT) && (ob_act->type == OB_FONT)) {
+ Curve *cu = ob_act_eval->data;
+ EditFont *ef = cu->editfont;
+
+ zero_v3(lastofs);
+ for (int i = 0; i < 4; i++) {
+ add_v2_v2(lastofs, ef->textcurs[i]);
+ }
+ mul_v2_fl(lastofs, 1.0f / 4.0f);
+
+ mul_m4_v3(ob_act_eval->obmat, lastofs);
+
+ is_set = true;
+ }
+ else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) {
+ /* object mode use boundbox centers */
+ Base *base_eval;
+ uint tot = 0;
+ float select_center[3];
+
+ zero_v3(select_center);
+ for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
+ if (BASE_SELECTED(v3d, base_eval)) {
+ /* use the boundbox if we can */
+ Object *ob_eval = base_eval->object;
+
+ if (ob_eval->runtime.bb && !(ob_eval->runtime.bb->flag & BOUNDBOX_DIRTY)) {
+ float cent[3];
+
+ BKE_boundbox_calc_center_aabb(ob_eval->runtime.bb, cent);
+
+ mul_m4_v3(ob_eval->obmat, cent);
+ add_v3_v3(select_center, cent);
+ }
+ else {
+ add_v3_v3(select_center, ob_eval->obmat[3]);
+ }
+ tot++;
+ }
+ }
+ if (tot) {
+ mul_v3_fl(select_center, 1.0f / (float)tot);
+ copy_v3_v3(lastofs, select_center);
+ is_set = true;
+ }
+ }
+ else {
+ /* If there's no selection, `lastofs` is unmodified and last value since static. */
+ is_set = calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, lastofs, NULL);
+ }
+
+ copy_v3_v3(r_dyn_ofs, lastofs);
+
+ return is_set;
+}
+
+static enum eViewOpsFlag viewops_flag_from_args(bool use_select, bool use_depth)
+{
+ enum eViewOpsFlag flag = 0;
+ if (use_select) {
+ flag |= VIEWOPS_FLAG_ORBIT_SELECT;
+ }
+ if (use_depth) {
+ flag |= VIEWOPS_FLAG_DEPTH_NAVIGATE;
+ }
+
+ return flag;
+}
+
+enum eViewOpsFlag viewops_flag_from_prefs(void)
+{
+ return viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0,
+ (U.uiflag & USER_DEPTH_NAVIGATE) != 0);
+}
+
+ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOpsFlag viewops_flag)
+{
+ ViewOpsData *vod = MEM_callocN(sizeof(ViewOpsData), __func__);
+
+ /* Store data. */
+ vod->bmain = CTX_data_main(C);
+ vod->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ vod->scene = CTX_data_scene(C);
+ vod->area = CTX_wm_area(C);
+ vod->region = CTX_wm_region(C);
+ vod->v3d = vod->area->spacedata.first;
+ vod->rv3d = vod->region->regiondata;
+
+ Depsgraph *depsgraph = vod->depsgraph;
+ RegionView3D *rv3d = vod->rv3d;
+
+ /* Could do this more nicely. */
+ if ((viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) == 0) {
+ viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
+ }
+
+ /* we need the depth info before changing any viewport options */
+ if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
+ float fallback_depth_pt[3];
+
+ view3d_operator_needs_opengl(C); /* Needed for Z-buffer drawing. */
+
+ negate_v3_v3(fallback_depth_pt, rv3d->ofs);
+
+ vod->use_dyn_ofs = ED_view3d_autodist(
+ depsgraph, vod->region, vod->v3d, event->mval, vod->dyn_ofs, true, fallback_depth_pt);
+ }
+ else {
+ vod->use_dyn_ofs = false;
+ }
+
+ if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
+ if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->region)) {
+ /* If we're switching from camera view to the perspective one,
+ * need to tag viewport update, so camera view and borders are properly updated. */
+ ED_region_tag_redraw(vod->region);
+ }
+ }
+
+ /* set the view from the camera, if view locking is enabled.
+ * we may want to make this optional but for now its needed always */
+ ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d);
+
+ vod->init.persp = rv3d->persp;
+ vod->init.dist = rv3d->dist;
+ vod->init.camzoom = rv3d->camzoom;
+ copy_qt_qt(vod->init.quat, rv3d->viewquat);
+ copy_v2_v2_int(vod->init.event_xy, event->xy);
+ copy_v2_v2_int(vod->prev.event_xy, event->xy);
+
+ if (viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) {
+ zero_v2_int(vod->init.event_xy_offset);
+ }
+ else {
+ /* Simulate the event starting in the middle of the region. */
+ vod->init.event_xy_offset[0] = BLI_rcti_cent_x(&vod->region->winrct) - event->xy[0];
+ vod->init.event_xy_offset[1] = BLI_rcti_cent_y(&vod->region->winrct) - event->xy[1];
+ }
+
+ vod->init.event_type = event->type;
+ copy_v3_v3(vod->init.ofs, rv3d->ofs);
+
+ copy_qt_qt(vod->curr.viewquat, rv3d->viewquat);
+
+ if (viewops_flag & VIEWOPS_FLAG_ORBIT_SELECT) {
+ float ofs[3];
+ if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) {
+ vod->use_dyn_ofs = true;
+ negate_v3_v3(vod->dyn_ofs, ofs);
+ viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
+ }
+ }
+
+ if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
+ if (vod->use_dyn_ofs) {
+ if (rv3d->is_persp) {
+ float my_origin[3]; /* Original #RegionView3D.ofs. */
+ float my_pivot[3]; /* View pivot. */
+ float dvec[3];
+
+ /* locals for dist correction */
+ float mat[3][3];
+ float upvec[3];
+
+ negate_v3_v3(my_origin, rv3d->ofs); /* ofs is flipped */
+
+ /* Set the dist value to be the distance from this 3d point this means you'll
+ * always be able to zoom into it and panning won't go bad when dist was zero. */
+
+ /* remove dist value */
+ upvec[0] = upvec[1] = 0;
+ upvec[2] = rv3d->dist;
+ copy_m3_m4(mat, rv3d->viewinv);
+
+ mul_m3_v3(mat, upvec);
+ sub_v3_v3v3(my_pivot, rv3d->ofs, upvec);
+ negate_v3(my_pivot); /* ofs is flipped */
+
+ /* find a new ofs value that is along the view axis
+ * (rather than the mouse location) */
+ closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin);
+ vod->init.dist = rv3d->dist = len_v3v3(my_pivot, dvec);
+
+ negate_v3_v3(rv3d->ofs, dvec);
+ }
+ else {
+ const float mval_region_mid[2] = {(float)vod->region->winx / 2.0f,
+ (float)vod->region->winy / 2.0f};
+
+ ED_view3d_win_to_3d(vod->v3d, vod->region, vod->dyn_ofs, mval_region_mid, rv3d->ofs);
+ negate_v3(rv3d->ofs);
+ }
+ negate_v3(vod->dyn_ofs);
+ copy_v3_v3(vod->init.ofs, rv3d->ofs);
+ }
+ }
+
+ /* For dolly */
+ ED_view3d_win_to_vector(vod->region, (const float[2]){UNPACK2(event->mval)}, vod->init.mousevec);
+
+ {
+ int event_xy_offset[2];
+ add_v2_v2v2_int(event_xy_offset, event->xy, vod->init.event_xy_offset);
+
+ /* For rotation with trackball rotation. */
+ calctrackballvec(&vod->region->winrct, event_xy_offset, vod->init.trackvec);
+ }
+
+ {
+ float tvec[3];
+ negate_v3_v3(tvec, rv3d->ofs);
+ vod->init.zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
+ }
+
+ vod->reverse = 1.0f;
+ if (rv3d->persmat[2][1] < 0.0f) {
+ vod->reverse = -1.0f;
+ }
+
+ rv3d->rflag |= RV3D_NAVIGATING;
+
+ return vod;
+}
+
+void viewops_data_free(bContext *C, ViewOpsData *vod)
+{
+ ARegion *region;
+ if (vod) {
+ region = vod->region;
+ vod->rv3d->rflag &= ~RV3D_NAVIGATING;
+
+ if (vod->timer) {
+ WM_event_remove_timer(CTX_wm_manager(C), vod->timer->win, vod->timer);
+ }
+
+ if (vod->init.dial) {
+ MEM_freeN(vod->init.dial);
+ }
+
+ MEM_freeN(vod);
+ }
+ else {
+ region = CTX_wm_region(C);
+ }
+
+ /* Need to redraw because drawing code uses RV3D_NAVIGATING to draw
+ * faster while navigation operator runs. */
+ ED_region_tag_redraw(region);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Generic View Operator Utilities
+ * \{ */
+
+/**
+ * \param align_to_quat: When not NULL, set the axis relative to this rotation.
+ */
+static void axis_set_view(bContext *C,
+ View3D *v3d,
+ ARegion *region,
+ const float quat_[4],
+ char view,
+ char view_axis_roll,
+ int perspo,
+ const float *align_to_quat,
+ const int smooth_viewtx)
+{
+ RegionView3D *rv3d = region->regiondata; /* no NULL check is needed, poll checks */
+ float quat[4];
+ const short orig_persp = rv3d->persp;
+
+ normalize_qt_qt(quat, quat_);
+
+ if (align_to_quat) {
+ mul_qt_qtqt(quat, quat, align_to_quat);
+ rv3d->view = view = RV3D_VIEW_USER;
+ rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
+ }
+
+ if (align_to_quat == NULL) {
+ rv3d->view = view;
+ rv3d->view_axis_roll = view_axis_roll;
+ }
+
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) {
+ ED_region_tag_redraw(region);
+ return;
+ }
+
+ if (U.uiflag & USER_AUTOPERSP) {
+ rv3d->persp = RV3D_VIEW_IS_AXIS(view) ? RV3D_ORTHO : perspo;
+ }
+ else if (rv3d->persp == RV3D_CAMOB) {
+ rv3d->persp = perspo;
+ }
+
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ /* to camera */
+ ED_view3d_smooth_view(C,
+ v3d,
+ region,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .camera_old = v3d->camera,
+ .ofs = rv3d->ofs,
+ .quat = quat,
+ });
+ }
+ else if (orig_persp == RV3D_CAMOB && v3d->camera) {
+ /* from camera */
+ float ofs[3], dist;
+
+ copy_v3_v3(ofs, rv3d->ofs);
+ dist = rv3d->dist;
+
+ /* so we animate _from_ the camera location */
+ Object *camera_eval = DEG_get_evaluated_object(CTX_data_ensure_evaluated_depsgraph(C),
+ v3d->camera);
+ ED_view3d_from_object(camera_eval, rv3d->ofs, NULL, &rv3d->dist, NULL);
+
+ ED_view3d_smooth_view(C,
+ v3d,
+ region,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .camera_old = camera_eval,
+ .ofs = ofs,
+ .quat = quat,
+ .dist = &dist,
+ });
+ }
+ else {
+ /* rotate around selection */
+ const float *dyn_ofs_pt = NULL;
+ float dyn_ofs[3];
+
+ if (U.uiflag & USER_ORBIT_SELECTION) {
+ if (view3d_orbit_calc_center(C, dyn_ofs)) {
+ negate_v3(dyn_ofs);
+ dyn_ofs_pt = dyn_ofs;
+ }
+ }
+
+ /* no camera involved */
+ ED_view3d_smooth_view(C,
+ v3d,
+ region,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .quat = quat,
+ .dyn_ofs = dyn_ofs_pt,
+ });
+ }
+}
+
+void viewmove_apply(ViewOpsData *vod, int x, int y)
+{
+ if (ED_view3d_offset_lock_check(vod->v3d, vod->rv3d)) {
+ vod->rv3d->ofs_lock[0] -= ((vod->prev.event_xy[0] - x) * 2.0f) / (float)vod->region->winx;
+ vod->rv3d->ofs_lock[1] -= ((vod->prev.event_xy[1] - y) * 2.0f) / (float)vod->region->winy;
+ }
+ else if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
+ const float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
+ vod->rv3d->camdx += (vod->prev.event_xy[0] - x) / (vod->region->winx * zoomfac);
+ vod->rv3d->camdy += (vod->prev.event_xy[1] - y) / (vod->region->winy * zoomfac);
+ CLAMP(vod->rv3d->camdx, -1.0f, 1.0f);
+ CLAMP(vod->rv3d->camdy, -1.0f, 1.0f);
+ }
+ else {
+ float dvec[3];
+ float mval_f[2];
+
+ mval_f[0] = x - vod->prev.event_xy[0];
+ mval_f[1] = y - vod->prev.event_xy[1];
+ ED_view3d_win_to_delta(vod->region, mval_f, dvec, vod->init.zfac);
+
+ add_v3_v3(vod->rv3d->ofs, dvec);
+
+ if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(vod->area, vod->region);
+ }
+ }
+
+ vod->prev.event_xy[0] = x;
+ vod->prev.event_xy[1] = y;
+
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
+
+ ED_region_tag_redraw(vod->region);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View All Operator
+ *
+ * Move & Zoom the view to fit all of its contents.
+ * \{ */
+
+static bool view3d_object_skip_minmax(const View3D *v3d,
+ const RegionView3D *rv3d,
+ const Object *ob,
+ const bool skip_camera,
+ bool *r_only_center)
+{
+ BLI_assert(ob->id.orig_id == NULL);
+ *r_only_center = false;
+
+ if (skip_camera && (ob == v3d->camera)) {
+ return true;
+ }
+
+ if ((ob->type == OB_EMPTY) && (ob->empty_drawtype == OB_EMPTY_IMAGE) &&
+ !BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d)) {
+ *r_only_center = true;
+ return false;
+ }
+
+ return false;
+}
+
+static void view3d_object_calc_minmax(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob_eval,
+ const bool only_center,
+ float min[3],
+ float max[3])
+{
+ /* Account for duplis. */
+ if (BKE_object_minmax_dupli(depsgraph, scene, ob_eval, min, max, false) == 0) {
+ /* Use if duplis aren't found. */
+ if (only_center) {
+ minmax_v3v3_v3(min, max, ob_eval->obmat[3]);
+ }
+ else {
+ BKE_object_minmax(ob_eval, min, max, false);
+ }
+ }
+}
+
+static void view3d_from_minmax(bContext *C,
+ View3D *v3d,
+ ARegion *region,
+ const float min[3],
+ const float max[3],
+ bool ok_dist,
+ const int smooth_viewtx)
+{
+ RegionView3D *rv3d = region->regiondata;
+ float afm[3];
+ float size;
+
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
+
+ /* SMOOTHVIEW */
+ float new_ofs[3];
+ float new_dist;
+
+ sub_v3_v3v3(afm, max, min);
+ size = max_fff(afm[0], afm[1], afm[2]);
+
+ if (ok_dist) {
+ char persp;
+
+ if (rv3d->is_persp) {
+ if (rv3d->persp == RV3D_CAMOB && ED_view3d_camera_lock_check(v3d, rv3d)) {
+ persp = RV3D_CAMOB;
+ }
+ else {
+ persp = RV3D_PERSP;
+ }
+ }
+ else { /* ortho */
+ if (size < 0.0001f) {
+ /* bounding box was a single point so do not zoom */
+ ok_dist = false;
+ }
+ else {
+ /* adjust zoom so it looks nicer */
+ persp = RV3D_ORTHO;
+ }
+ }
+
+ if (ok_dist) {
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ new_dist = ED_view3d_radius_to_dist(
+ v3d, region, depsgraph, persp, true, (size / 2) * VIEW3D_MARGIN);
+ if (rv3d->is_persp) {
+ /* don't zoom closer than the near clipping plane */
+ new_dist = max_ff(new_dist, v3d->clip_start * 1.5f);
+ }
+ }
+ }
+
+ mid_v3_v3v3(new_ofs, min, max);
+ negate_v3(new_ofs);
+
+ if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) {
+ rv3d->persp = RV3D_PERSP;
+ ED_view3d_smooth_view(C,
+ v3d,
+ region,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .camera_old = v3d->camera,
+ .ofs = new_ofs,
+ .dist = ok_dist ? &new_dist : NULL,
+ });
+ }
+ else {
+ ED_view3d_smooth_view(C,
+ v3d,
+ region,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .ofs = new_ofs,
+ .dist = ok_dist ? &new_dist : NULL,
+ });
+ }
+
+ /* Smooth-view does view-lock #RV3D_BOXVIEW copy. */
+}
+
+/**
+ * Same as #view3d_from_minmax but for all regions (except cameras).
+ */
+static void view3d_from_minmax_multi(bContext *C,
+ View3D *v3d,
+ const float min[3],
+ const float max[3],
+ const bool ok_dist,
+ const int smooth_viewtx)
+{
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region;
+ for (region = area->regionbase.first; region; region = region->next) {
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = region->regiondata;
+ /* when using all regions, don't jump out of camera view,
+ * but _do_ allow locked cameras to be moved */
+ if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
+ view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx);
+ }
+ }
+ }
+}
+
+static int view3d_all_exec(bContext *C, wmOperator *op)
+{
+ ARegion *region = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
+ Base *base_eval;
+ const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
+ const bool skip_camera = (ED_view3d_camera_lock_check(v3d, region->regiondata) ||
+ /* any one of the regions may be locked */
+ (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
+ const bool center = RNA_boolean_get(op->ptr, "center");
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ float min[3], max[3];
+ bool changed = false;
+
+ if (center) {
+ /* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */
+ View3DCursor *cursor = &scene->cursor;
+ zero_v3(min);
+ zero_v3(max);
+ zero_v3(cursor->location);
+ float mat3[3][3];
+ unit_m3(mat3);
+ BKE_scene_cursor_mat3_to_rot(cursor, mat3, false);
+ }
+ else {
+ INIT_MINMAX(min, max);
+ }
+
+ for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
+ if (BASE_VISIBLE(v3d, base_eval)) {
+ bool only_center = false;
+ Object *ob = DEG_get_original_object(base_eval->object);
+ if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) {
+ continue;
+ }
+ view3d_object_calc_minmax(depsgraph, scene, base_eval->object, only_center, min, max);
+ changed = true;
+ }
+ }
+
+ if (center) {
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ WM_msg_publish_rna_prop(mbus, &scene->id, &scene->cursor, View3DCursor, location);
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ if (!changed) {
+ ED_region_tag_redraw(region);
+ /* TODO: should this be cancel?
+ * I think no, because we always move the cursor, with or without
+ * object, but in this case there is no change in the scene,
+ * only the cursor so I choice a ED_region_tag like
+ * view3d_smooth_view do for the center_cursor.
+ * See bug T22640.
+ */
+ return OPERATOR_FINISHED;
+ }
+
+ if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
+ /* This is an approximation, see function documentation for details. */
+ ED_view3d_clipping_clamp_minmax(rv3d, min, max);
+ }
+
+ if (use_all_regions) {
+ view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx);
+ }
+ else {
+ view3d_from_minmax(C, v3d, region, min, max, true, smooth_viewtx);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_view_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Frame All";
+ ot->description = "View all objects in scene";
+ ot->idname = "VIEW3D_OT_view_all";
+
+ /* api callbacks */
+ ot->exec = view3d_all_exec;
+ ot->poll = ED_operator_region_view3d_active;
+
+ /* flags */
+ ot->flag = 0;
+
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
+ RNA_def_boolean(ot->srna, "center", 0, "Center", "");
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Frame Selected Operator
+ *
+ * Move & Zoom the view to fit selected contents.
+ * \{ */
+
+static int viewselected_exec(bContext *C, wmOperator *op)
+{
+ ARegion *region = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
+ Object *ob_eval = OBACT(view_layer_eval);
+ Object *obedit = CTX_data_edit_object(C);
+ const bGPdata *gpd_eval = ob_eval && (ob_eval->type == OB_GPENCIL) ? ob_eval->data : NULL;
+ const bool is_gp_edit = gpd_eval ? GPENCIL_ANY_MODE(gpd_eval) : false;
+ const bool is_face_map = ((is_gp_edit == false) && region->gizmo_map &&
+ WM_gizmomap_is_any_selected(region->gizmo_map));
+ float min[3], max[3];
+ bool ok = false, ok_dist = true;
+ const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
+ const bool skip_camera = (ED_view3d_camera_lock_check(v3d, region->regiondata) ||
+ /* any one of the regions may be locked */
+ (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ INIT_MINMAX(min, max);
+ if (is_face_map) {
+ ob_eval = NULL;
+ }
+
+ if (ob_eval && (ob_eval->mode & OB_MODE_WEIGHT_PAINT)) {
+ /* hard-coded exception, we look for the one selected armature */
+ /* this is weak code this way, we should make a generic
+ * active/selection callback interface once... */
+ Base *base_eval;
+ for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
+ if (BASE_SELECTED_EDITABLE(v3d, base_eval)) {
+ if (base_eval->object->type == OB_ARMATURE) {
+ if (base_eval->object->mode & OB_MODE_POSE) {
+ break;
+ }
+ }
+ }
+ }
+ if (base_eval) {
+ ob_eval = base_eval->object;
+ }
+ }
+
+ if (is_gp_edit) {
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ /* we're only interested in selected points here... */
+ if ((gps->flag & GP_STROKE_SELECT) && (gps->flag & GP_STROKE_3DSPACE)) {
+ ok |= BKE_gpencil_stroke_minmax(gps, true, min, max);
+ }
+ if (gps->editcurve != NULL) {
+ for (int i = 0; i < gps->editcurve->tot_curve_points; i++) {
+ BezTriple *bezt = &gps->editcurve->curve_points[i].bezt;
+ if ((bezt->f1 & SELECT)) {
+ minmax_v3v3_v3(min, max, bezt->vec[0]);
+ ok = true;
+ }
+ if ((bezt->f2 & SELECT)) {
+ minmax_v3v3_v3(min, max, bezt->vec[1]);
+ ok = true;
+ }
+ if ((bezt->f3 & SELECT)) {
+ minmax_v3v3_v3(min, max, bezt->vec[2]);
+ ok = true;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if ((ob_eval) && (ok)) {
+ mul_m4_v3(ob_eval->obmat, min);
+ mul_m4_v3(ob_eval->obmat, max);
+ }
+ }
+ else if (is_face_map) {
+ ok = WM_gizmomap_minmax(region->gizmo_map, true, true, min, max);
+ }
+ else if (obedit) {
+ /* only selected */
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, v3d, obedit->type, obedit->mode, ob_eval_iter) {
+ ok |= ED_view3d_minmax_verts(ob_eval_iter, min, max);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ else if (ob_eval && (ob_eval->mode & OB_MODE_POSE)) {
+ FOREACH_OBJECT_IN_MODE_BEGIN (
+ view_layer_eval, v3d, ob_eval->type, ob_eval->mode, ob_eval_iter) {
+ ok |= BKE_pose_minmax(ob_eval_iter, min, max, true, true);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+ }
+ else if (BKE_paint_select_face_test(ob_eval)) {
+ ok = paintface_minmax(ob_eval, min, max);
+ }
+ else if (ob_eval && (ob_eval->mode & OB_MODE_PARTICLE_EDIT)) {
+ ok = PE_minmax(depsgraph, scene, CTX_data_view_layer(C), min, max);
+ }
+ else if (ob_eval && (ob_eval->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT |
+ OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
+ BKE_paint_stroke_get_average(scene, ob_eval, min);
+ copy_v3_v3(max, min);
+ ok = true;
+ ok_dist = 0; /* don't zoom */
+ }
+ else {
+ Base *base_eval;
+ for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
+ if (BASE_SELECTED(v3d, base_eval)) {
+ bool only_center = false;
+ Object *ob = DEG_get_original_object(base_eval->object);
+ if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) {
+ continue;
+ }
+ view3d_object_calc_minmax(depsgraph, scene, base_eval->object, only_center, min, max);
+ ok = 1;
+ }
+ }
+ }
+
+ if (ok == 0) {
+ return OPERATOR_FINISHED;
+ }
+
+ if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
+ /* This is an approximation, see function documentation for details. */
+ ED_view3d_clipping_clamp_minmax(rv3d, min, max);
+ }
+
+ if (use_all_regions) {
+ view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx);
+ }
+ else {
+ view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_view_selected(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Frame Selected";
+ ot->description = "Move the view to the selection center";
+ ot->idname = "VIEW3D_OT_view_selected";
+
+ /* api callbacks */
+ ot->exec = viewselected_exec;
+ ot->poll = view3d_zoom_or_dolly_poll;
+
+ /* flags */
+ ot->flag = 0;
+
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Center Cursor Operator
+ * \{ */
+
+static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (rv3d) {
+ ARegion *region = CTX_wm_region(C);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
+
+ /* non camera center */
+ float new_ofs[3];
+ negate_v3_v3(new_ofs, scene->cursor.location);
+ ED_view3d_smooth_view(
+ C, v3d, region, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs});
+
+ /* Smooth view does view-lock #RV3D_BOXVIEW copy. */
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Center View to Cursor";
+ ot->description = "Center the view so that the cursor is in the middle of the view";
+ ot->idname = "VIEW3D_OT_view_center_cursor";
+
+ /* api callbacks */
+ ot->exec = viewcenter_cursor_exec;
+ ot->poll = view3d_location_poll;
+
+ /* flags */
+ ot->flag = 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Center Pick Operator
+ * \{ */
+
+static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ ARegion *region = CTX_wm_region(C);
+
+ if (rv3d) {
+ struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ float new_ofs[3];
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
+
+ view3d_operator_needs_opengl(C);
+
+ if (ED_view3d_autodist(depsgraph, region, v3d, event->mval, new_ofs, false, NULL)) {
+ /* pass */
+ }
+ else {
+ /* fallback to simple pan */
+ negate_v3_v3(new_ofs, rv3d->ofs);
+ ED_view3d_win_to_3d_int(v3d, region, new_ofs, event->mval, new_ofs);
+ }
+ negate_v3(new_ofs);
+ ED_view3d_smooth_view(
+ C, v3d, region, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs});
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Center View to Mouse";
+ ot->description = "Center the view to the Z-depth position under the mouse cursor";
+ ot->idname = "VIEW3D_OT_view_center_pick";
+
+ /* api callbacks */
+ ot->invoke = viewcenter_pick_invoke;
+ ot->poll = view3d_location_poll;
+
+ /* flags */
+ ot->flag = 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Axis Operator
+ * \{ */
+
+static const EnumPropertyItem prop_view_items[] = {
+ {RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View from the left"},
+ {RV3D_VIEW_RIGHT, "RIGHT", ICON_TRIA_RIGHT, "Right", "View from the right"},
+ {RV3D_VIEW_BOTTOM, "BOTTOM", ICON_TRIA_DOWN, "Bottom", "View from the bottom"},
+ {RV3D_VIEW_TOP, "TOP", ICON_TRIA_UP, "Top", "View from the top"},
+ {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View from the front"},
+ {RV3D_VIEW_BACK, "BACK", 0, "Back", "View from the back"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int view_axis_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d;
+ ARegion *region;
+ RegionView3D *rv3d;
+ static int perspo = RV3D_PERSP;
+ int viewnum;
+ int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ /* no NULL check is needed, poll checks */
+ ED_view3d_context_user_region(C, &v3d, &region);
+ rv3d = region->regiondata;
+
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
+
+ viewnum = RNA_enum_get(op->ptr, "type");
+
+ float align_quat_buf[4];
+ float *align_quat = NULL;
+
+ if (RNA_boolean_get(op->ptr, "align_active")) {
+ /* align to active object */
+ Object *obact = CTX_data_active_object(C);
+ if (obact != NULL) {
+ float twmat[3][3];
+ struct ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = CTX_data_edit_object(C);
+ /* same as transform gizmo when normal is set */
+ ED_getTransformOrientationMatrix(view_layer, v3d, obact, obedit, V3D_AROUND_ACTIVE, twmat);
+ align_quat = align_quat_buf;
+ mat3_to_quat(align_quat, twmat);
+ invert_qt_normalized(align_quat);
+ }
+ }
+
+ if (RNA_boolean_get(op->ptr, "relative")) {
+ float quat_rotate[4];
+ float quat_test[4];
+
+ if (viewnum == RV3D_VIEW_LEFT) {
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], -M_PI / 2.0f);
+ }
+ else if (viewnum == RV3D_VIEW_RIGHT) {
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], M_PI / 2.0f);
+ }
+ else if (viewnum == RV3D_VIEW_TOP) {
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], -M_PI / 2.0f);
+ }
+ else if (viewnum == RV3D_VIEW_BOTTOM) {
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI / 2.0f);
+ }
+ else if (viewnum == RV3D_VIEW_FRONT) {
+ unit_qt(quat_rotate);
+ }
+ else if (viewnum == RV3D_VIEW_BACK) {
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ mul_qt_qtqt(quat_test, rv3d->viewquat, quat_rotate);
+
+ float angle_best = FLT_MAX;
+ int view_best = -1;
+ int view_axis_roll_best = -1;
+ for (int i = RV3D_VIEW_FRONT; i <= RV3D_VIEW_BOTTOM; i++) {
+ for (int j = RV3D_VIEW_AXIS_ROLL_0; j <= RV3D_VIEW_AXIS_ROLL_270; j++) {
+ float quat_axis[4];
+ ED_view3d_quat_from_axis_view(i, j, quat_axis);
+ if (align_quat) {
+ mul_qt_qtqt(quat_axis, quat_axis, align_quat);
+ }
+ const float angle_test = fabsf(angle_signed_qtqt(quat_axis, quat_test));
+ if (angle_best > angle_test) {
+ angle_best = angle_test;
+ view_best = i;
+ view_axis_roll_best = j;
+ }
+ }
+ }
+ if (view_best == -1) {
+ view_best = RV3D_VIEW_FRONT;
+ view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
+ }
+
+ /* Disallow non-upright views in turn-table modes,
+ * it's too difficult to navigate out of them. */
+ if ((U.flag & USER_TRACKBALL) == 0) {
+ if (!ELEM(view_best, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
+ view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
+ }
+ }
+
+ viewnum = view_best;
+ view_axis_roll = view_axis_roll_best;
+ }
+
+ /* Use this to test if we started out with a camera */
+ const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo;
+ float quat[4];
+ ED_view3d_quat_from_axis_view(viewnum, view_axis_roll, quat);
+ axis_set_view(
+ C, v3d, region, quat, viewnum, view_axis_roll, nextperspo, align_quat, smooth_viewtx);
+
+ perspo = rv3d->persp;
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_view_axis(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "View Axis";
+ ot->description = "Use a preset viewpoint";
+ ot->idname = "VIEW3D_OT_view_axis";
+
+ /* api callbacks */
+ ot->exec = view_axis_exec;
+ ot->poll = ED_operator_rv3d_user_region_poll;
+
+ /* flags */
+ ot->flag = 0;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "Preset viewpoint to use");
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "align_active", 0, "Align Active", "Align to the active object's axis");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "relative", 0, "Relative", "Rotate relative to the current orientation");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Camera Operator
+ * \{ */
+
+static int view_camera_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d;
+ ARegion *region;
+ RegionView3D *rv3d;
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ /* no NULL check is needed, poll checks */
+ ED_view3d_context_user_region(C, &v3d, &region);
+ rv3d = region->regiondata;
+
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
+
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (rv3d->persp != RV3D_CAMOB) {
+ Object *ob = OBACT(view_layer);
+
+ if (!rv3d->smooth_timer) {
+ /* store settings of current view before allowing overwriting with camera view
+ * only if we're not currently in a view transition */
+
+ ED_view3d_lastview_store(rv3d);
+ }
+
+ /* first get the default camera for the view lock type */
+ if (v3d->scenelock) {
+ /* sets the camera view if available */
+ v3d->camera = scene->camera;
+ }
+ else {
+ /* use scene camera if one is not set (even though we're unlocked) */
+ if (v3d->camera == NULL) {
+ v3d->camera = scene->camera;
+ }
+ }
+
+ /* if the camera isn't found, check a number of options */
+ if (v3d->camera == NULL && ob && ob->type == OB_CAMERA) {
+ v3d->camera = ob;
+ }
+
+ if (v3d->camera == NULL) {
+ v3d->camera = BKE_view_layer_camera_find(view_layer);
+ }
+
+ /* couldn't find any useful camera, bail out */
+ if (v3d->camera == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* important these don't get out of sync for locked scenes */
+ if (v3d->scenelock && scene->camera != v3d->camera) {
+ scene->camera = v3d->camera;
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ }
+
+ /* finally do snazzy view zooming */
+ rv3d->persp = RV3D_CAMOB;
+ ED_view3d_smooth_view(C,
+ v3d,
+ region,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .camera = v3d->camera,
+ .ofs = rv3d->ofs,
+ .quat = rv3d->viewquat,
+ .dist = &rv3d->dist,
+ .lens = &v3d->lens,
+ });
+ }
+ else {
+ /* return to settings of last view */
+ /* does view3d_smooth_view too */
+ axis_set_view(C,
+ v3d,
+ region,
+ rv3d->lviewquat,
+ rv3d->lview,
+ rv3d->lview_axis_roll,
+ rv3d->lpersp,
+ NULL,
+ smooth_viewtx);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_view_camera(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "View Camera";
+ ot->description = "Toggle the camera view";
+ ot->idname = "VIEW3D_OT_view_camera";
+
+ /* api callbacks */
+ ot->exec = view_camera_exec;
+ ot->poll = ED_operator_rv3d_user_region_poll;
+
+ /* flags */
+ ot->flag = 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Orbit Operator
+ *
+ * Rotate (orbit) in incremental steps. For interactive orbit see #VIEW3D_OT_rotate.
+ * \{ */
+
+enum {
+ V3D_VIEW_STEPLEFT = 1,
+ V3D_VIEW_STEPRIGHT,
+ V3D_VIEW_STEPDOWN,
+ V3D_VIEW_STEPUP,
+};
+
+static const EnumPropertyItem prop_view_orbit_items[] = {
+ {V3D_VIEW_STEPLEFT, "ORBITLEFT", 0, "Orbit Left", "Orbit the view around to the left"},
+ {V3D_VIEW_STEPRIGHT, "ORBITRIGHT", 0, "Orbit Right", "Orbit the view around to the right"},
+ {V3D_VIEW_STEPUP, "ORBITUP", 0, "Orbit Up", "Orbit the view up"},
+ {V3D_VIEW_STEPDOWN, "ORBITDOWN", 0, "Orbit Down", "Orbit the view down"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int vieworbit_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d;
+ ARegion *region;
+ RegionView3D *rv3d;
+ int orbitdir;
+ char view_opposite;
+ PropertyRNA *prop_angle = RNA_struct_find_property(op->ptr, "angle");
+ float angle = RNA_property_is_set(op->ptr, prop_angle) ?
+ RNA_property_float_get(op->ptr, prop_angle) :
+ DEG2RADF(U.pad_rot_angle);
+
+ /* no NULL check is needed, poll checks */
+ v3d = CTX_wm_view3d(C);
+ region = CTX_wm_region(C);
+ rv3d = region->regiondata;
+
+ /* support for switching to the opposite view (even when in locked views) */
+ view_opposite = (fabsf(angle) == (float)M_PI) ? ED_view3d_axis_view_opposite(rv3d->view) :
+ RV3D_VIEW_USER;
+ orbitdir = RNA_enum_get(op->ptr, "type");
+
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) && (view_opposite == RV3D_VIEW_USER)) {
+ /* no NULL check is needed, poll checks */
+ ED_view3d_context_user_region(C, &v3d, &region);
+ rv3d = region->regiondata;
+ }
+
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
+
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0 || (view_opposite != RV3D_VIEW_USER)) {
+ if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
+ int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ float quat_mul[4];
+ float quat_new[4];
+
+ if (view_opposite == RV3D_VIEW_USER) {
+ const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ED_view3d_persp_ensure(depsgraph, v3d, region);
+ }
+
+ if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
+ if (orbitdir == V3D_VIEW_STEPRIGHT) {
+ angle = -angle;
+ }
+
+ /* z-axis */
+ axis_angle_to_quat_single(quat_mul, 'Z', angle);
+ }
+ else {
+
+ if (orbitdir == V3D_VIEW_STEPDOWN) {
+ angle = -angle;
+ }
+
+ /* horizontal axis */
+ axis_angle_to_quat(quat_mul, rv3d->viewinv[0], angle);
+ }
+
+ mul_qt_qtqt(quat_new, rv3d->viewquat, quat_mul);
+
+ /* avoid precision loss over time */
+ normalize_qt(quat_new);
+
+ if (view_opposite != RV3D_VIEW_USER) {
+ rv3d->view = view_opposite;
+ /* avoid float in-precision, just get a new orientation */
+ ED_view3d_quat_from_axis_view(view_opposite, rv3d->view_axis_roll, quat_new);
+ }
+ else {
+ rv3d->view = RV3D_VIEW_USER;
+ }
+
+ float dyn_ofs[3], *dyn_ofs_pt = NULL;
+
+ if (U.uiflag & USER_ORBIT_SELECTION) {
+ if (view3d_orbit_calc_center(C, dyn_ofs)) {
+ negate_v3(dyn_ofs);
+ dyn_ofs_pt = dyn_ofs;
+ }
+ }
+
+ ED_view3d_smooth_view(C,
+ v3d,
+ region,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .quat = quat_new,
+ .dyn_ofs = dyn_ofs_pt,
+ });
+
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void VIEW3D_OT_view_orbit(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "View Orbit";
+ ot->description = "Orbit the view";
+ ot->idname = "VIEW3D_OT_view_orbit";
+
+ /* api callbacks */
+ ot->exec = vieworbit_exec;
+ ot->poll = ED_operator_rv3d_user_region_poll;
+
+ /* flags */
+ ot->flag = 0;
+
+ /* properties */
+ prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Pan Operator
+ *
+ * Move (pan) in incremental steps. For interactive pan see #VIEW3D_OT_move.
+ * \{ */
+
+enum {
+ V3D_VIEW_PANLEFT = 1,
+ V3D_VIEW_PANRIGHT,
+ V3D_VIEW_PANDOWN,
+ V3D_VIEW_PANUP,
+};
+
+static const EnumPropertyItem prop_view_pan_items[] = {
+ {V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the left"},
+ {V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the right"},
+ {V3D_VIEW_PANUP, "PANUP", 0, "Pan Up", "Pan the view up"},
+ {V3D_VIEW_PANDOWN, "PANDOWN", 0, "Pan Down", "Pan the view down"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int x = 0, y = 0;
+ int pandir = RNA_enum_get(op->ptr, "type");
+
+ if (pandir == V3D_VIEW_PANRIGHT) {
+ x = -32;
+ }
+ else if (pandir == V3D_VIEW_PANLEFT) {
+ x = 32;
+ }
+ else if (pandir == V3D_VIEW_PANUP) {
+ y = -25;
+ }
+ else if (pandir == V3D_VIEW_PANDOWN) {
+ y = 25;
+ }
+
+ ViewOpsData *vod = viewops_data_create(
+ C, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT));
+
+ viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y);
+
+ viewops_data_free(C, vod);
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_view_pan(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Pan View Direction";
+ ot->description = "Pan the view in a given direction";
+ ot->idname = "VIEW3D_OT_view_pan";
+
+ /* api callbacks */
+ ot->invoke = viewpan_invoke;
+ ot->poll = view3d_location_poll;
+
+ /* flags */
+ ot->flag = 0;
+
+ /* Properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan");
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_navigate.h b/source/blender/editors/space_view3d/view3d_navigate.h
new file mode 100644
index 00000000000..792d2a83bc2
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_navigate.h
@@ -0,0 +1,282 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup spview3d
+ */
+
+#pragma once
+
+/**
+ * Size of the sphere being dragged for trackball rotation within the view bounds.
+ * also affects speed (smaller is faster).
+ */
+#define V3D_OP_TRACKBALLSIZE (1.1f)
+
+struct ARegion;
+struct bContext;
+struct Depsgraph;
+struct Dial;
+struct Main;
+struct rcti;
+struct RegionView3D;
+struct Scene;
+struct ScrArea;
+struct View3D;
+struct wmEvent;
+struct wmOperator;
+
+enum eV3D_OpPropFlag {
+ V3D_OP_PROP_MOUSE_CO = (1 << 0),
+ V3D_OP_PROP_DELTA = (1 << 1),
+ V3D_OP_PROP_USE_ALL_REGIONS = (1 << 2),
+ V3D_OP_PROP_USE_MOUSE_INIT = (1 << 3),
+};
+
+enum {
+ VIEW_PASS = 0,
+ VIEW_APPLY,
+ VIEW_CONFIRM,
+};
+
+/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
+enum {
+ VIEW_MODAL_CONFIRM = 1, /* used for all view operations */
+ VIEWROT_MODAL_AXIS_SNAP_ENABLE = 2,
+ VIEWROT_MODAL_AXIS_SNAP_DISABLE = 3,
+ VIEWROT_MODAL_SWITCH_ZOOM = 4,
+ VIEWROT_MODAL_SWITCH_MOVE = 5,
+ VIEWROT_MODAL_SWITCH_ROTATE = 6,
+};
+
+enum eViewOpsFlag {
+ /** When enabled, rotate around the selection. */
+ VIEWOPS_FLAG_ORBIT_SELECT = (1 << 0),
+ /** When enabled, use the depth under the cursor for navigation. */
+ VIEWOPS_FLAG_DEPTH_NAVIGATE = (1 << 1),
+ /**
+ * When enabled run #ED_view3d_persp_ensure this may switch out of camera view
+ * when orbiting or switch from orthographic to perspective when auto-perspective is enabled.
+ * Some operations don't require this (view zoom/pan or NDOF where subtle rotation is common
+ * so we don't want it to trigger auto-perspective). */
+ VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2),
+ /** When set, ignore any options that depend on initial cursor location. */
+ VIEWOPS_FLAG_USE_MOUSE_INIT = (1 << 3),
+};
+
+/** Generic View Operator Custom-Data */
+typedef struct ViewOpsData {
+ /** Context pointers (assigned by #viewops_data_create). */
+ struct Main *bmain;
+ struct Scene *scene;
+ struct ScrArea *area;
+ struct ARegion *region;
+ struct View3D *v3d;
+ struct RegionView3D *rv3d;
+ struct Depsgraph *depsgraph;
+
+ /** Needed for continuous zoom. */
+ struct wmTimer *timer;
+
+ /** Viewport state on initialization, don't change afterwards. */
+ struct {
+ float dist;
+ float camzoom;
+ float quat[4];
+ /** #wmEvent.xy. */
+ int event_xy[2];
+ /** Offset to use when #VIEWOPS_FLAG_USE_MOUSE_INIT is not set.
+ * so we can simulate pressing in the middle of the screen. */
+ int event_xy_offset[2];
+ /** #wmEvent.type that triggered the operator. */
+ int event_type;
+ float ofs[3];
+ /** Initial distance to 'ofs'. */
+ float zfac;
+
+ /** Trackball rotation only. */
+ float trackvec[3];
+ /** Dolly only. */
+ float mousevec[3];
+
+ /**
+ * #RegionView3D.persp set after auto-perspective is applied.
+ * If we want the value before running the operator, add a separate member.
+ */
+ char persp;
+
+ /** Used for roll */
+ struct Dial *dial;
+ } init;
+
+ /** Previous state (previous modal event handled). */
+ struct {
+ int event_xy[2];
+ /** For operators that use time-steps (continuous zoom). */
+ double time;
+ } prev;
+
+ /** Current state. */
+ struct {
+ /** Working copy of #RegionView3D.viewquat, needed for rotation calculation
+ * so we can apply snap to the 3D Viewport while keeping the unsnapped rotation
+ * here to use when snap is disabled and for continued calculation. */
+ float viewquat[4];
+ } curr;
+
+ float reverse;
+ bool axis_snap; /* view rotate only */
+
+ /** Use for orbit selection and auto-dist. */
+ float dyn_ofs[3];
+ bool use_dyn_ofs;
+} ViewOpsData;
+
+/* view3d_navigate.c */
+bool view3d_location_poll(struct bContext *C);
+bool view3d_rotation_poll(struct bContext *C);
+bool view3d_zoom_or_dolly_poll(struct bContext *C);
+
+enum eViewOpsFlag viewops_flag_from_prefs(void);
+void calctrackballvec(const struct rcti *rect, const int event_xy[2], float r_dir[3]);
+void viewmove_apply(ViewOpsData *vod, int x, int y);
+void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
+ const float ofs_old[3],
+ const float viewquat_old[4],
+ const float viewquat_new[4],
+ const float dyn_ofs[3]);
+void viewrotate_apply_dyn_ofs(ViewOpsData *vod, const float viewquat_new[4]);
+bool view3d_orbit_calc_center(struct bContext *C, float r_dyn_ofs[3]);
+
+void view3d_operator_properties_common(struct wmOperatorType *ot, const enum eV3D_OpPropFlag flag);
+
+/**
+ * Allocate and fill in context pointers for #ViewOpsData
+ */
+void viewops_data_free(struct bContext *C, ViewOpsData *vod);
+
+/**
+ * Allocate, fill in context pointers and calculate the values for #ViewOpsData
+ */
+ViewOpsData *viewops_data_create(struct bContext *C,
+ const struct wmEvent *event,
+ enum eViewOpsFlag viewops_flag);
+
+void VIEW3D_OT_view_all(struct wmOperatorType *ot);
+void VIEW3D_OT_view_selected(struct wmOperatorType *ot);
+void VIEW3D_OT_view_center_cursor(struct wmOperatorType *ot);
+void VIEW3D_OT_view_center_pick(struct wmOperatorType *ot);
+void VIEW3D_OT_view_axis(struct wmOperatorType *ot);
+void VIEW3D_OT_view_camera(struct wmOperatorType *ot);
+void VIEW3D_OT_view_orbit(struct wmOperatorType *ot);
+void VIEW3D_OT_view_pan(struct wmOperatorType *ot);
+
+/* view3d_navigate_dolly.c */
+void viewdolly_modal_keymap(struct wmKeyConfig *keyconf);
+void VIEW3D_OT_dolly(struct wmOperatorType *ot);
+
+/* view3d_navigate_fly.c */
+void fly_modal_keymap(struct wmKeyConfig *keyconf);
+void view3d_keymap(struct wmKeyConfig *keyconf);
+void VIEW3D_OT_fly(struct wmOperatorType *ot);
+
+/* view3d_navigate_move.c */
+void viewmove_modal_keymap(struct wmKeyConfig *keyconf);
+void VIEW3D_OT_move(struct wmOperatorType *ot);
+
+/* view3d_navigate_ndof.c */
+#ifdef WITH_INPUT_NDOF
+struct wmNDOFMotionData;
+
+/**
+ * Called from both fly mode and walk mode,
+ */
+void view3d_ndof_fly(const struct wmNDOFMotionData *ndof,
+ struct View3D *v3d,
+ struct RegionView3D *rv3d,
+ bool use_precision,
+ short protectflag,
+ bool *r_has_translate,
+ bool *r_has_rotate);
+void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot);
+void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot);
+void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot);
+void VIEW3D_OT_ndof_all(struct wmOperatorType *ot);
+#endif /* WITH_INPUT_NDOF */
+
+/* view3d_navigate_roll.c */
+void VIEW3D_OT_view_roll(struct wmOperatorType *ot);
+
+/* view3d_navigate_rotate.c */
+void viewrotate_modal_keymap(struct wmKeyConfig *keyconf);
+void VIEW3D_OT_rotate(struct wmOperatorType *ot);
+
+/* view3d_navigate_smoothview.c */
+
+/**
+ * Parameters for setting the new 3D Viewport state.
+ *
+ * Each of the struct members may be NULL to signify they aren't to be adjusted.
+ */
+typedef struct V3D_SmoothParams {
+ struct Object *camera_old, *camera;
+ const float *ofs, *quat, *dist, *lens;
+
+ /** Alternate rotation center, when set `ofs` must be NULL. */
+ const float *dyn_ofs;
+} V3D_SmoothParams;
+
+/**
+ * The arguments are the desired situation.
+ */
+void ED_view3d_smooth_view_ex(const struct Depsgraph *depsgraph,
+ struct wmWindowManager *wm,
+ struct wmWindow *win,
+ struct ScrArea *area,
+ struct View3D *v3d,
+ struct ARegion *region,
+ int smooth_viewtx,
+ const V3D_SmoothParams *sview);
+
+void ED_view3d_smooth_view(struct bContext *C,
+ struct View3D *v3d,
+ struct ARegion *region,
+ int smooth_viewtx,
+ const V3D_SmoothParams *sview);
+
+/**
+ * Apply the smooth-view immediately, use when we need to start a new view operation.
+ * (so we don't end up half-applying a view operation when pressing keys quickly).
+ */
+void ED_view3d_smooth_view_force_finish(struct bContext *C,
+ struct View3D *v3d,
+ struct ARegion *region);
+
+void VIEW3D_OT_smoothview(struct wmOperatorType *ot);
+
+/* view3d_navigate_walk.c */
+void walk_modal_keymap(struct wmKeyConfig *keyconf);
+void VIEW3D_OT_walk(struct wmOperatorType *ot);
+
+/* view3d_navigate_zoom.c */
+void viewzoom_modal_keymap(struct wmKeyConfig *keyconf);
+void VIEW3D_OT_zoom(struct wmOperatorType *ot);
+
+/* view3d_navigate_zoom_border.c */
+void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_view3d/view3d_navigate_dolly.c b/source/blender/editors/space_view3d/view3d_navigate_dolly.c
new file mode 100644
index 00000000000..02783c2a244
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_navigate_dolly.c
@@ -0,0 +1,337 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup spview3d
+ */
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_report.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+
+#include "RNA_access.h"
+
+#include "ED_screen.h"
+
+#include "view3d_intern.h"
+#include "view3d_navigate.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name View Dolly Operator
+ *
+ * Like zoom but translates the view offset along the view direction
+ * which avoids #RegionView3D.dist approaching zero.
+ * \{ */
+
+/* This is an exact copy of #viewzoom_modal_keymap. */
+void viewdolly_modal_keymap(wmKeyConfig *keyconf)
+{
+ static const EnumPropertyItem modal_items[] = {
+ {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+
+ {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
+ {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
+
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Dolly Modal");
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if (keymap && keymap->modal_items) {
+ return;
+ }
+
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Dolly Modal", modal_items);
+
+ /* disabled mode switching for now, can re-implement better, later on */
+#if 0
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+#endif
+
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly");
+}
+
+static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (ED_view3d_offset_lock_check(v3d, rv3d)) {
+ BKE_report(op->reports, RPT_WARNING, "Cannot dolly when the view offset is locked");
+ return true;
+ }
+ return false;
+}
+
+static void view_dolly_to_vector_3d(ARegion *region,
+ const float orig_ofs[3],
+ const float dvec[3],
+ float dfac)
+{
+ RegionView3D *rv3d = region->regiondata;
+ madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac));
+}
+
+static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const bool zoom_invert)
+{
+ float zfac = 1.0;
+
+ {
+ float len1, len2;
+
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ len1 = (vod->region->winrct.xmax - xy[0]) + 5;
+ len2 = (vod->region->winrct.xmax - vod->init.event_xy[0]) + 5;
+ }
+ else {
+ len1 = (vod->region->winrct.ymax - xy[1]) + 5;
+ len2 = (vod->region->winrct.ymax - vod->init.event_xy[1]) + 5;
+ }
+ if (zoom_invert) {
+ SWAP(float, len1, len2);
+ }
+
+ zfac = 1.0f + ((len1 - len2) * 0.01f * vod->rv3d->dist);
+ }
+
+ if (zfac != 1.0f) {
+ view_dolly_to_vector_3d(vod->region, vod->init.ofs, vod->init.mousevec, zfac);
+ }
+
+ if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(vod->area, vod->region);
+ }
+
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
+
+ ED_region_tag_redraw(vod->region);
+}
+
+static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* execute the events */
+ if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_MOVE:
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ROTATE:
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ viewdolly_apply(vod, event->xy, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
+
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, vod);
+ op->customdata = NULL;
+ }
+
+ return ret;
+}
+
+static int viewdolly_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ScrArea *area;
+ ARegion *region;
+ float mousevec[3];
+
+ const int delta = RNA_int_get(op->ptr, "delta");
+
+ if (op->customdata) {
+ ViewOpsData *vod = op->customdata;
+
+ area = vod->area;
+ region = vod->region;
+ copy_v3_v3(mousevec, vod->init.mousevec);
+ }
+ else {
+ area = CTX_wm_area(C);
+ region = CTX_wm_region(C);
+ negate_v3_v3(mousevec, ((RegionView3D *)region->regiondata)->viewinv[2]);
+ normalize_v3(mousevec);
+ }
+
+ v3d = area->spacedata.first;
+ rv3d = region->regiondata;
+
+ const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
+
+ /* overwrite the mouse vector with the view direction (zoom into the center) */
+ if ((use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
+ normalize_v3_v3(mousevec, rv3d->viewinv[2]);
+ negate_v3(mousevec);
+ }
+
+ view_dolly_to_vector_3d(region, rv3d->ofs, mousevec, delta < 0 ? 1.8f : 0.2f);
+
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(area, region);
+ }
+
+ ED_view3d_camera_lock_sync(CTX_data_ensure_evaluated_depsgraph(C), v3d, rv3d);
+
+ ED_region_tag_redraw(region);
+
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+
+ return OPERATOR_FINISHED;
+}
+
+/* copied from viewzoom_invoke(), changes here may apply there */
+static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod;
+
+ if (viewdolly_offset_lock_check(C, op)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
+
+ vod = op->customdata = viewops_data_create(
+ C,
+ event,
+ (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
+ (use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
+
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
+
+ /* needs to run before 'viewops_data_create' so the backup 'rv3d->ofs' is correct */
+ /* switch from camera view when: */
+ if (vod->rv3d->persp != RV3D_PERSP) {
+ if (vod->rv3d->persp == RV3D_CAMOB) {
+ /* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
+ const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ED_view3d_persp_switch_from_camera(depsgraph, vod->v3d, vod->rv3d, RV3D_PERSP);
+ }
+ else {
+ vod->rv3d->persp = RV3D_PERSP;
+ }
+ ED_region_tag_redraw(vod->region);
+ }
+
+ /* if one or the other zoom position aren't set, set from event */
+ if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
+ RNA_int_set(op->ptr, "mx", event->xy[0]);
+ RNA_int_set(op->ptr, "my", event->xy[1]);
+ }
+
+ if (RNA_struct_property_is_set(op->ptr, "delta")) {
+ viewdolly_exec(C, op);
+ }
+ else {
+ /* overwrite the mouse vector with the view direction (zoom into the center) */
+ if ((use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
+ negate_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
+ normalize_v3(vod->init.mousevec);
+ }
+
+ if (event->type == MOUSEZOOM) {
+ /* Bypass Zoom invert flag for track pads (pass false always) */
+
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->xy[0];
+ }
+ else {
+ /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
+ vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->xy[0] -
+ event->prev_xy[0];
+ }
+ viewdolly_apply(vod, event->prev_xy, (U.uiflag & USER_ZOOM_INVERT) == 0);
+
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+ return OPERATOR_FINISHED;
+ }
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ return OPERATOR_FINISHED;
+}
+
+static void viewdolly_cancel(bContext *C, wmOperator *op)
+{
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+}
+
+void VIEW3D_OT_dolly(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Dolly View";
+ ot->description = "Dolly in/out in the view";
+ ot->idname = "VIEW3D_OT_dolly";
+
+ /* api callbacks */
+ ot->invoke = viewdolly_invoke;
+ ot->exec = viewdolly_exec;
+ ot->modal = viewdolly_modal;
+ ot->poll = view3d_rotation_poll;
+ ot->cancel = viewdolly_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY;
+
+ /* properties */
+ view3d_operator_properties_common(
+ ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_navigate_fly.c b/source/blender/editors/space_view3d/view3d_navigate_fly.c
index 2e9cb419e2e..05f6a10d89f 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_fly.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_fly.c
@@ -58,6 +58,7 @@
#include "DEG_depsgraph.h"
#include "view3d_intern.h" /* own include */
+#include "view3d_navigate.h"
/* -------------------------------------------------------------------- */
/** \name Modal Key-map
@@ -1102,9 +1103,9 @@ static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
else
#endif /* WITH_INPUT_NDOF */
- if (event->type == TIMER && event->customdata == fly->timer) {
- flyApply(C, fly, false);
- }
+ if (event->type == TIMER && event->customdata == fly->timer) {
+ flyApply(C, fly, false);
+ }
do_draw |= fly->redraw;
diff --git a/source/blender/editors/space_view3d/view3d_navigate_move.c b/source/blender/editors/space_view3d/view3d_navigate_move.c
new file mode 100644
index 00000000000..90acf20d24f
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_navigate_move.c
@@ -0,0 +1,188 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup spview3d
+ */
+
+#include "BKE_context.h"
+
+#include "WM_api.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_screen.h"
+
+#include "view3d_intern.h"
+#include "view3d_navigate.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name View Move (Pan) Operator
+ * \{ */
+
+/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
+
+void viewmove_modal_keymap(wmKeyConfig *keyconf)
+{
+ static const EnumPropertyItem modal_items[] = {
+ {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+
+ {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
+ {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
+
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Move Modal");
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if (keymap && keymap->modal_items) {
+ return;
+ }
+
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Move Modal", modal_items);
+
+ /* items for modal map */
+ WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, EVT_ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+
+ /* disabled mode switching for now, can re-implement better, later on */
+#if 0
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+ WM_modalkeymap_add_item(
+ keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+#endif
+
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_move");
+}
+
+static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* execute the events */
+ if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ZOOM:
+ WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ROTATE:
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ viewmove_apply(vod, event->xy[0], event->xy[1]);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
+
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+ }
+
+ return ret;
+}
+
+static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod;
+
+ const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
+
+ vod = op->customdata = viewops_data_create(
+ C,
+ event,
+ (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
+ (use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
+ vod = op->customdata;
+
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
+
+ if (event->type == MOUSEPAN) {
+ /* invert it, trackpad scroll follows same principle as 2d windows this way */
+ viewmove_apply(
+ vod, 2 * event->xy[0] - event->prev_xy[0], 2 * event->xy[1] - event->prev_xy[1]);
+
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+
+ return OPERATOR_FINISHED;
+ }
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void viewmove_cancel(bContext *C, wmOperator *op)
+{
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+}
+
+void VIEW3D_OT_move(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name = "Pan View";
+ ot->description = "Move the view";
+ ot->idname = "VIEW3D_OT_move";
+
+ /* api callbacks */
+ ot->invoke = viewmove_invoke;
+ ot->modal = viewmove_modal;
+ ot->poll = view3d_location_poll;
+ ot->cancel = viewmove_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY;
+
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_navigate_ndof.c b/source/blender/editors/space_view3d/view3d_navigate_ndof.c
new file mode 100644
index 00000000000..285d5c02db2
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_navigate_ndof.c
@@ -0,0 +1,661 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup spview3d
+ */
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+
+#include "ED_screen.h"
+
+#include "view3d_intern.h"
+#include "view3d_navigate.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name NDOF Utility Functions
+ * \{ */
+
+#ifdef WITH_INPUT_NDOF
+
+enum {
+ HAS_TRANSLATE = (1 << 0),
+ HAS_ROTATE = (1 << 0),
+};
+
+static bool ndof_has_translate(const wmNDOFMotionData *ndof,
+ const View3D *v3d,
+ const RegionView3D *rv3d)
+{
+ return !is_zero_v3(ndof->tvec) && (!ED_view3d_offset_lock_check(v3d, rv3d));
+}
+
+static bool ndof_has_rotate(const wmNDOFMotionData *ndof, const RegionView3D *rv3d)
+{
+ return !is_zero_v3(ndof->rvec) && ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0);
+}
+
+/**
+ * \param depth_pt: A point to calculate the depth (in perspective mode)
+ */
+static float view3d_ndof_pan_speed_calc_ex(RegionView3D *rv3d, const float depth_pt[3])
+{
+ float speed = rv3d->pixsize * NDOF_PIXELS_PER_SECOND;
+
+ if (rv3d->is_persp) {
+ speed *= ED_view3d_calc_zfac(rv3d, depth_pt, NULL);
+ }
+
+ return speed;
+}
+
+static float view3d_ndof_pan_speed_calc_from_dist(RegionView3D *rv3d, const float dist)
+{
+ float viewinv[4];
+ float tvec[3];
+
+ BLI_assert(dist >= 0.0f);
+
+ copy_v3_fl3(tvec, 0.0f, 0.0f, dist);
+ /* rv3d->viewinv isn't always valid */
+# if 0
+ mul_mat3_m4_v3(rv3d->viewinv, tvec);
+# else
+ invert_qt_qt_normalized(viewinv, rv3d->viewquat);
+ mul_qt_v3(viewinv, tvec);
+# endif
+
+ return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
+}
+
+static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d)
+{
+ float tvec[3];
+ negate_v3_v3(tvec, rv3d->ofs);
+
+ return view3d_ndof_pan_speed_calc_ex(rv3d, tvec);
+}
+
+/**
+ * Zoom and pan in the same function since sometimes zoom is interpreted as dolly (pan forward).
+ *
+ * \param has_zoom: zoom, otherwise dolly,
+ * often `!rv3d->is_persp` since it doesn't make sense to dolly in ortho.
+ */
+static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof,
+ ScrArea *area,
+ ARegion *region,
+ const bool has_translate,
+ const bool has_zoom)
+{
+ RegionView3D *rv3d = region->regiondata;
+ float view_inv[4];
+ float pan_vec[3];
+
+ if (has_translate == false && has_zoom == false) {
+ return;
+ }
+
+ WM_event_ndof_pan_get(ndof, pan_vec, false);
+
+ if (has_zoom) {
+ /* zoom with Z */
+
+ /* Zoom!
+ * velocity should be proportional to the linear velocity attained by rotational motion
+ * of same strength [got that?] proportional to `arclength = radius * angle`.
+ */
+
+ pan_vec[2] = 0.0f;
+
+ /* "zoom in" or "translate"? depends on zoom mode in user settings? */
+ if (ndof->tvec[2]) {
+ float zoom_distance = rv3d->dist * ndof->dt * ndof->tvec[2];
+
+ if (U.ndof_flag & NDOF_ZOOM_INVERT) {
+ zoom_distance = -zoom_distance;
+ }
+
+ rv3d->dist += zoom_distance;
+ }
+ }
+ else {
+ /* dolly with Z */
+
+ /* all callers must check */
+ if (has_translate) {
+ BLI_assert(ED_view3d_offset_lock_check((View3D *)area->spacedata.first, rv3d) == false);
+ }
+ }
+
+ if (has_translate) {
+ const float speed = view3d_ndof_pan_speed_calc(rv3d);
+
+ mul_v3_fl(pan_vec, speed * ndof->dt);
+
+ /* transform motion from view to world coordinates */
+ invert_qt_qt_normalized(view_inv, rv3d->viewquat);
+ mul_qt_v3(view_inv, pan_vec);
+
+ /* move center of view opposite of hand motion (this is camera mode, not object mode) */
+ sub_v3_v3(rv3d->ofs, pan_vec);
+
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(area, region);
+ }
+ }
+}
+
+static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof,
+ ScrArea *area,
+ ARegion *region,
+ ViewOpsData *vod,
+ const bool apply_dyn_ofs)
+{
+ View3D *v3d = area->spacedata.first;
+ RegionView3D *rv3d = region->regiondata;
+
+ float view_inv[4];
+
+ BLI_assert((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0);
+
+ ED_view3d_persp_ensure(vod->depsgraph, v3d, region);
+
+ rv3d->view = RV3D_VIEW_USER;
+
+ invert_qt_qt_normalized(view_inv, rv3d->viewquat);
+
+ if (U.ndof_flag & NDOF_TURNTABLE) {
+ float rot[3];
+
+ /* Turntable view code adapted for 3D mouse use. */
+ float angle, quat[4];
+ float xvec[3] = {1, 0, 0};
+
+ /* only use XY, ignore Z */
+ WM_event_ndof_rotate_get(ndof, rot);
+
+ /* Determine the direction of the x vector (for rotating up and down) */
+ mul_qt_v3(view_inv, xvec);
+
+ /* Perform the up/down rotation */
+ angle = ndof->dt * rot[0];
+ axis_angle_to_quat(quat, xvec, angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
+
+ /* Perform the orbital rotation */
+ angle = ndof->dt * rot[1];
+
+ /* Update the onscreen axis-angle indicator. */
+ rv3d->rot_angle = angle;
+ rv3d->rot_axis[0] = 0;
+ rv3d->rot_axis[1] = 0;
+ rv3d->rot_axis[2] = 1;
+
+ axis_angle_to_quat_single(quat, 'Z', angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
+ }
+ else {
+ float quat[4];
+ float axis[3];
+ float angle = WM_event_ndof_to_axis_angle(ndof, axis);
+
+ /* transform rotation axis from view to world coordinates */
+ mul_qt_v3(view_inv, axis);
+
+ /* Update the onscreen axis-angle indicator. */
+ rv3d->rot_angle = angle;
+ copy_v3_v3(rv3d->rot_axis, axis);
+
+ axis_angle_to_quat(quat, axis, angle);
+
+ /* apply rotation */
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
+ }
+
+ if (apply_dyn_ofs) {
+ viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
+ }
+}
+
+void view3d_ndof_fly(const wmNDOFMotionData *ndof,
+ View3D *v3d,
+ RegionView3D *rv3d,
+ const bool use_precision,
+ const short protectflag,
+ bool *r_has_translate,
+ bool *r_has_rotate)
+{
+ bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
+ bool has_rotate = ndof_has_rotate(ndof, rv3d);
+
+ float view_inv[4];
+ invert_qt_qt_normalized(view_inv, rv3d->viewquat);
+
+ rv3d->rot_angle = 0.0f; /* Disable onscreen rotation indicator. */
+
+ if (has_translate) {
+ /* ignore real 'dist' since fly has its own speed settings,
+ * also its overwritten at this point. */
+ float speed = view3d_ndof_pan_speed_calc_from_dist(rv3d, 1.0f);
+ float trans[3], trans_orig_y;
+
+ if (use_precision) {
+ speed *= 0.2f;
+ }
+
+ WM_event_ndof_pan_get(ndof, trans, false);
+ mul_v3_fl(trans, speed * ndof->dt);
+ trans_orig_y = trans[1];
+
+ if (U.ndof_flag & NDOF_FLY_HELICOPTER) {
+ trans[1] = 0.0f;
+ }
+
+ /* transform motion from view to world coordinates */
+ mul_qt_v3(view_inv, trans);
+
+ if (U.ndof_flag & NDOF_FLY_HELICOPTER) {
+ /* replace world z component with device y (yes it makes sense) */
+ trans[2] = trans_orig_y;
+ }
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ /* respect camera position locks */
+ if (protectflag & OB_LOCK_LOCX) {
+ trans[0] = 0.0f;
+ }
+ if (protectflag & OB_LOCK_LOCY) {
+ trans[1] = 0.0f;
+ }
+ if (protectflag & OB_LOCK_LOCZ) {
+ trans[2] = 0.0f;
+ }
+ }
+
+ if (!is_zero_v3(trans)) {
+ /* move center of view opposite of hand motion
+ * (this is camera mode, not object mode) */
+ sub_v3_v3(rv3d->ofs, trans);
+ has_translate = true;
+ }
+ else {
+ has_translate = false;
+ }
+ }
+
+ if (has_rotate) {
+ const float turn_sensitivity = 1.0f;
+
+ float rotation[4];
+ float axis[3];
+ float angle = turn_sensitivity * WM_event_ndof_to_axis_angle(ndof, axis);
+
+ if (fabsf(angle) > 0.0001f) {
+ has_rotate = true;
+
+ if (use_precision) {
+ angle *= 0.2f;
+ }
+
+ /* transform rotation axis from view to world coordinates */
+ mul_qt_v3(view_inv, axis);
+
+ /* apply rotation to view */
+ axis_angle_to_quat(rotation, axis, angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
+
+ if (U.ndof_flag & NDOF_LOCK_HORIZON) {
+ /* force an upright viewpoint
+ * TODO: make this less... sudden */
+ float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */
+ float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */
+
+ /* find new inverse since viewquat has changed */
+ invert_qt_qt_normalized(view_inv, rv3d->viewquat);
+ /* could apply reverse rotation to existing view_inv to save a few cycles */
+
+ /* transform view vectors to world coordinates */
+ mul_qt_v3(view_inv, view_horizon);
+ mul_qt_v3(view_inv, view_direction);
+
+ /* find difference between view & world horizons
+ * true horizon lives in world xy plane, so look only at difference in z */
+ angle = -asinf(view_horizon[2]);
+
+ /* rotate view so view horizon = world horizon */
+ axis_angle_to_quat(rotation, view_direction, angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
+ }
+
+ rv3d->view = RV3D_VIEW_USER;
+ }
+ else {
+ has_rotate = false;
+ }
+ }
+
+ *r_has_translate = has_translate;
+ *r_has_rotate = has_rotate;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name NDOF Orbit/Translate Operator
+ * \{ */
+
+static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (event->type != NDOF_MOTION) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ViewOpsData *vod;
+ View3D *v3d;
+ RegionView3D *rv3d;
+ char xform_flag = 0;
+
+ const wmNDOFMotionData *ndof = event->customdata;
+
+ vod = op->customdata = viewops_data_create(
+ C, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_DEPTH_NAVIGATE));
+
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
+
+ v3d = vod->v3d;
+ rv3d = vod->rv3d;
+
+ /* off by default, until changed later this function */
+ rv3d->rot_angle = 0.0f;
+
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
+
+ if (ndof->progress != P_FINISHING) {
+ const bool has_rotation = ndof_has_rotate(ndof, rv3d);
+ /* if we can't rotate, fallback to translate (locked axis views) */
+ const bool has_translate = ndof_has_translate(ndof, v3d, rv3d) &&
+ (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION);
+ const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
+
+ if (has_translate || has_zoom) {
+ view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, has_zoom);
+ xform_flag |= HAS_TRANSLATE;
+ }
+
+ if (has_rotation) {
+ view3d_ndof_orbit(ndof, vod->area, vod->region, vod, true);
+ xform_flag |= HAS_ROTATE;
+ }
+ }
+
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ if (xform_flag) {
+ ED_view3d_camera_lock_autokey(
+ v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
+ }
+
+ ED_region_tag_redraw(vod->region);
+
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "NDOF Orbit View";
+ ot->description = "Orbit the view using the 3D mouse";
+ ot->idname = "VIEW3D_OT_ndof_orbit";
+
+ /* api callbacks */
+ ot->invoke = ndof_orbit_invoke;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name NDOF Orbit/Zoom Operator
+ * \{ */
+
+static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (event->type != NDOF_MOTION) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ViewOpsData *vod;
+ View3D *v3d;
+ RegionView3D *rv3d;
+ char xform_flag = 0;
+
+ const wmNDOFMotionData *ndof = event->customdata;
+
+ vod = op->customdata = viewops_data_create(
+ C, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_DEPTH_NAVIGATE));
+
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
+
+ v3d = vod->v3d;
+ rv3d = vod->rv3d;
+
+ /* off by default, until changed later this function */
+ rv3d->rot_angle = 0.0f;
+
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
+
+ if (ndof->progress == P_FINISHING) {
+ /* pass */
+ }
+ else if ((rv3d->persp == RV3D_ORTHO) && RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ /* if we can't rotate, fallback to translate (locked axis views) */
+ const bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
+ const bool has_zoom = (ndof->tvec[2] != 0.0f) && ED_view3d_offset_lock_check(v3d, rv3d);
+
+ if (has_translate || has_zoom) {
+ view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, true);
+ xform_flag |= HAS_TRANSLATE;
+ }
+ }
+ else {
+ /* NOTE: based on feedback from T67579, users want to have pan and orbit enabled at once.
+ * It's arguable that orbit shouldn't pan (since we have a pan only operator),
+ * so if there are users who like to separate orbit/pan operations - it can be a preference. */
+ const bool is_orbit_around_pivot = (U.ndof_flag & NDOF_MODE_ORBIT) ||
+ ED_view3d_offset_lock_check(v3d, rv3d);
+ const bool has_rotation = ndof_has_rotate(ndof, rv3d);
+ bool has_translate, has_zoom;
+
+ if (is_orbit_around_pivot) {
+ /* Orbit preference or forced lock (Z zooms). */
+ has_translate = !is_zero_v2(ndof->tvec) && ndof_has_translate(ndof, v3d, rv3d);
+ has_zoom = (ndof->tvec[2] != 0.0f);
+ }
+ else {
+ /* Free preference (Z translates). */
+ has_translate = ndof_has_translate(ndof, v3d, rv3d);
+ has_zoom = false;
+ }
+
+ /* Rotation first because dynamic offset resets offset otherwise (and disables panning). */
+ if (has_rotation) {
+ const float dist_backup = rv3d->dist;
+ if (!is_orbit_around_pivot) {
+ ED_view3d_distance_set(rv3d, 0.0f);
+ }
+ view3d_ndof_orbit(ndof, vod->area, vod->region, vod, is_orbit_around_pivot);
+ xform_flag |= HAS_ROTATE;
+ if (!is_orbit_around_pivot) {
+ ED_view3d_distance_set(rv3d, dist_backup);
+ }
+ }
+
+ if (has_translate || has_zoom) {
+ view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, has_zoom);
+ xform_flag |= HAS_TRANSLATE;
+ }
+ }
+
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ if (xform_flag) {
+ ED_view3d_camera_lock_autokey(
+ v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
+ }
+
+ ED_region_tag_redraw(vod->region);
+
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "NDOF Orbit View with Zoom";
+ ot->description = "Orbit and zoom the view using the 3D mouse";
+ ot->idname = "VIEW3D_OT_ndof_orbit_zoom";
+
+ /* api callbacks */
+ ot->invoke = ndof_orbit_zoom_invoke;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name NDOF Pan/Zoom Operator
+ * \{ */
+
+static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ if (event->type != NDOF_MOTION) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ const wmNDOFMotionData *ndof = event->customdata;
+ char xform_flag = 0;
+
+ const bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
+ const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
+
+ /* we're panning here! so erase any leftover rotation from other operators */
+ rv3d->rot_angle = 0.0f;
+
+ if (!(has_translate || has_zoom)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
+
+ if (ndof->progress != P_FINISHING) {
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+
+ if (has_translate || has_zoom) {
+ view3d_ndof_pan_zoom(ndof, area, region, has_translate, has_zoom);
+ xform_flag |= HAS_TRANSLATE;
+ }
+ }
+
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ if (xform_flag) {
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, xform_flag & HAS_TRANSLATE);
+ }
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "NDOF Pan View";
+ ot->description = "Pan the view with the 3D mouse";
+ ot->idname = "VIEW3D_OT_ndof_pan";
+
+ /* api callbacks */
+ ot->invoke = ndof_pan_invoke;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name NDOF Transform All Operator
+ * \{ */
+
+/**
+ * wraps #ndof_orbit_zoom but never restrict to orbit.
+ */
+static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ /* weak!, but it works */
+ const int ndof_flag = U.ndof_flag;
+ int ret;
+
+ U.ndof_flag &= ~NDOF_MODE_ORBIT;
+
+ ret = ndof_orbit_zoom_invoke(C, op, event);
+
+ U.ndof_flag = ndof_flag;
+
+ return ret;
+}
+
+void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "NDOF Transform View";
+ ot->description = "Pan and rotate the view with the 3D mouse";
+ ot->idname = "VIEW3D_OT_ndof_all";
+
+ /* api callbacks */
+ ot->invoke = ndof_all_invoke;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = 0;
+}
+
+#endif /* WITH_INPUT_NDOF */
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_navigate_roll.c b/source/blender/editors/space_view3d/view3d_navigate_roll.c
new file mode 100644
index 00000000000..c9bfdc4412a
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_navigate_roll.c
@@ -0,0 +1,292 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup spview3d
+ */
+
+#include "BLI_blenlib.h"
+#include "BLI_dial_2d.h"
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+
+#include "WM_api.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_screen.h"
+
+#include "view3d_intern.h"
+#include "view3d_navigate.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name View Roll Operator
+ * \{ */
+
+static void view_roll_angle(
+ ARegion *region, float quat[4], const float orig_quat[4], const float dvec[3], float angle)
+{
+ RegionView3D *rv3d = region->regiondata;
+ float quat_mul[4];
+
+ /* camera axis */
+ axis_angle_normalized_to_quat(quat_mul, dvec, angle);
+
+ mul_qt_qtqt(quat, orig_quat, quat_mul);
+
+ /* avoid precision loss over time */
+ normalize_qt(quat);
+
+ rv3d->view = RV3D_VIEW_USER;
+}
+
+static void viewroll_apply(ViewOpsData *vod, int x, int y)
+{
+ float angle = BLI_dial_angle(vod->init.dial, (const float[2]){x, y});
+
+ if (angle != 0.0f) {
+ view_roll_angle(vod->region, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle);
+ }
+
+ if (vod->use_dyn_ofs) {
+ view3d_orbit_apply_dyn_ofs(
+ vod->rv3d->ofs, vod->init.ofs, vod->init.quat, vod->rv3d->viewquat, vod->dyn_ofs);
+ }
+
+ if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(vod->area, vod->region);
+ }
+
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
+
+ ED_region_tag_redraw(vod->region);
+}
+
+static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* execute the events */
+ if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_MOVE:
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ROTATE:
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
+ /* Note this does not remove auto-keys on locked cameras. */
+ copy_qt_qt(vod->rv3d->viewquat, vod->init.quat);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+ return OPERATOR_CANCELLED;
+ }
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ viewroll_apply(vod, event->xy[0], event->xy[1]);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
+
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+ }
+
+ return ret;
+}
+
+enum {
+ V3D_VIEW_STEPLEFT = 1,
+ V3D_VIEW_STEPRIGHT,
+};
+
+static const EnumPropertyItem prop_view_roll_items[] = {
+ {0, "ANGLE", 0, "Roll Angle", "Roll the view using an angle value"},
+ {V3D_VIEW_STEPLEFT, "LEFT", 0, "Roll Left", "Roll the view around to the left"},
+ {V3D_VIEW_STEPRIGHT, "RIGHT", 0, "Roll Right", "Roll the view around to the right"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int viewroll_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ARegion *region;
+
+ if (op->customdata) {
+ ViewOpsData *vod = op->customdata;
+ region = vod->region;
+ v3d = vod->v3d;
+ }
+ else {
+ ED_view3d_context_user_region(C, &v3d, &region);
+ }
+
+ rv3d = region->regiondata;
+ if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
+
+ ED_view3d_smooth_view_force_finish(C, v3d, region);
+
+ int type = RNA_enum_get(op->ptr, "type");
+ float angle = (type == 0) ? RNA_float_get(op->ptr, "angle") : DEG2RADF(U.pad_rot_angle);
+ float mousevec[3];
+ float quat_new[4];
+
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ if (type == V3D_VIEW_STEPLEFT) {
+ angle = -angle;
+ }
+
+ normalize_v3_v3(mousevec, rv3d->viewinv[2]);
+ negate_v3(mousevec);
+ view_roll_angle(region, quat_new, rv3d->viewquat, mousevec, angle);
+
+ const float *dyn_ofs_pt = NULL;
+ float dyn_ofs[3];
+ if (U.uiflag & USER_ORBIT_SELECTION) {
+ if (view3d_orbit_calc_center(C, dyn_ofs)) {
+ negate_v3(dyn_ofs);
+ dyn_ofs_pt = dyn_ofs;
+ }
+ }
+
+ ED_view3d_smooth_view(C,
+ v3d,
+ region,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .quat = quat_new,
+ .dyn_ofs = dyn_ofs_pt,
+ });
+
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+ return OPERATOR_FINISHED;
+ }
+
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+ return OPERATOR_CANCELLED;
+}
+
+static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod;
+
+ bool use_angle = RNA_enum_get(op->ptr, "type") != 0;
+
+ if (use_angle || RNA_struct_property_is_set(op->ptr, "angle")) {
+ viewroll_exec(C, op);
+ }
+ else {
+ /* makes op->customdata */
+ vod = op->customdata = viewops_data_create(C, event, viewops_flag_from_prefs());
+ vod->init.dial = BLI_dial_init((const float[2]){BLI_rcti_cent_x(&vod->region->winrct),
+ BLI_rcti_cent_y(&vod->region->winrct)},
+ FLT_EPSILON);
+
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
+
+ /* overwrite the mouse vector with the view direction */
+ normalize_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
+ negate_v3(vod->init.mousevec);
+
+ if (event->type == MOUSEROTATE) {
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->xy[0];
+ viewroll_apply(vod, event->prev_xy[0], event->prev_xy[1]);
+
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+ return OPERATOR_FINISHED;
+ }
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ return OPERATOR_FINISHED;
+}
+
+static void viewroll_cancel(bContext *C, wmOperator *op)
+{
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+}
+
+void VIEW3D_OT_view_roll(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "View Roll";
+ ot->description = "Roll the view";
+ ot->idname = "VIEW3D_OT_view_roll";
+
+ /* api callbacks */
+ ot->invoke = viewroll_invoke;
+ ot->exec = viewroll_exec;
+ ot->modal = viewroll_modal;
+ ot->poll = ED_operator_rv3d_user_region_poll;
+ ot->cancel = viewroll_cancel;
+
+ /* flags */
+ ot->flag = 0;
+
+ /* properties */
+ ot->prop = prop = RNA_def_float(
+ ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_enum(ot->srna,
+ "type",
+ prop_view_roll_items,
+ 0,
+ "Roll Angle Source",
+ "How roll angle is calculated");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_navigate_rotate.c b/source/blender/editors/space_view3d/view3d_navigate_rotate.c
new file mode 100644
index 00000000000..c3730b3b3b1
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_navigate_rotate.c
@@ -0,0 +1,452 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup spview3d
+ */
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+
+#include "WM_api.h"
+
+#include "RNA_access.h"
+
+#include "ED_screen.h"
+
+#include "view3d_intern.h"
+#include "view3d_navigate.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name View Rotate Operator
+ * \{ */
+
+void viewrotate_modal_keymap(wmKeyConfig *keyconf)
+{
+ static const EnumPropertyItem modal_items[] = {
+ {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+
+ {VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Axis Snap", ""},
+ {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Axis Snap (Off)", ""},
+
+ {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
+ {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
+
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Rotate Modal");
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if (keymap && keymap->modal_items) {
+ return;
+ }
+
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Rotate Modal", modal_items);
+
+ /* disabled mode switching for now, can re-implement better, later on */
+#if 0
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+#endif
+
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate");
+}
+
+static void viewrotate_apply_snap(ViewOpsData *vod)
+{
+ const float axis_limit = DEG2RADF(45 / 3);
+
+ RegionView3D *rv3d = vod->rv3d;
+
+ float viewquat_inv[4];
+ float zaxis[3] = {0, 0, 1};
+ float zaxis_best[3];
+ int x, y, z;
+ bool found = false;
+
+ invert_qt_qt_normalized(viewquat_inv, vod->curr.viewquat);
+
+ mul_qt_v3(viewquat_inv, zaxis);
+ normalize_v3(zaxis);
+
+ for (x = -1; x < 2; x++) {
+ for (y = -1; y < 2; y++) {
+ for (z = -1; z < 2; z++) {
+ if (x || y || z) {
+ float zaxis_test[3] = {x, y, z};
+
+ normalize_v3(zaxis_test);
+
+ if (angle_normalized_v3v3(zaxis_test, zaxis) < axis_limit) {
+ copy_v3_v3(zaxis_best, zaxis_test);
+ found = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (found) {
+
+ /* find the best roll */
+ float quat_roll[4], quat_final[4], quat_best[4], quat_snap[4];
+ float viewquat_align[4]; /* viewquat aligned to zaxis_best */
+ float viewquat_align_inv[4]; /* viewquat aligned to zaxis_best */
+ float best_angle = axis_limit;
+ int j;
+
+ /* viewquat_align is the original viewquat aligned to the snapped axis
+ * for testing roll */
+ rotation_between_vecs_to_quat(viewquat_align, zaxis_best, zaxis);
+ normalize_qt(viewquat_align);
+ mul_qt_qtqt(viewquat_align, vod->curr.viewquat, viewquat_align);
+ normalize_qt(viewquat_align);
+ invert_qt_qt_normalized(viewquat_align_inv, viewquat_align);
+
+ vec_to_quat(quat_snap, zaxis_best, OB_NEGZ, OB_POSY);
+ normalize_qt(quat_snap);
+ invert_qt_normalized(quat_snap);
+
+ /* check if we can find the roll */
+ found = false;
+
+ /* find best roll */
+ for (j = 0; j < 8; j++) {
+ float angle;
+ float xaxis1[3] = {1, 0, 0};
+ float xaxis2[3] = {1, 0, 0};
+ float quat_final_inv[4];
+
+ axis_angle_to_quat(quat_roll, zaxis_best, (float)j * DEG2RADF(45.0f));
+ normalize_qt(quat_roll);
+
+ mul_qt_qtqt(quat_final, quat_snap, quat_roll);
+ normalize_qt(quat_final);
+
+ /* compare 2 vector angles to find the least roll */
+ invert_qt_qt_normalized(quat_final_inv, quat_final);
+ mul_qt_v3(viewquat_align_inv, xaxis1);
+ mul_qt_v3(quat_final_inv, xaxis2);
+ angle = angle_v3v3(xaxis1, xaxis2);
+
+ if (angle <= best_angle) {
+ found = true;
+ best_angle = angle;
+ copy_qt_qt(quat_best, quat_final);
+ }
+ }
+
+ if (found) {
+ /* lock 'quat_best' to an axis view if we can */
+ ED_view3d_quat_to_axis_view(quat_best, 0.01f, &rv3d->view, &rv3d->view_axis_roll);
+ if (rv3d->view != RV3D_VIEW_USER) {
+ ED_view3d_quat_from_axis_view(rv3d->view, rv3d->view_axis_roll, quat_best);
+ }
+ }
+ else {
+ copy_qt_qt(quat_best, viewquat_align);
+ }
+
+ copy_qt_qt(rv3d->viewquat, quat_best);
+
+ viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
+
+ if (U.uiflag & USER_AUTOPERSP) {
+ if (RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ if (rv3d->persp == RV3D_PERSP) {
+ rv3d->persp = RV3D_ORTHO;
+ }
+ }
+ }
+ }
+ else if (U.uiflag & USER_AUTOPERSP) {
+ rv3d->persp = vod->init.persp;
+ }
+}
+
+static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
+{
+ RegionView3D *rv3d = vod->rv3d;
+
+ rv3d->view = RV3D_VIEW_USER; /* need to reset every time because of view snapping */
+
+ if (U.flag & USER_TRACKBALL) {
+ float axis[3], q1[4], dvec[3], newvec[3];
+ float angle;
+
+ {
+ const int event_xy_offset[2] = {
+ event_xy[0] + vod->init.event_xy_offset[0],
+ event_xy[1] + vod->init.event_xy_offset[1],
+ };
+ calctrackballvec(&vod->region->winrct, event_xy_offset, newvec);
+ }
+
+ sub_v3_v3v3(dvec, newvec, vod->init.trackvec);
+
+ angle = (len_v3(dvec) / (2.0f * V3D_OP_TRACKBALLSIZE)) * (float)M_PI;
+
+ /* Before applying the sensitivity this is rotating 1:1,
+ * where the cursor would match the surface of a sphere in the view. */
+ angle *= U.view_rotate_sensitivity_trackball;
+
+ /* Allow for rotation beyond the interval [-pi, pi] */
+ angle = angle_wrap_rad(angle);
+
+ /* This relation is used instead of the actual angle between vectors
+ * so that the angle of rotation is linearly proportional to
+ * the distance that the mouse is dragged. */
+
+ cross_v3_v3v3(axis, vod->init.trackvec, newvec);
+ axis_angle_to_quat(q1, axis, angle);
+
+ mul_qt_qtqt(vod->curr.viewquat, q1, vod->init.quat);
+
+ viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
+ }
+ else {
+ float quat_local_x[4], quat_global_z[4];
+ float m[3][3];
+ float m_inv[3][3];
+ const float zvec_global[3] = {0.0f, 0.0f, 1.0f};
+ float xaxis[3];
+
+ /* Radians per-pixel. */
+ const float sensitivity = U.view_rotate_sensitivity_turntable / U.dpi_fac;
+
+ /* Get the 3x3 matrix and its inverse from the quaternion */
+ quat_to_mat3(m, vod->curr.viewquat);
+ invert_m3_m3(m_inv, m);
+
+ /* Avoid Gimbal Lock
+ *
+ * Even though turn-table mode is in use, this can occur when the user exits the camera view
+ * or when aligning the view to a rotated object.
+ *
+ * We have gimbal lock when the user's view is rotated +/- 90 degrees along the view axis.
+ * In this case the vertical rotation is the same as the sideways turntable motion.
+ * Making it impossible to get out of the gimbal locked state without resetting the view.
+ *
+ * The logic below lets the user exit out of this state without any abrupt 'fix'
+ * which would be disorienting.
+ *
+ * This works by blending two horizons:
+ * - Rotated-horizon: `cross_v3_v3v3(xaxis, zvec_global, m_inv[2])`
+ * When only this is used, this turntable rotation works - but it's side-ways
+ * (as if the entire turn-table has been placed on its side)
+ * While there is no gimbal lock, it's also awkward to use.
+ * - Un-rotated-horizon: `m_inv[0]`
+ * When only this is used, the turntable rotation can have gimbal lock.
+ *
+ * The solution used here is to blend between these two values,
+ * so the severity of the gimbal lock is used to blend the rotated horizon.
+ * Blending isn't essential, it just makes the transition smoother.
+ *
+ * This allows sideways turn-table rotation on a Z axis that isn't world-space Z,
+ * While up-down turntable rotation eventually corrects gimbal lock. */
+#if 1
+ if (len_squared_v3v3(zvec_global, m_inv[2]) > 0.001f) {
+ float fac;
+ cross_v3_v3v3(xaxis, zvec_global, m_inv[2]);
+ if (dot_v3v3(xaxis, m_inv[0]) < 0) {
+ negate_v3(xaxis);
+ }
+ fac = angle_normalized_v3v3(zvec_global, m_inv[2]) / (float)M_PI;
+ fac = fabsf(fac - 0.5f) * 2;
+ fac = fac * fac;
+ interp_v3_v3v3(xaxis, xaxis, m_inv[0], fac);
+ }
+ else {
+ copy_v3_v3(xaxis, m_inv[0]);
+ }
+#else
+ copy_v3_v3(xaxis, m_inv[0]);
+#endif
+
+ /* Determine the direction of the x vector (for rotating up and down) */
+ /* This can likely be computed directly from the quaternion. */
+
+ /* Perform the up/down rotation */
+ axis_angle_to_quat(quat_local_x, xaxis, sensitivity * -(event_xy[1] - vod->prev.event_xy[1]));
+ mul_qt_qtqt(quat_local_x, vod->curr.viewquat, quat_local_x);
+
+ /* Perform the orbital rotation */
+ axis_angle_to_quat_single(
+ quat_global_z, 'Z', sensitivity * vod->reverse * (event_xy[0] - vod->prev.event_xy[0]));
+ mul_qt_qtqt(vod->curr.viewquat, quat_local_x, quat_global_z);
+
+ viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
+ }
+
+ /* avoid precision loss over time */
+ normalize_qt(vod->curr.viewquat);
+
+ /* use a working copy so view rotation locking doesn't overwrite the locked
+ * rotation back into the view we calculate with */
+ copy_qt_qt(rv3d->viewquat, vod->curr.viewquat);
+
+ /* Check for view snap,
+ * NOTE: don't apply snap to `vod->viewquat` so the view won't jam up. */
+ if (vod->axis_snap) {
+ viewrotate_apply_snap(vod);
+ }
+ vod->prev.event_xy[0] = event_xy[0];
+ vod->prev.event_xy[1] = event_xy[1];
+
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d);
+
+ ED_region_tag_redraw(vod->region);
+}
+
+static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* execute the events */
+ if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_AXIS_SNAP_ENABLE:
+ vod->axis_snap = true;
+ event_code = VIEW_APPLY;
+ break;
+ case VIEWROT_MODAL_AXIS_SNAP_DISABLE:
+ vod->rv3d->persp = vod->init.persp;
+ vod->axis_snap = false;
+ event_code = VIEW_APPLY;
+ break;
+ case VIEWROT_MODAL_SWITCH_ZOOM:
+ WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_MOVE:
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ viewrotate_apply(vod, event->xy);
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
+
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+ }
+
+ return ret;
+}
+
+static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod;
+
+ const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
+
+ /* makes op->customdata */
+ vod = op->customdata = viewops_data_create(
+ C,
+ event,
+ viewops_flag_from_prefs() | VIEWOPS_FLAG_PERSP_ENSURE |
+ (use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
+
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
+
+ if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
+ /* Rotate direction we keep always same */
+ int event_xy[2];
+
+ if (event->type == MOUSEPAN) {
+ if (event->is_direction_inverted) {
+ event_xy[0] = 2 * event->xy[0] - event->prev_xy[0];
+ event_xy[1] = 2 * event->xy[1] - event->prev_xy[1];
+ }
+ else {
+ copy_v2_v2_int(event_xy, event->prev_xy);
+ }
+ }
+ else {
+ /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
+ copy_v2_v2_int(event_xy, event->prev_xy);
+ }
+
+ viewrotate_apply(vod, event_xy);
+
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+
+ return OPERATOR_FINISHED;
+ }
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void viewrotate_cancel(bContext *C, wmOperator *op)
+{
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+}
+
+void VIEW3D_OT_rotate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Rotate View";
+ ot->description = "Rotate the view";
+ ot->idname = "VIEW3D_OT_rotate";
+
+ /* api callbacks */
+ ot->invoke = viewrotate_invoke;
+ ot->modal = viewrotate_modal;
+ ot->poll = view3d_rotation_poll;
+ ot->cancel = viewrotate_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY;
+
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_navigate_smoothview.c b/source/blender/editors/space_view3d/view3d_navigate_smoothview.c
new file mode 100644
index 00000000000..aeffb520b0a
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_navigate_smoothview.c
@@ -0,0 +1,406 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup spview3d
+ */
+
+#include "DNA_camera_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "WM_api.h"
+
+#include "ED_screen.h"
+
+#include "view3d_intern.h"
+#include "view3d_navigate.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name Smooth View Operator & Utilities
+ *
+ * Use for view transitions to have smooth (animated) transitions.
+ * \{ */
+
+/* This operator is one of the 'timer refresh' ones like animation playback */
+
+struct SmoothView3DState {
+ float dist;
+ float lens;
+ float quat[4];
+ float ofs[3];
+};
+
+struct SmoothView3DStore {
+ /* Source. */
+ struct SmoothView3DState src; /* source */
+ struct SmoothView3DState dst; /* destination */
+ struct SmoothView3DState org; /* original */
+
+ bool to_camera;
+
+ bool use_dyn_ofs;
+ float dyn_ofs[3];
+
+ /* When smooth-view is enabled, store the 'rv3d->view' here,
+ * assign back when the view motion is completed. */
+ char org_view;
+
+ double time_allowed;
+};
+
+static void view3d_smooth_view_state_backup(struct SmoothView3DState *sms_state,
+ const View3D *v3d,
+ const RegionView3D *rv3d)
+{
+ copy_v3_v3(sms_state->ofs, rv3d->ofs);
+ copy_qt_qt(sms_state->quat, rv3d->viewquat);
+ sms_state->dist = rv3d->dist;
+ sms_state->lens = v3d->lens;
+}
+
+static void view3d_smooth_view_state_restore(const struct SmoothView3DState *sms_state,
+ View3D *v3d,
+ RegionView3D *rv3d)
+{
+ copy_v3_v3(rv3d->ofs, sms_state->ofs);
+ copy_qt_qt(rv3d->viewquat, sms_state->quat);
+ rv3d->dist = sms_state->dist;
+ v3d->lens = sms_state->lens;
+}
+
+/* will start timer if appropriate */
+void ED_view3d_smooth_view_ex(
+ /* avoid passing in the context */
+ const Depsgraph *depsgraph,
+ wmWindowManager *wm,
+ wmWindow *win,
+ ScrArea *area,
+ View3D *v3d,
+ ARegion *region,
+ const int smooth_viewtx,
+ const V3D_SmoothParams *sview)
+{
+ RegionView3D *rv3d = region->regiondata;
+ struct SmoothView3DStore sms = {{0}};
+
+ /* initialize sms */
+ view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d);
+ view3d_smooth_view_state_backup(&sms.src, v3d, rv3d);
+ /* If smooth-view runs multiple times. */
+ if (rv3d->sms == NULL) {
+ view3d_smooth_view_state_backup(&sms.org, v3d, rv3d);
+ }
+ else {
+ sms.org = rv3d->sms->org;
+ }
+ sms.org_view = rv3d->view;
+
+ /* sms.to_camera = false; */ /* initialized to zero anyway */
+
+ /* note on camera locking, this is a little confusing but works ok.
+ * we may be changing the view 'as if' there is no active camera, but in fact
+ * there is an active camera which is locked to the view.
+ *
+ * In the case where smooth view is moving _to_ a camera we don't want that
+ * camera to be moved or changed, so only when the camera is not being set should
+ * we allow camera option locking to initialize the view settings from the camera.
+ */
+ if (sview->camera == NULL && sview->camera_old == NULL) {
+ ED_view3d_camera_lock_init(depsgraph, v3d, rv3d);
+ }
+
+ /* store the options we want to end with */
+ if (sview->ofs) {
+ copy_v3_v3(sms.dst.ofs, sview->ofs);
+ }
+ if (sview->quat) {
+ copy_qt_qt(sms.dst.quat, sview->quat);
+ }
+ if (sview->dist) {
+ sms.dst.dist = *sview->dist;
+ }
+ if (sview->lens) {
+ sms.dst.lens = *sview->lens;
+ }
+
+ if (sview->dyn_ofs) {
+ BLI_assert(sview->ofs == NULL);
+ BLI_assert(sview->quat != NULL);
+
+ copy_v3_v3(sms.dyn_ofs, sview->dyn_ofs);
+ sms.use_dyn_ofs = true;
+
+ /* calculate the final destination offset */
+ view3d_orbit_apply_dyn_ofs(sms.dst.ofs, sms.src.ofs, sms.src.quat, sms.dst.quat, sms.dyn_ofs);
+ }
+
+ if (sview->camera) {
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
+ if (sview->ofs != NULL) {
+ sms.dst.dist = ED_view3d_offset_distance(
+ ob_camera_eval->obmat, sview->ofs, VIEW3D_DIST_FALLBACK);
+ }
+ ED_view3d_from_object(ob_camera_eval, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
+ sms.to_camera = true; /* restore view3d values in end */
+ }
+
+ if ((sview->camera_old == sview->camera) && /* Camera. */
+ (sms.dst.dist == rv3d->dist) && /* Distance. */
+ (sms.dst.lens == v3d->lens) && /* Lens. */
+ equals_v3v3(sms.dst.ofs, rv3d->ofs) && /* Offset. */
+ equals_v4v4(sms.dst.quat, rv3d->viewquat) /* Rotation. */
+ ) {
+ /* Early return if nothing changed. */
+ return;
+ }
+
+ /* Skip smooth viewing for external render engine draw. */
+ if (smooth_viewtx && !(v3d->shading.type == OB_RENDER && rv3d->render_engine)) {
+
+ /* original values */
+ if (sview->camera_old) {
+ Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old);
+ if (sview->ofs != NULL) {
+ sms.src.dist = ED_view3d_offset_distance(ob_camera_old_eval->obmat, sview->ofs, 0.0f);
+ }
+ ED_view3d_from_object(
+ ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
+ }
+ /* grid draw as floor */
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
+ /* use existing if exists, means multiple calls to smooth view
+ * won't lose the original 'view' setting */
+ rv3d->view = RV3D_VIEW_USER;
+ }
+
+ sms.time_allowed = (double)smooth_viewtx / 1000.0;
+
+ /* If this is view rotation only we can decrease the time allowed by the angle between quats
+ * this means small rotations won't lag. */
+ if (sview->quat && !sview->ofs && !sview->dist) {
+ /* scale the time allowed by the rotation */
+ /* 180deg == 1.0 */
+ sms.time_allowed *= (double)fabsf(angle_signed_normalized_qtqt(sms.dst.quat, sms.src.quat)) /
+ M_PI;
+ }
+
+ /* ensure it shows correct */
+ if (sms.to_camera) {
+ /* use ortho if we move from an ortho view to an ortho camera */
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
+ rv3d->persp = (((rv3d->is_persp == false) && (ob_camera_eval->type == OB_CAMERA) &&
+ (((Camera *)ob_camera_eval->data)->type == CAM_ORTHO)) ?
+ RV3D_ORTHO :
+ RV3D_PERSP);
+ }
+
+ rv3d->rflag |= RV3D_NAVIGATING;
+
+ /* not essential but in some cases the caller will tag the area for redraw, and in that
+ * case we can get a flicker of the 'org' user view but we want to see 'src' */
+ view3d_smooth_view_state_restore(&sms.src, v3d, rv3d);
+
+ /* keep track of running timer! */
+ if (rv3d->sms == NULL) {
+ rv3d->sms = MEM_mallocN(sizeof(struct SmoothView3DStore), "smoothview v3d");
+ }
+ *rv3d->sms = sms;
+ if (rv3d->smooth_timer) {
+ WM_event_remove_timer(wm, win, rv3d->smooth_timer);
+ }
+ /* #TIMER1 is hard-coded in key-map. */
+ rv3d->smooth_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 100.0);
+ }
+ else {
+ /* Animation is disabled, apply immediately. */
+ if (sms.to_camera == false) {
+ copy_v3_v3(rv3d->ofs, sms.dst.ofs);
+ copy_qt_qt(rv3d->viewquat, sms.dst.quat);
+ rv3d->dist = sms.dst.dist;
+ v3d->lens = sms.dst.lens;
+
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ }
+
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_copy(area, region);
+ }
+
+ ED_region_tag_redraw(region);
+
+ WM_event_add_mousemove(win);
+ }
+}
+
+void ED_view3d_smooth_view(bContext *C,
+ View3D *v3d,
+ ARegion *region,
+ const int smooth_viewtx,
+ const struct V3D_SmoothParams *sview)
+{
+ const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *area = CTX_wm_area(C);
+
+ ED_view3d_smooth_view_ex(depsgraph, wm, win, area, v3d, region, smooth_viewtx, sview);
+}
+
+/* only meant for timer usage */
+static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *region, bool sync_boxview)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ RegionView3D *rv3d = region->regiondata;
+ struct SmoothView3DStore *sms = rv3d->sms;
+ float step, step_inv;
+
+ if (sms->time_allowed != 0.0) {
+ step = (float)((rv3d->smooth_timer->duration) / sms->time_allowed);
+ }
+ else {
+ step = 1.0f;
+ }
+
+ /* end timer */
+ if (step >= 1.0f) {
+ wmWindow *win = CTX_wm_window(C);
+
+ /* if we went to camera, store the original */
+ if (sms->to_camera) {
+ rv3d->persp = RV3D_CAMOB;
+ view3d_smooth_view_state_restore(&sms->org, v3d, rv3d);
+ }
+ else {
+ const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+
+ view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
+
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
+ }
+
+ if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
+ rv3d->view = sms->org_view;
+ }
+
+ MEM_freeN(rv3d->sms);
+ rv3d->sms = NULL;
+
+ WM_event_remove_timer(wm, win, rv3d->smooth_timer);
+ rv3d->smooth_timer = NULL;
+ rv3d->rflag &= ~RV3D_NAVIGATING;
+
+ /* Event handling won't know if a UI item has been moved under the pointer. */
+ WM_event_add_mousemove(win);
+ }
+ else {
+ /* ease in/out */
+ step = (3.0f * step * step - 2.0f * step * step * step);
+
+ step_inv = 1.0f - step;
+
+ interp_qt_qtqt(rv3d->viewquat, sms->src.quat, sms->dst.quat, step);
+
+ if (sms->use_dyn_ofs) {
+ view3d_orbit_apply_dyn_ofs(
+ rv3d->ofs, sms->src.ofs, sms->src.quat, rv3d->viewquat, sms->dyn_ofs);
+ }
+ else {
+ interp_v3_v3v3(rv3d->ofs, sms->src.ofs, sms->dst.ofs, step);
+ }
+
+ rv3d->dist = sms->dst.dist * step + sms->src.dist * step_inv;
+ v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv;
+
+ const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ if (ED_screen_animation_playing(wm)) {
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
+ }
+ }
+
+ if (sync_boxview && (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW)) {
+ view3d_boxview_copy(CTX_wm_area(C), region);
+ }
+
+ /* NOTE: this doesn't work right because the v3d->lens is now used in ortho mode r51636,
+ * when switching camera in quad-view the other ortho views would zoom & reset.
+ *
+ * For now only redraw all regions when smooth-view finishes.
+ */
+ if (step >= 1.0f) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ }
+ else {
+ ED_region_tag_redraw(region);
+ }
+}
+
+static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
+
+ /* escape if not our timer */
+ if (rv3d->smooth_timer == NULL || rv3d->smooth_timer != event->customdata) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ view3d_smoothview_apply(C, v3d, region, true);
+
+ return OPERATOR_FINISHED;
+}
+
+void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *region)
+{
+ RegionView3D *rv3d = region->regiondata;
+
+ if (rv3d && rv3d->sms) {
+ rv3d->sms->time_allowed = 0.0; /* force finishing */
+ view3d_smoothview_apply(C, v3d, region, false);
+
+ /* force update of view matrix so tools that run immediately after
+ * can use them without redrawing first */
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, region, NULL, NULL, NULL, false);
+ }
+}
+
+void VIEW3D_OT_smoothview(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Smooth View";
+ ot->idname = "VIEW3D_OT_smoothview";
+
+ /* api callbacks */
+ ot->invoke = view3d_smoothview_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
+
+ ot->poll = ED_operator_view3d_active;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c
index ed76b10c95a..4d6df2b655a 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_walk.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c
@@ -58,6 +58,7 @@
#include "DEG_depsgraph.h"
#include "view3d_intern.h" /* own include */
+#include "view3d_navigate.h"
#ifdef WITH_INPUT_NDOF
//# define NDOF_WALK_DEBUG
@@ -1486,9 +1487,9 @@ static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
else
#endif /* WITH_INPUT_NDOF */
- if (event->type == TIMER && event->customdata == walk->timer) {
- walkApply(C, walk, false);
- }
+ if (event->type == TIMER && event->customdata == walk->timer) {
+ walkApply(C, walk, false);
+ }
do_draw |= walk->redraw;
diff --git a/source/blender/editors/space_view3d/view3d_navigate_zoom.c b/source/blender/editors/space_view3d/view3d_navigate_zoom.c
new file mode 100644
index 00000000000..a6c7d06c079
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_navigate_zoom.c
@@ -0,0 +1,598 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup spview3d
+ */
+
+#include "BLI_math.h"
+#include "BLI_rect.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "WM_api.h"
+
+#include "RNA_access.h"
+
+#include "ED_screen.h"
+
+#include "PIL_time.h"
+
+#include "view3d_intern.h"
+#include "view3d_navigate.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name View Zoom Operator
+ * \{ */
+
+/* #viewdolly_modal_keymap has an exact copy of this, apply fixes to both. */
+void viewzoom_modal_keymap(wmKeyConfig *keyconf)
+{
+ static const EnumPropertyItem modal_items[] = {
+ {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+
+ {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
+ {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
+
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Zoom Modal");
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if (keymap && keymap->modal_items) {
+ return;
+ }
+
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Zoom Modal", modal_items);
+
+ /* disabled mode switching for now, can re-implement better, later on */
+#if 0
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+#endif
+
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
+}
+
+/**
+ * \param zoom_xy: Optionally zoom to window location
+ * (coords compatible w/ #wmEvent.xy). Use when not NULL.
+ */
+static void view_zoom_to_window_xy_camera(Scene *scene,
+ Depsgraph *depsgraph,
+ View3D *v3d,
+ ARegion *region,
+ float dfac,
+ const int zoom_xy[2])
+{
+ RegionView3D *rv3d = region->regiondata;
+ const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
+ const float zoomfac_new = clamp_f(
+ zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR);
+ const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new);
+
+ if (zoom_xy != NULL) {
+ float zoomfac_px;
+ rctf camera_frame_old;
+ rctf camera_frame_new;
+
+ const float pt_src[2] = {zoom_xy[0], zoom_xy[1]};
+ float pt_dst[2];
+ float delta_px[2];
+
+ ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &camera_frame_old, false);
+ BLI_rctf_translate(&camera_frame_old, region->winrct.xmin, region->winrct.ymin);
+
+ rv3d->camzoom = camzoom_new;
+ CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
+
+ ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &camera_frame_new, false);
+ BLI_rctf_translate(&camera_frame_new, region->winrct.xmin, region->winrct.ymin);
+
+ BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
+ sub_v2_v2v2(delta_px, pt_dst, pt_src);
+
+ /* translate the camera offset using pixel space delta
+ * mapped back to the camera (same logic as panning in camera view) */
+ zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f;
+
+ rv3d->camdx += delta_px[0] / (region->winx * zoomfac_px);
+ rv3d->camdy += delta_px[1] / (region->winy * zoomfac_px);
+ CLAMP(rv3d->camdx, -1.0f, 1.0f);
+ CLAMP(rv3d->camdy, -1.0f, 1.0f);
+ }
+ else {
+ rv3d->camzoom = camzoom_new;
+ CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
+ }
+}
+
+/**
+ * \param zoom_xy: Optionally zoom to window location
+ * (coords compatible w/ #wmEvent.xy). Use when not NULL.
+ */
+static void view_zoom_to_window_xy_3d(ARegion *region, float dfac, const int zoom_xy[2])
+{
+ RegionView3D *rv3d = region->regiondata;
+ const float dist_new = rv3d->dist * dfac;
+
+ if (zoom_xy != NULL) {
+ float dvec[3];
+ float tvec[3];
+ float tpos[3];
+ float mval_f[2];
+
+ float zfac;
+
+ negate_v3_v3(tpos, rv3d->ofs);
+
+ mval_f[0] = (float)(((zoom_xy[0] - region->winrct.xmin) * 2) - region->winx) / 2.0f;
+ mval_f[1] = (float)(((zoom_xy[1] - region->winrct.ymin) * 2) - region->winy) / 2.0f;
+
+ /* Project cursor position into 3D space */
+ zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL);
+ ED_view3d_win_to_delta(region, mval_f, dvec, zfac);
+
+ /* Calculate view target position for dolly */
+ add_v3_v3v3(tvec, tpos, dvec);
+ negate_v3(tvec);
+
+ /* Offset to target position and dolly */
+ copy_v3_v3(rv3d->ofs, tvec);
+ rv3d->dist = dist_new;
+
+ /* Calculate final offset */
+ madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac);
+ }
+ else {
+ rv3d->dist = dist_new;
+ }
+}
+
+static float viewzoom_scale_value(const rcti *winrct,
+ const eViewZoom_Style viewzoom,
+ const bool zoom_invert,
+ const bool zoom_invert_force,
+ const int xy_curr[2],
+ const int xy_init[2],
+ const float val,
+ const float val_orig,
+ double *r_timer_lastdraw)
+{
+ float zfac;
+
+ if (viewzoom == USER_ZOOM_CONTINUE) {
+ double time = PIL_check_seconds_timer();
+ float time_step = (float)(time - *r_timer_lastdraw);
+ float fac;
+
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ fac = (float)(xy_init[0] - xy_curr[0]);
+ }
+ else {
+ fac = (float)(xy_init[1] - xy_curr[1]);
+ }
+
+ fac /= U.dpi_fac;
+
+ if (zoom_invert != zoom_invert_force) {
+ fac = -fac;
+ }
+
+ zfac = 1.0f + ((fac / 20.0f) * time_step);
+ *r_timer_lastdraw = time;
+ }
+ else if (viewzoom == USER_ZOOM_SCALE) {
+ /* method which zooms based on how far you move the mouse */
+
+ const int ctr[2] = {
+ BLI_rcti_cent_x(winrct),
+ BLI_rcti_cent_y(winrct),
+ };
+ float len_new = (5 * U.dpi_fac) + ((float)len_v2v2_int(ctr, xy_curr) / U.dpi_fac);
+ float len_old = (5 * U.dpi_fac) + ((float)len_v2v2_int(ctr, xy_init) / U.dpi_fac);
+
+ /* intentionally ignore 'zoom_invert' for scale */
+ if (zoom_invert_force) {
+ SWAP(float, len_new, len_old);
+ }
+
+ zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val;
+ }
+ else { /* USER_ZOOM_DOLLY */
+ float len_new = 5 * U.dpi_fac;
+ float len_old = 5 * U.dpi_fac;
+
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ len_new += (winrct->xmax - (xy_curr[0])) / U.dpi_fac;
+ len_old += (winrct->xmax - (xy_init[0])) / U.dpi_fac;
+ }
+ else {
+ len_new += (winrct->ymax - (xy_curr[1])) / U.dpi_fac;
+ len_old += (winrct->ymax - (xy_init[1])) / U.dpi_fac;
+ }
+
+ if (zoom_invert != zoom_invert_force) {
+ SWAP(float, len_new, len_old);
+ }
+
+ zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val;
+ }
+
+ return zfac;
+}
+
+static float viewzoom_scale_value_offset(const rcti *winrct,
+ const eViewZoom_Style viewzoom,
+ const bool zoom_invert,
+ const bool zoom_invert_force,
+ const int xy_curr[2],
+ const int xy_init[2],
+ const int xy_offset[2],
+ const float val,
+ const float val_orig,
+ double *r_timer_lastdraw)
+{
+ const int xy_curr_offset[2] = {
+ xy_curr[0] + xy_offset[0],
+ xy_curr[1] + xy_offset[1],
+ };
+ const int xy_init_offset[2] = {
+ xy_init[0] + xy_offset[0],
+ xy_init[1] + xy_offset[1],
+ };
+ return viewzoom_scale_value(winrct,
+ viewzoom,
+ zoom_invert,
+ zoom_invert_force,
+ xy_curr_offset,
+ xy_init_offset,
+ val,
+ val_orig,
+ r_timer_lastdraw);
+}
+
+static void viewzoom_apply_camera(ViewOpsData *vod,
+ const int xy[2],
+ const eViewZoom_Style viewzoom,
+ const bool zoom_invert,
+ const bool zoom_to_pos)
+{
+ float zfac;
+ float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->init.camzoom) * 2.0f;
+ float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
+
+ zfac = viewzoom_scale_value_offset(&vod->region->winrct,
+ viewzoom,
+ zoom_invert,
+ true,
+ xy,
+ vod->init.event_xy,
+ vod->init.event_xy_offset,
+ zoomfac,
+ zoomfac_prev,
+ &vod->prev.time);
+
+ if (!ELEM(zfac, 1.0f, 0.0f)) {
+ /* calculate inverted, then invert again (needed because of camera zoom scaling) */
+ zfac = 1.0f / zfac;
+ view_zoom_to_window_xy_camera(vod->scene,
+ vod->depsgraph,
+ vod->v3d,
+ vod->region,
+ zfac,
+ zoom_to_pos ? vod->prev.event_xy : NULL);
+ }
+
+ ED_region_tag_redraw(vod->region);
+}
+
+static void viewzoom_apply_3d(ViewOpsData *vod,
+ const int xy[2],
+ const eViewZoom_Style viewzoom,
+ const bool zoom_invert,
+ const bool zoom_to_pos)
+{
+ float zfac;
+ float dist_range[2];
+
+ ED_view3d_dist_range_get(vod->v3d, dist_range);
+
+ zfac = viewzoom_scale_value_offset(&vod->region->winrct,
+ viewzoom,
+ zoom_invert,
+ false,
+ xy,
+ vod->init.event_xy,
+ vod->init.event_xy_offset,
+ vod->rv3d->dist,
+ vod->init.dist,
+ &vod->prev.time);
+
+ if (zfac != 1.0f) {
+ const float zfac_min = dist_range[0] / vod->rv3d->dist;
+ const float zfac_max = dist_range[1] / vod->rv3d->dist;
+ CLAMP(zfac, zfac_min, zfac_max);
+
+ view_zoom_to_window_xy_3d(vod->region, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
+ }
+
+ /* these limits were in old code too */
+ CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]);
+
+ if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(vod->area, vod->region);
+ }
+
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
+
+ ED_region_tag_redraw(vod->region);
+}
+
+static void viewzoom_apply(ViewOpsData *vod,
+ const int xy[2],
+ const eViewZoom_Style viewzoom,
+ const bool zoom_invert,
+ const bool zoom_to_pos)
+{
+ if ((vod->rv3d->persp == RV3D_CAMOB) &&
+ (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0) {
+ viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
+ }
+ else {
+ viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
+ }
+}
+
+static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+ bool use_autokey = false;
+ int ret = OPERATOR_RUNNING_MODAL;
+
+ /* execute the events */
+ if (event->type == TIMER && event->customdata == vod->timer) {
+ /* continuous zoom */
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_MOVE:
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ROTATE:
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
+ viewzoom_apply(vod,
+ event->xy,
+ (eViewZoom_Style)U.viewzoom,
+ (U.uiflag & USER_ZOOM_INVERT) != 0,
+ (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
+ if (ED_screen_animation_playing(CTX_wm_manager(C))) {
+ use_autokey = true;
+ }
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ use_autokey = true;
+ ret = OPERATOR_FINISHED;
+ }
+
+ if (use_autokey) {
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+ }
+
+ if (ret & OPERATOR_FINISHED) {
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+ }
+
+ return ret;
+}
+
+static int viewzoom_exec(bContext *C, wmOperator *op)
+{
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ScrArea *area;
+ ARegion *region;
+ bool use_cam_zoom;
+ float dist_range[2];
+
+ const int delta = RNA_int_get(op->ptr, "delta");
+ const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
+
+ if (op->customdata) {
+ ViewOpsData *vod = op->customdata;
+
+ area = vod->area;
+ region = vod->region;
+ }
+ else {
+ area = CTX_wm_area(C);
+ region = CTX_wm_region(C);
+ }
+
+ v3d = area->spacedata.first;
+ rv3d = region->regiondata;
+
+ use_cam_zoom = (rv3d->persp == RV3D_CAMOB) &&
+ !(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
+
+ int zoom_xy_buf[2];
+ const int *zoom_xy = NULL;
+ if (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
+ zoom_xy_buf[0] = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") :
+ region->winx / 2;
+ zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") :
+ region->winy / 2;
+ zoom_xy = zoom_xy_buf;
+ }
+
+ ED_view3d_dist_range_get(v3d, dist_range);
+
+ if (delta < 0) {
+ const float step = 1.2f;
+ if (use_cam_zoom) {
+ view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy);
+ }
+ else {
+ if (rv3d->dist < dist_range[1]) {
+ view_zoom_to_window_xy_3d(region, step, zoom_xy);
+ }
+ }
+ }
+ else {
+ const float step = 1.0f / 1.2f;
+ if (use_cam_zoom) {
+ view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy);
+ }
+ else {
+ if (rv3d->dist > dist_range[0]) {
+ view_zoom_to_window_xy_3d(region, step, zoom_xy);
+ }
+ }
+ }
+
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(area, region);
+ }
+
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
+ ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
+
+ ED_region_tag_redraw(region);
+
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+
+ return OPERATOR_FINISHED;
+}
+
+/* viewdolly_invoke() copied this function, changes here may apply there */
+static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod;
+
+ const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
+
+ vod = op->customdata = viewops_data_create(
+ C,
+ event,
+ (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
+ (use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
+
+ ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
+
+ /* if one or the other zoom position aren't set, set from event */
+ if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
+ RNA_int_set(op->ptr, "mx", event->xy[0]);
+ RNA_int_set(op->ptr, "my", event->xy[1]);
+ }
+
+ if (RNA_struct_property_is_set(op->ptr, "delta")) {
+ viewzoom_exec(C, op);
+ }
+ else {
+ if (ELEM(event->type, MOUSEZOOM, MOUSEPAN)) {
+
+ if (U.uiflag & USER_ZOOM_HORIZ) {
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->xy[0];
+ }
+ else {
+ /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
+ vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->xy[0] -
+ event->prev_xy[0];
+ }
+ viewzoom_apply(vod,
+ event->prev_xy,
+ USER_ZOOM_DOLLY,
+ (U.uiflag & USER_ZOOM_INVERT) != 0,
+ (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
+ ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
+
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+ return OPERATOR_FINISHED;
+ }
+
+ if (U.viewzoom == USER_ZOOM_CONTINUE) {
+ /* needs a timer to continue redrawing */
+ vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
+ vod->prev.time = PIL_check_seconds_timer();
+ }
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ return OPERATOR_FINISHED;
+}
+
+static void viewzoom_cancel(bContext *C, wmOperator *op)
+{
+ viewops_data_free(C, op->customdata);
+ op->customdata = NULL;
+}
+
+void VIEW3D_OT_zoom(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Zoom View";
+ ot->description = "Zoom in/out in the view";
+ ot->idname = "VIEW3D_OT_zoom";
+
+ /* api callbacks */
+ ot->invoke = viewzoom_invoke;
+ ot->exec = viewzoom_exec;
+ ot->modal = viewzoom_modal;
+ ot->poll = view3d_zoom_or_dolly_poll;
+ ot->cancel = viewzoom_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY;
+
+ /* properties */
+ view3d_operator_properties_common(
+ ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_navigate_zoom_border.c b/source/blender/editors/space_view3d/view3d_navigate_zoom_border.c
new file mode 100644
index 00000000000..38c3e37bac6
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_navigate_zoom_border.c
@@ -0,0 +1,221 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup spview3d
+ */
+
+#include "DNA_camera_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_rect.h"
+
+#include "BKE_context.h"
+#include "BKE_report.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "WM_api.h"
+
+#include "RNA_access.h"
+
+#include "view3d_intern.h"
+#include "view3d_navigate.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name Border Zoom Operator
+ * \{ */
+
+static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
+{
+ ARegion *region = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ /* Zooms in on a border drawn by the user */
+ rcti rect;
+ float dvec[3], vb[2], xscale, yscale;
+ float dist_range[2];
+
+ /* SMOOTHVIEW */
+ float new_dist;
+ float new_ofs[3];
+
+ /* ZBuffer depth vars */
+ float depth_close = FLT_MAX;
+ float cent[2], p[3];
+
+ /* NOTE: otherwise opengl won't work. */
+ view3d_operator_needs_opengl(C);
+
+ /* get box select values using rna */
+ WM_operator_properties_border_to_rcti(op, &rect);
+
+ /* check if zooming in/out view */
+ const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out");
+
+ ED_view3d_dist_range_get(v3d, dist_range);
+
+ ED_view3d_depth_override(
+ CTX_data_ensure_evaluated_depsgraph(C), region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, NULL);
+ {
+ /* avoid allocating the whole depth buffer */
+ ViewDepths depth_temp = {0};
+
+ /* avoid view3d_update_depths() for speed. */
+ view3d_depths_rect_create(region, &rect, &depth_temp);
+
+ /* find the closest Z pixel */
+ depth_close = view3d_depth_near(&depth_temp);
+
+ MEM_SAFE_FREE(depth_temp.depths);
+ }
+
+ /* Resize border to the same ratio as the window. */
+ {
+ const float region_aspect = (float)region->winx / (float)region->winy;
+ if (((float)BLI_rcti_size_x(&rect) / (float)BLI_rcti_size_y(&rect)) < region_aspect) {
+ BLI_rcti_resize_x(&rect, (int)(BLI_rcti_size_y(&rect) * region_aspect));
+ }
+ else {
+ BLI_rcti_resize_y(&rect, (int)(BLI_rcti_size_x(&rect) / region_aspect));
+ }
+ }
+
+ cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
+ cent[1] = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
+
+ if (rv3d->is_persp) {
+ float p_corner[3];
+
+ /* no depths to use, we can't do anything! */
+ if (depth_close == FLT_MAX) {
+ BKE_report(op->reports, RPT_ERROR, "Depth too large");
+ return OPERATOR_CANCELLED;
+ }
+ /* convert border to 3d coordinates */
+ if ((!ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p)) ||
+ (!ED_view3d_unproject_v3(region, rect.xmin, rect.ymin, depth_close, p_corner))) {
+ return OPERATOR_CANCELLED;
+ }
+
+ sub_v3_v3v3(dvec, p, p_corner);
+ negate_v3_v3(new_ofs, p);
+
+ new_dist = len_v3(dvec);
+
+ /* Account for the lens, without this a narrow lens zooms in too close. */
+ new_dist *= (v3d->lens / DEFAULT_SENSOR_WIDTH);
+
+ /* ignore dist_range min */
+ dist_range[0] = v3d->clip_start * 1.5f;
+ }
+ else { /* orthographic */
+ /* find the current window width and height */
+ vb[0] = region->winx;
+ vb[1] = region->winy;
+
+ new_dist = rv3d->dist;
+
+ /* convert the drawn rectangle into 3d space */
+ if (depth_close != FLT_MAX &&
+ ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p)) {
+ negate_v3_v3(new_ofs, p);
+ }
+ else {
+ float mval_f[2];
+ float zfac;
+
+ /* We can't use the depth, fallback to the old way that doesn't set the center depth */
+ copy_v3_v3(new_ofs, rv3d->ofs);
+
+ {
+ float tvec[3];
+ negate_v3_v3(tvec, new_ofs);
+ zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
+ }
+
+ mval_f[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f;
+ mval_f[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f;
+ ED_view3d_win_to_delta(region, mval_f, dvec, zfac);
+ /* center the view to the center of the rectangle */
+ sub_v3_v3(new_ofs, dvec);
+ }
+
+ /* work out the ratios, so that everything selected fits when we zoom */
+ xscale = (BLI_rcti_size_x(&rect) / vb[0]);
+ yscale = (BLI_rcti_size_y(&rect) / vb[1]);
+ new_dist *= max_ff(xscale, yscale);
+ }
+
+ if (!zoom_in) {
+ sub_v3_v3v3(dvec, new_ofs, rv3d->ofs);
+ new_dist = rv3d->dist * (rv3d->dist / new_dist);
+ add_v3_v3v3(new_ofs, rv3d->ofs, dvec);
+ }
+
+ /* clamp after because we may have been zooming out */
+ CLAMP(new_dist, dist_range[0], dist_range[1]);
+
+ /* TODO(campbell): 'is_camera_lock' not currently working well. */
+ const bool is_camera_lock = ED_view3d_camera_lock_check(v3d, rv3d);
+ if ((rv3d->persp == RV3D_CAMOB) && (is_camera_lock == false)) {
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, RV3D_PERSP);
+ }
+
+ ED_view3d_smooth_view(C,
+ v3d,
+ region,
+ smooth_viewtx,
+ &(const V3D_SmoothParams){
+ .ofs = new_ofs,
+ .dist = &new_dist,
+ });
+
+ if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
+ view3d_boxview_sync(CTX_wm_area(C), region);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_zoom_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Zoom to Border";
+ ot->description = "Zoom in the view to the nearest object contained in the border";
+ ot->idname = "VIEW3D_OT_zoom_border";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = view3d_zoom_border_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
+
+ ot->poll = view3d_zoom_or_dolly_poll;
+
+ /* flags */
+ ot->flag = 0;
+
+ /* properties */
+ WM_operator_properties_gesture_box_zoom(ot);
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 823aa3b6643..52db8526937 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -50,6 +50,7 @@
#include "ED_transform.h"
#include "view3d_intern.h"
+#include "view3d_navigate.h"
#ifdef WIN32
# include "BLI_math_base.h" /* M_PI */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 45899880b41..34aa24a1eef 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -99,6 +99,7 @@
#include "UI_resources.h"
#include "GPU_matrix.h"
+#include "GPU_select.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -1566,8 +1567,8 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot)
static Base *object_mouse_select_menu(bContext *C,
ViewContext *vc,
- const uint *buffer,
- int hits,
+ const GPUSelectResult *buffer,
+ const int hits,
const int mval[2],
bool extend,
bool deselect,
@@ -1585,7 +1586,7 @@ static Base *object_mouse_select_menu(bContext *C,
if (buffer) {
for (int a = 0; a < hits; a++) {
/* index was converted */
- if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
+ if (base->object->runtime.select_id == (buffer[a].id & ~0xFFFF0000)) {
ok = true;
break;
}
@@ -1742,7 +1743,7 @@ void VIEW3D_OT_bone_select_menu(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static bool bone_mouse_select_menu(bContext *C,
- const uint *buffer,
+ const GPUSelectResult *buffer,
const int hits,
const bool is_editmode,
const bool extend,
@@ -1760,7 +1761,7 @@ static bool bone_mouse_select_menu(bContext *C,
for (int a = 0; a < hits; a++) {
void *bone_ptr = NULL;
Base *bone_base = NULL;
- uint hitresult = buffer[3 + (a * 4)];
+ uint hitresult = buffer[a].id;
if (!(hitresult & BONESEL_ANY)) {
/* To avoid including objects in selection. */
@@ -1874,10 +1875,10 @@ static bool bone_mouse_select_menu(bContext *C,
return true;
}
-static bool selectbuffer_has_bones(const uint *buffer, const uint hits)
+static bool selectbuffer_has_bones(const GPUSelectResult *buffer, const uint hits)
{
for (uint i = 0; i < hits; i++) {
- if (buffer[(4 * i) + 3] & 0xFFFF0000) {
+ if (buffer[i].id & 0xFFFF0000) {
return true;
}
}
@@ -1885,25 +1886,25 @@ static bool selectbuffer_has_bones(const uint *buffer, const uint hits)
}
/* utility function for mixed_bones_object_selectbuffer */
-static int selectbuffer_ret_hits_15(uint *UNUSED(buffer), const int hits15)
+static int selectbuffer_ret_hits_15(GPUSelectResult *UNUSED(buffer), const int hits15)
{
return hits15;
}
-static int selectbuffer_ret_hits_9(uint *buffer, const int hits15, const int hits9)
+static int selectbuffer_ret_hits_9(GPUSelectResult *buffer, const int hits15, const int hits9)
{
- const int ofs = 4 * hits15;
- memcpy(buffer, buffer + ofs, 4 * hits9 * sizeof(uint));
+ const int ofs = hits15;
+ memcpy(buffer, buffer + ofs, hits9 * sizeof(GPUSelectResult));
return hits9;
}
-static int selectbuffer_ret_hits_5(uint *buffer,
+static int selectbuffer_ret_hits_5(GPUSelectResult *buffer,
const int hits15,
const int hits9,
const int hits5)
{
- const int ofs = 4 * hits15 + 4 * hits9;
- memcpy(buffer, buffer + ofs, 4 * hits5 * sizeof(uint));
+ const int ofs = hits15 + hits9;
+ memcpy(buffer, buffer + ofs, hits5 * sizeof(GPUSelectResult));
return hits5;
}
@@ -1916,7 +1917,8 @@ static int selectbuffer_ret_hits_5(uint *buffer,
* Needed so we can step to the next, non-active object when it's already selected, see: T76445.
*/
static int mixed_bones_object_selectbuffer(ViewContext *vc,
- uint *buffer,
+ GPUSelectResult *buffer,
+ const int buffer_len,
const int mval[2],
eV3DSelectObjectFilter select_filter,
bool do_nearest,
@@ -1941,7 +1943,7 @@ static int mixed_bones_object_selectbuffer(ViewContext *vc,
BLI_rcti_init_pt_radius(&rect, mval, 14);
hits15 = view3d_opengl_select_ex(
- vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter, do_material_slot_selection);
+ vc, buffer, buffer_len, &rect, select_mode, select_filter, do_material_slot_selection);
if (hits15 == 1) {
hits = selectbuffer_ret_hits_15(buffer, hits15);
goto finally;
@@ -1950,10 +1952,10 @@ static int mixed_bones_object_selectbuffer(ViewContext *vc,
int ofs;
has_bones15 = selectbuffer_has_bones(buffer, hits15);
- ofs = 4 * hits15;
+ ofs = hits15;
BLI_rcti_init_pt_radius(&rect, mval, 9);
hits9 = view3d_opengl_select(
- vc, buffer + ofs, MAXPICKBUF - ofs, &rect, select_mode, select_filter);
+ vc, buffer + ofs, buffer_len - ofs, &rect, select_mode, select_filter);
if (hits9 == 1) {
hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
goto finally;
@@ -1961,10 +1963,10 @@ static int mixed_bones_object_selectbuffer(ViewContext *vc,
else if (hits9 > 0) {
has_bones9 = selectbuffer_has_bones(buffer + ofs, hits9);
- ofs += 4 * hits9;
+ ofs += hits9;
BLI_rcti_init_pt_radius(&rect, mval, 5);
hits5 = view3d_opengl_select(
- vc, buffer + ofs, MAXPICKBUF - ofs, &rect, select_mode, select_filter);
+ vc, buffer + ofs, buffer_len - ofs, &rect, select_mode, select_filter);
if (hits5 == 1) {
hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
goto finally;
@@ -2007,7 +2009,8 @@ finally:
}
static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
- uint *buffer,
+ GPUSelectResult *buffer,
+ const int buffer_len,
const int mval[2],
eV3DSelectObjectFilter select_filter,
bool use_cycle,
@@ -2038,7 +2041,7 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
do_nearest = do_nearest && !enumerate;
int hits = mixed_bones_object_selectbuffer(
- vc, buffer, mval, select_filter, do_nearest, true, false);
+ vc, buffer, buffer_len, mval, select_filter, do_nearest, true, false);
return hits;
}
@@ -2051,7 +2054,7 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
* \return the active base or NULL.
*/
static Base *mouse_select_eval_buffer(ViewContext *vc,
- const uint *buffer,
+ const GPUSelectResult *buffer,
int hits,
Base *startbase,
bool has_bones,
@@ -2071,10 +2074,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
if (has_bones) {
/* we skip non-bone hits */
for (a = 0; a < hits; a++) {
- if (min > buffer[4 * a + 1] && (buffer[4 * a + 3] & 0xFFFF0000)) {
- min = buffer[4 * a + 1];
- selcol = buffer[4 * a + 3] & 0xFFFF;
- sub_selection_id = (buffer[4 * a + 3] & 0xFFFF0000) >> 16;
+ if (min > buffer[a].depth && (buffer[a].id & 0xFFFF0000)) {
+ min = buffer[a].depth;
+ selcol = buffer[a].id & 0xFFFF;
+ sub_selection_id = (buffer[a].id & 0xFFFF0000) >> 16;
}
}
}
@@ -2085,10 +2088,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
}
for (a = 0; a < hits; a++) {
- if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
- min = buffer[4 * a + 1];
- selcol = buffer[4 * a + 3] & 0xFFFF;
- sub_selection_id = (buffer[4 * a + 3] & 0xFFFF0000) >> 16;
+ if (min > buffer[a].depth && notcol != (buffer[a].id & 0xFFFF)) {
+ min = buffer[a].depth;
+ selcol = buffer[a].id & 0xFFFF;
+ sub_selection_id = (buffer[a].id & 0xFFFF0000) >> 16;
}
}
}
@@ -2127,14 +2130,14 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
for (a = 0; a < hits; a++) {
if (has_bones) {
/* skip non-bone objects */
- if (buffer[4 * a + 3] & 0xFFFF0000) {
- if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
+ if (buffer[a].id & 0xFFFF0000) {
+ if (base->object->runtime.select_id == (buffer[a].id & 0xFFFF)) {
basact = base;
}
}
}
else {
- if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
+ if (base->object->runtime.select_id == (buffer[a].id & 0xFFFF)) {
basact = base;
}
}
@@ -2169,7 +2172,7 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C,
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
Base *basact = NULL;
- uint buffer[MAXPICKBUF];
+ GPUSelectResult buffer[MAXPICKELEMS];
/* setup view context for argument to callbacks */
view3d_operator_needs_opengl(C);
@@ -2179,8 +2182,14 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C,
const bool do_nearest = !XRAY_ACTIVE(vc.v3d);
const bool do_material_slot_selection = r_material_slot != NULL;
- const int hits = mixed_bones_object_selectbuffer(
- &vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest, false, do_material_slot_selection);
+ const int hits = mixed_bones_object_selectbuffer(&vc,
+ buffer,
+ ARRAY_SIZE(buffer),
+ mval,
+ VIEW3D_SELECT_FILTER_NOP,
+ do_nearest,
+ false,
+ do_material_slot_selection);
if (hits > 0) {
const bool has_bones = (r_material_slot == NULL) && selectbuffer_has_bones(buffer, hits);
@@ -2342,7 +2351,7 @@ static bool ed_object_select_pick(bContext *C,
}
}
else {
- uint buffer[MAXPICKBUF];
+ GPUSelectResult buffer[MAXPICKELEMS];
bool do_nearest;
// TIMEIT_START(select_time);
@@ -2353,7 +2362,7 @@ static bool ed_object_select_pick(bContext *C,
vc.obact) :
VIEW3D_SELECT_FILTER_NOP);
hits = mixed_bones_object_selectbuffer_extended(
- &vc, buffer, mval, select_filter, true, enumerate, &do_nearest);
+ &vc, buffer, ARRAY_SIZE(buffer), mval, select_filter, true, enumerate, &do_nearest);
// TIMEIT_END(select_time);
@@ -2383,7 +2392,7 @@ static bool ed_object_select_pick(bContext *C,
bool changed = false;
for (int i = 0; i < hits; i++) {
- int hitresult = buffer[3 + (i * 4)];
+ const int hitresult = buffer[i].id;
/* if there's bundles in buffer select bundles first,
* so non-camera elements should be ignored in buffer */
@@ -2394,7 +2403,7 @@ static bool ed_object_select_pick(bContext *C,
/* index of bundle is 1<<16-based. if there's no "bone" index
* in height word, this buffer value belongs to camera. not to bundle
*/
- if (buffer[4 * i + 3] & 0xFFFF0000) {
+ if (hitresult & 0xFFFF0000) {
MovieTracking *tracking = &clip->tracking;
ListBase *tracksbase;
MovieTrackingTrack *track;
@@ -2674,9 +2683,15 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
- uint buffer[MAXPICKBUF];
- const int hits = mixed_bones_object_selectbuffer(
- &vc, buffer, location, VIEW3D_SELECT_FILTER_NOP, false, true, false);
+ GPUSelectResult buffer[MAXPICKELEMS];
+ const int hits = mixed_bones_object_selectbuffer(&vc,
+ buffer,
+ ARRAY_SIZE(buffer),
+ location,
+ VIEW3D_SELECT_FILTER_NOP,
+ false,
+ true,
+ false);
retval = bone_mouse_select_menu(C, buffer, hits, true, extend, deselect, toggle);
}
if (!retval) {
@@ -3256,11 +3271,11 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO
int a;
bool changed = false;
- uint buffer[MAXPICKBUF];
+ GPUSelectResult buffer[MAXPICKELEMS];
int hits;
hits = view3d_opengl_select(
- vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
+ vc, buffer, MAXPICKELEMS, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
changed |= BKE_mball_deselect_all(mb);
@@ -3272,7 +3287,7 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO
bool is_inside_stiff = false;
for (a = 0; a < hits; a++) {
- int hitresult = buffer[(4 * a) + 3];
+ const int hitresult = buffer[a].id;
if (hitresult == -1) {
continue;
@@ -3323,11 +3338,11 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel
bool changed = false;
int a;
- uint buffer[MAXPICKBUF];
+ GPUSelectResult buffer[MAXPICKELEMS];
int hits;
hits = view3d_opengl_select(
- vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
+ vc, buffer, MAXPICKELEMS, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
uint bases_len = 0;
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
@@ -3347,7 +3362,7 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel
/* first we only check points inside the border */
for (a = 0; a < hits; a++) {
- int select_id = buffer[(4 * a) + 3];
+ const int select_id = buffer[a].id;
if (select_id != -1) {
if ((select_id & 0xFFFF0000) == 0) {
continue;
@@ -3375,14 +3390,13 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel
}
/**
- * Compare result of 'GPU_select': 'uint[4]',
+ * Compare result of 'GPU_select': 'GPUSelectResult',
* needed for when we need to align with object draw-order.
*/
static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
{
- /* 4th element is select id */
- uint sel_a = ((uint *)sel_a_p)[3];
- uint sel_b = ((uint *)sel_b_p)[3];
+ uint sel_a = ((GPUSelectResult *)sel_a_p)->id;
+ uint sel_b = ((GPUSelectResult *)sel_b_p)->id;
#ifdef __BIG_ENDIAN__
BLI_endian_switch_uint32(&sel_a);
@@ -3401,14 +3415,15 @@ static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_
static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
View3D *v3d = vc->v3d;
- int totobj = MAXPICKBUF; /* XXX solve later */
+ int totobj = MAXPICKELEMS; /* XXX solve later */
- /* selection buffer now has bones potentially too, so we add MAXPICKBUF */
- uint *vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
+ /* Selection buffer has bones potentially too, so we add #MAXPICKELEMS. */
+ GPUSelectResult *buffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult),
+ "selection buffer");
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
vc->obact);
const int hits = view3d_opengl_select(
- vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
+ vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
LISTBASE_FOREACH (Base *, base, &vc->view_layer->object_bases) {
base->object->id.tag &= ~LIB_TAG_DOIT;
@@ -3435,12 +3450,13 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
}
/* The draw order doesn't always match the order we populate the engine, see: T51695. */
- qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
+ qsort(buffer, hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp);
- for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
+ for (const GPUSelectResult *buf_iter = buffer, *buf_end = buf_iter + hits; buf_iter < buf_end;
+ buf_iter++) {
bPoseChannel *pchan_dummy;
Base *base = ED_armature_base_and_pchan_from_select_buffer(
- bases, BLI_array_len(bases), *col, &pchan_dummy);
+ bases, BLI_array_len(bases), buf_iter->id, &pchan_dummy);
if (base != NULL) {
base->object->id.tag |= LIB_TAG_DOIT;
}
@@ -3463,7 +3479,7 @@ finally:
MEM_freeN(bases);
}
- MEM_freeN(vbuffer);
+ MEM_freeN(buffer);
if (changed) {
DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
@@ -3477,14 +3493,15 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
uint bases_len;
Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len);
- int totobj = MAXPICKBUF; /* XXX solve later */
+ int totobj = MAXPICKELEMS; /* XXX solve later */
- /* selection buffer now has bones potentially too, so we add MAXPICKBUF */
- uint *vbuffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
+ /* Selection buffer has bones potentially too, so add #MAXPICKELEMS. */
+ GPUSelectResult *buffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult),
+ "selection buffer");
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
vc->obact);
const int hits = view3d_opengl_select(
- vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
+ vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
/*
* LOGIC NOTES (theeth):
* The buffer and ListBase have the same relative order, which makes the selection
@@ -3498,18 +3515,20 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
/* no need to loop if there's no hit */
/* The draw order doesn't always match the order we populate the engine, see: T51695. */
- qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
+ qsort(buffer, hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp);
- for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
+ for (const GPUSelectResult *buf_iter = buffer, *buf_end = buf_iter + hits; buf_iter < buf_end;
+ buf_iter++) {
Bone *bone;
- Base *base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, *col, &bone);
+ Base *base = ED_armature_base_and_bone_from_select_buffer(
+ bases, bases_len, buf_iter->id, &bone);
if (base == NULL) {
continue;
}
/* Loop over contiguous bone hits for 'base'. */
- for (; col != col_end; col += 4) {
+ for (; buf_iter != buf_end; buf_iter++) {
/* should never fail */
if (bone != NULL) {
base->object->id.tag |= LIB_TAG_DOIT;
@@ -3517,12 +3536,13 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
}
/* Select the next bone if we're not switching bases. */
- if (col + 4 != col_end) {
- if ((base->object->runtime.select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
+ if (buf_iter + 1 != buf_end) {
+ const GPUSelectResult *col_next = buf_iter + 1;
+ if ((base->object->runtime.select_id & 0x0000FFFF) != (col_next->id & 0x0000FFFF)) {
break;
}
if (base->object->pose != NULL) {
- const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16;
+ const uint hit_bone = (col_next->id & ~BONESEL_ANY) >> 16;
bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
bone = pchan ? pchan->bone : NULL;
}
@@ -3543,7 +3563,7 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
if (bases != NULL) {
MEM_freeN(bases);
}
- MEM_freeN(vbuffer);
+ MEM_freeN(buffer);
return changed_multi;
}
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 165f931394d..ddd5cc640bb 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -21,21 +21,14 @@
* \ingroup spview3d
*/
-#include "DNA_camera_types.h"
-#include "DNA_gpencil_modifier_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
#include "MEM_guardedalloc.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
-#include "BLI_utildefines.h"
#include "BKE_action.h"
-#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_gpencil_modifier.h"
@@ -47,7 +40,6 @@
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
#include "UI_resources.h"
@@ -57,7 +49,6 @@
#include "GPU_state.h"
#include "WM_api.h"
-#include "WM_types.h"
#include "ED_object.h"
#include "ED_screen.h"
@@ -68,376 +59,7 @@
#include "RNA_define.h"
#include "view3d_intern.h" /* own include */
-
-/* -------------------------------------------------------------------- */
-/** \name Smooth View Operator & Utilities
- *
- * Use for view transitions to have smooth (animated) transitions.
- * \{ */
-
-/* This operator is one of the 'timer refresh' ones like animation playback */
-
-struct SmoothView3DState {
- float dist;
- float lens;
- float quat[4];
- float ofs[3];
-};
-
-struct SmoothView3DStore {
- /* Source. */
- struct SmoothView3DState src; /* source */
- struct SmoothView3DState dst; /* destination */
- struct SmoothView3DState org; /* original */
-
- bool to_camera;
-
- bool use_dyn_ofs;
- float dyn_ofs[3];
-
- /* When smooth-view is enabled, store the 'rv3d->view' here,
- * assign back when the view motion is completed. */
- char org_view;
-
- double time_allowed;
-};
-
-static void view3d_smooth_view_state_backup(struct SmoothView3DState *sms_state,
- const View3D *v3d,
- const RegionView3D *rv3d)
-{
- copy_v3_v3(sms_state->ofs, rv3d->ofs);
- copy_qt_qt(sms_state->quat, rv3d->viewquat);
- sms_state->dist = rv3d->dist;
- sms_state->lens = v3d->lens;
-}
-
-static void view3d_smooth_view_state_restore(const struct SmoothView3DState *sms_state,
- View3D *v3d,
- RegionView3D *rv3d)
-{
- copy_v3_v3(rv3d->ofs, sms_state->ofs);
- copy_qt_qt(rv3d->viewquat, sms_state->quat);
- rv3d->dist = sms_state->dist;
- v3d->lens = sms_state->lens;
-}
-
-/* will start timer if appropriate */
-void ED_view3d_smooth_view_ex(
- /* avoid passing in the context */
- const Depsgraph *depsgraph,
- wmWindowManager *wm,
- wmWindow *win,
- ScrArea *area,
- View3D *v3d,
- ARegion *region,
- const int smooth_viewtx,
- const V3D_SmoothParams *sview)
-{
- RegionView3D *rv3d = region->regiondata;
- struct SmoothView3DStore sms = {{0}};
-
- /* initialize sms */
- view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d);
- view3d_smooth_view_state_backup(&sms.src, v3d, rv3d);
- /* If smooth-view runs multiple times. */
- if (rv3d->sms == NULL) {
- view3d_smooth_view_state_backup(&sms.org, v3d, rv3d);
- }
- else {
- sms.org = rv3d->sms->org;
- }
- sms.org_view = rv3d->view;
-
- /* sms.to_camera = false; */ /* initialized to zero anyway */
-
- /* note on camera locking, this is a little confusing but works ok.
- * we may be changing the view 'as if' there is no active camera, but in fact
- * there is an active camera which is locked to the view.
- *
- * In the case where smooth view is moving _to_ a camera we don't want that
- * camera to be moved or changed, so only when the camera is not being set should
- * we allow camera option locking to initialize the view settings from the camera.
- */
- if (sview->camera == NULL && sview->camera_old == NULL) {
- ED_view3d_camera_lock_init(depsgraph, v3d, rv3d);
- }
-
- /* store the options we want to end with */
- if (sview->ofs) {
- copy_v3_v3(sms.dst.ofs, sview->ofs);
- }
- if (sview->quat) {
- copy_qt_qt(sms.dst.quat, sview->quat);
- }
- if (sview->dist) {
- sms.dst.dist = *sview->dist;
- }
- if (sview->lens) {
- sms.dst.lens = *sview->lens;
- }
-
- if (sview->dyn_ofs) {
- BLI_assert(sview->ofs == NULL);
- BLI_assert(sview->quat != NULL);
-
- copy_v3_v3(sms.dyn_ofs, sview->dyn_ofs);
- sms.use_dyn_ofs = true;
-
- /* calculate the final destination offset */
- view3d_orbit_apply_dyn_ofs(sms.dst.ofs, sms.src.ofs, sms.src.quat, sms.dst.quat, sms.dyn_ofs);
- }
-
- if (sview->camera) {
- Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
- if (sview->ofs != NULL) {
- sms.dst.dist = ED_view3d_offset_distance(
- ob_camera_eval->obmat, sview->ofs, VIEW3D_DIST_FALLBACK);
- }
- ED_view3d_from_object(ob_camera_eval, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
- sms.to_camera = true; /* restore view3d values in end */
- }
-
- if ((sview->camera_old == sview->camera) && /* Camera. */
- (sms.dst.dist == rv3d->dist) && /* Distance. */
- (sms.dst.lens == v3d->lens) && /* Lens. */
- equals_v3v3(sms.dst.ofs, rv3d->ofs) && /* Offset. */
- equals_v4v4(sms.dst.quat, rv3d->viewquat) /* Rotation. */
- ) {
- /* Early return if nothing changed. */
- return;
- }
-
- /* Skip smooth viewing for external render engine draw. */
- if (smooth_viewtx && !(v3d->shading.type == OB_RENDER && rv3d->render_engine)) {
-
- /* original values */
- if (sview->camera_old) {
- Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old);
- if (sview->ofs != NULL) {
- sms.src.dist = ED_view3d_offset_distance(ob_camera_old_eval->obmat, sview->ofs, 0.0f);
- }
- ED_view3d_from_object(
- ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
- }
- /* grid draw as floor */
- if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
- /* use existing if exists, means multiple calls to smooth view
- * won't lose the original 'view' setting */
- rv3d->view = RV3D_VIEW_USER;
- }
-
- sms.time_allowed = (double)smooth_viewtx / 1000.0;
-
- /* If this is view rotation only we can decrease the time allowed by the angle between quats
- * this means small rotations won't lag. */
- if (sview->quat && !sview->ofs && !sview->dist) {
- /* scale the time allowed by the rotation */
- /* 180deg == 1.0 */
- sms.time_allowed *= (double)fabsf(angle_signed_normalized_qtqt(sms.dst.quat, sms.src.quat)) /
- M_PI;
- }
-
- /* ensure it shows correct */
- if (sms.to_camera) {
- /* use ortho if we move from an ortho view to an ortho camera */
- Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
- rv3d->persp = (((rv3d->is_persp == false) && (ob_camera_eval->type == OB_CAMERA) &&
- (((Camera *)ob_camera_eval->data)->type == CAM_ORTHO)) ?
- RV3D_ORTHO :
- RV3D_PERSP);
- }
-
- rv3d->rflag |= RV3D_NAVIGATING;
-
- /* not essential but in some cases the caller will tag the area for redraw, and in that
- * case we can get a flicker of the 'org' user view but we want to see 'src' */
- view3d_smooth_view_state_restore(&sms.src, v3d, rv3d);
-
- /* keep track of running timer! */
- if (rv3d->sms == NULL) {
- rv3d->sms = MEM_mallocN(sizeof(struct SmoothView3DStore), "smoothview v3d");
- }
- *rv3d->sms = sms;
- if (rv3d->smooth_timer) {
- WM_event_remove_timer(wm, win, rv3d->smooth_timer);
- }
- /* #TIMER1 is hard-coded in key-map. */
- rv3d->smooth_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 100.0);
- }
- else {
- /* Animation is disabled, apply immediately. */
- if (sms.to_camera == false) {
- copy_v3_v3(rv3d->ofs, sms.dst.ofs);
- copy_qt_qt(rv3d->viewquat, sms.dst.quat);
- rv3d->dist = sms.dst.dist;
- v3d->lens = sms.dst.lens;
-
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- }
-
- if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_copy(area, region);
- }
-
- ED_region_tag_redraw(region);
-
- WM_event_add_mousemove(win);
- }
-}
-
-void ED_view3d_smooth_view(bContext *C,
- View3D *v3d,
- ARegion *region,
- const int smooth_viewtx,
- const struct V3D_SmoothParams *sview)
-{
- const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- ScrArea *area = CTX_wm_area(C);
-
- ED_view3d_smooth_view_ex(depsgraph, wm, win, area, v3d, region, smooth_viewtx, sview);
-}
-
-/* only meant for timer usage */
-static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *region, bool sync_boxview)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- RegionView3D *rv3d = region->regiondata;
- struct SmoothView3DStore *sms = rv3d->sms;
- float step, step_inv;
-
- if (sms->time_allowed != 0.0) {
- step = (float)((rv3d->smooth_timer->duration) / sms->time_allowed);
- }
- else {
- step = 1.0f;
- }
-
- /* end timer */
- if (step >= 1.0f) {
- wmWindow *win = CTX_wm_window(C);
-
- /* if we went to camera, store the original */
- if (sms->to_camera) {
- rv3d->persp = RV3D_CAMOB;
- view3d_smooth_view_state_restore(&sms->org, v3d, rv3d);
- }
- else {
- const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
-
- view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
-
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
- }
-
- if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
- rv3d->view = sms->org_view;
- }
-
- MEM_freeN(rv3d->sms);
- rv3d->sms = NULL;
-
- WM_event_remove_timer(wm, win, rv3d->smooth_timer);
- rv3d->smooth_timer = NULL;
- rv3d->rflag &= ~RV3D_NAVIGATING;
-
- /* Event handling won't know if a UI item has been moved under the pointer. */
- WM_event_add_mousemove(win);
- }
- else {
- /* ease in/out */
- step = (3.0f * step * step - 2.0f * step * step * step);
-
- step_inv = 1.0f - step;
-
- interp_qt_qtqt(rv3d->viewquat, sms->src.quat, sms->dst.quat, step);
-
- if (sms->use_dyn_ofs) {
- view3d_orbit_apply_dyn_ofs(
- rv3d->ofs, sms->src.ofs, sms->src.quat, rv3d->viewquat, sms->dyn_ofs);
- }
- else {
- interp_v3_v3v3(rv3d->ofs, sms->src.ofs, sms->dst.ofs, step);
- }
-
- rv3d->dist = sms->dst.dist * step + sms->src.dist * step_inv;
- v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv;
-
- const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
- if (ED_screen_animation_playing(wm)) {
- ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
- }
- }
-
- if (sync_boxview && (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW)) {
- view3d_boxview_copy(CTX_wm_area(C), region);
- }
-
- /* NOTE: this doesn't work right because the v3d->lens is now used in ortho mode r51636,
- * when switching camera in quad-view the other ortho views would zoom & reset.
- *
- * For now only redraw all regions when smooth-view finishes.
- */
- if (step >= 1.0f) {
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- }
- else {
- ED_region_tag_redraw(region);
- }
-}
-
-static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
-{
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *region = CTX_wm_region(C);
- RegionView3D *rv3d = region->regiondata;
-
- /* escape if not our timer */
- if (rv3d->smooth_timer == NULL || rv3d->smooth_timer != event->customdata) {
- return OPERATOR_PASS_THROUGH;
- }
-
- view3d_smoothview_apply(C, v3d, region, true);
-
- return OPERATOR_FINISHED;
-}
-
-void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *region)
-{
- RegionView3D *rv3d = region->regiondata;
-
- if (rv3d && rv3d->sms) {
- rv3d->sms->time_allowed = 0.0; /* force finishing */
- view3d_smoothview_apply(C, v3d, region, false);
-
- /* force update of view matrix so tools that run immediately after
- * can use them without redrawing first */
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ED_view3d_update_viewmat(depsgraph, scene, v3d, region, NULL, NULL, NULL, false);
- }
-}
-
-void VIEW3D_OT_smoothview(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Smooth View";
- ot->idname = "VIEW3D_OT_smoothview";
-
- /* api callbacks */
- ot->invoke = view3d_smoothview_invoke;
-
- /* flags */
- ot->flag = OPTYPE_INTERNAL;
-
- ot->poll = ED_operator_view3d_active;
-}
-
-/** \} */
+#include "view3d_navigate.h"
/* -------------------------------------------------------------------- */
/** \name Camera to View Operator
@@ -863,10 +485,10 @@ void view3d_opengl_select_cache_end(void)
struct DrawSelectLoopUserData {
uint pass;
uint hits;
- uint *buffer;
+ GPUSelectResult *buffer;
uint buffer_len;
const rcti *rect;
- char gpu_select_mode;
+ eGPUSelectMode gpu_select_mode;
};
static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
@@ -927,8 +549,8 @@ static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void
}
int view3d_opengl_select_ex(ViewContext *vc,
- uint *buffer,
- uint bufsize,
+ GPUSelectResult *buffer,
+ uint buffer_len,
const rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter,
@@ -950,7 +572,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
const bool use_nearest = (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST);
bool draw_surface = true;
- char gpu_select_mode;
+ eGPUSelectMode gpu_select_mode;
/* case not a box select */
if (input->xmin == input->xmax) {
@@ -981,6 +603,15 @@ int view3d_opengl_select_ex(ViewContext *vc,
}
}
+ /* Re-use cache (rect must be smaller than the cached)
+ * other context is assumed to be unchanged */
+ if (GPU_select_is_cached()) {
+ GPU_select_begin(buffer, buffer_len, &rect, gpu_select_mode, 0);
+ GPU_select_cache_load_id();
+ hits = GPU_select_end();
+ goto finally;
+ }
+
/* Important to use 'vc->obact', not 'OBACT(vc->view_layer)' below,
* so it will be NULL when hidden. */
struct {
@@ -1040,15 +671,6 @@ int view3d_opengl_select_ex(ViewContext *vc,
UI_Theme_Store(&theme_state);
UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
- /* Re-use cache (rect must be smaller than the cached)
- * other context is assumed to be unchanged */
- if (GPU_select_is_cached()) {
- GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
- GPU_select_cache_load_id();
- hits = GPU_select_end();
- goto finally;
- }
-
/* All of the queries need to be perform on the drawing context. */
DRW_opengl_context_enable();
@@ -1071,7 +693,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
.pass = 0,
.hits = 0,
.buffer = buffer,
- .buffer_len = bufsize,
+ .buffer_len = buffer_len,
.rect = &rect,
.gpu_select_mode = gpu_select_mode,
};
@@ -1101,7 +723,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
.pass = 0,
.hits = 0,
.buffer = buffer,
- .buffer_len = bufsize,
+ .buffer_len = buffer_len,
.rect = &rect,
.gpu_select_mode = gpu_select_mode,
};
@@ -1132,36 +754,36 @@ int view3d_opengl_select_ex(ViewContext *vc,
DRW_opengl_context_disable();
+ UI_Theme_Restore(&theme_state);
+
finally:
if (hits < 0) {
printf("Too many objects in select buffer\n"); /* XXX make error message */
}
- UI_Theme_Restore(&theme_state);
-
return hits;
}
int view3d_opengl_select(ViewContext *vc,
- uint *buffer,
- uint bufsize,
+ GPUSelectResult *buffer,
+ uint buffer_len,
const rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter)
{
- return view3d_opengl_select_ex(vc, buffer, bufsize, input, select_mode, select_filter, false);
+ return view3d_opengl_select_ex(vc, buffer, buffer_len, input, select_mode, select_filter, false);
}
int view3d_opengl_select_with_id_filter(ViewContext *vc,
- uint *buffer,
- uint bufsize,
+ GPUSelectResult *buffer,
+ const uint buffer_len,
const rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter,
uint select_id)
{
- int hits = view3d_opengl_select(vc, buffer, bufsize, input, select_mode, select_filter);
+ int hits = view3d_opengl_select(vc, buffer, buffer_len, input, select_mode, select_filter);
/* Selection sometimes uses -1 for an invalid selection ID, remove these as they
* interfere with detection of actual number of hits in the selection. */
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index 64a720322c1..09c53d7196c 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -125,9 +125,5 @@ set(LIB
bf_gpu
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_transform "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 642de550812..8d91f90ea29 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -580,11 +580,11 @@ typedef struct TransInfo {
/** Mouse side of the current frame, 'L', 'R' or 'B' */
char frame_side;
- /** copy from G.vd, prevents feedback. */
+ /** copy from #RegionView3D, prevents feedback. */
float viewmat[4][4];
/** and to make sure we don't have to. */
float viewinv[4][4];
- /** access G.vd from other space types. */
+ /** Access #RegionView3D from other space types. */
float persmat[4][4];
float persinv[4][4];
short persp;
diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h
index c40f3c28a79..90f78d4abf1 100644
--- a/source/blender/editors/transform/transform_convert.h
+++ b/source/blender/editors/transform/transform_convert.h
@@ -124,10 +124,8 @@ void special_aftertrans_update__actedit(bContext *C, TransInfo *t);
* Sets transform flags in the bones.
* Returns total number of bones with #BONE_TRANSFORM.
*/
-int transform_convert_pose_transflags_update(Object *ob,
- int mode,
- short around,
- bool has_translate_rotate[2]);
+void transform_convert_pose_transflags_update(Object *ob, int mode, short around);
+
/**
* When objects array is NULL, use 't->data_container' as is.
*/
diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c
index 5d0a3bd9dd1..04a8d462924 100644
--- a/source/blender/editors/transform/transform_convert_armature.c
+++ b/source/blender/editors/transform/transform_convert_armature.c
@@ -739,9 +739,43 @@ void createTransPose(TransInfo *t)
const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
- /* set flags and count total */
- tc->data_len = transform_convert_pose_transflags_update(
- ob, t->mode, t->around, has_translate_rotate);
+ /* Set flags. */
+ transform_convert_pose_transflags_update(ob, t->mode, t->around);
+
+ /* Now count, and check if we have autoIK or have to switch from translate to rotate. */
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ Bone *bone = pchan->bone;
+ if (!(bone->flag & BONE_TRANSFORM)) {
+ continue;
+ }
+
+ tc->data_len++;
+
+ if (has_translate_rotate != NULL) {
+ if (has_translate_rotate[0] && has_translate_rotate[1]) {
+ continue;
+ }
+
+ if (has_targetless_ik(pchan) == NULL) {
+ if (pchan->parent && (bone->flag & BONE_CONNECTED)) {
+ if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
+ has_translate_rotate[0] = true;
+ }
+ }
+ else {
+ if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC) {
+ has_translate_rotate[0] = true;
+ }
+ }
+ if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT) {
+ has_translate_rotate[1] = true;
+ }
+ }
+ else {
+ has_translate_rotate[0] = true;
+ }
+ }
+ }
if (tc->data_len == 0) {
continue;
@@ -1499,15 +1533,11 @@ static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
}
}
-int transform_convert_pose_transflags_update(Object *ob,
- const int mode,
- const short around,
- bool has_translate_rotate[2])
+void transform_convert_pose_transflags_update(Object *ob, const int mode, const short around)
{
bArmature *arm = ob->data;
bPoseChannel *pchan;
Bone *bone;
- int total = 0;
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
bone = pchan->bone;
@@ -1537,36 +1567,6 @@ int transform_convert_pose_transflags_update(Object *ob,
}
}
}
- /* now count, and check if we have autoIK or have to switch from translate to rotate */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
- if (bone->flag & BONE_TRANSFORM) {
- total++;
-
- if (has_translate_rotate != NULL) {
- if (has_targetless_ik(pchan) == NULL) {
- if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
- if (pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
- has_translate_rotate[0] = true;
- }
- }
- else {
- if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC) {
- has_translate_rotate[0] = true;
- }
- }
- if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT) {
- has_translate_rotate[1] = true;
- }
- }
- else {
- has_translate_rotate[0] = true;
- }
- }
- }
- }
-
- return total;
}
static short apply_targetless_ik(Object *ob)
@@ -1733,7 +1733,7 @@ void special_aftertrans_update__pose(bContext *C, TransInfo *t)
/* Set BONE_TRANSFORM flags for auto-key, gizmo draw might have changed them. */
if (!canceled && (t->mode != TFM_DUMMY)) {
- transform_convert_pose_transflags_update(ob, t->mode, t->around, NULL);
+ transform_convert_pose_transflags_update(ob, t->mode, t->around);
}
/* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 9bd55d78039..c0572478481 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -953,32 +953,25 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *ob_iter = objects[ob_index];
- const bool use_mat_local = (ob_iter != ob);
- bPoseChannel *pchan;
-
+ const bool use_mat_local = params->use_local_axis && (ob_iter != ob);
/* mislead counting bones... bah. We don't know the gizmo mode, could be mixed */
const int mode = TFM_ROTATION;
- const int totsel_iter = transform_convert_pose_transflags_update(
- ob_iter, mode, V3D_AROUND_CENTER_BOUNDS, NULL);
+ transform_convert_pose_transflags_update(ob_iter, mode, V3D_AROUND_CENTER_BOUNDS);
- if (totsel_iter) {
- float mat_local[4][4];
- if (params->use_local_axis) {
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, ob->imat, ob_iter->obmat);
- }
- }
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, ob->imat, ob_iter->obmat);
+ }
- /* use channels to get stats */
- for (pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
- 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, orient_index);
- }
+ /* Use channels to get stats. */
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ if (!(pchan->bone->flag & BONE_TRANSFORM)) {
+ continue;
}
- totsel += totsel_iter;
+ calc_tw_center_with_matrix(tbounds, pchan->pose_head, use_mat_local, mat_local);
+ protectflag_to_drawflags_pchan(rv3d, pchan, orient_index);
+ totsel++;
}
}
MEM_freeN(objects);
diff --git a/source/blender/editors/undo/CMakeLists.txt b/source/blender/editors/undo/CMakeLists.txt
index 0f4152c9128..6f659e383fe 100644
--- a/source/blender/editors/undo/CMakeLists.txt
+++ b/source/blender/editors/undo/CMakeLists.txt
@@ -46,8 +46,4 @@ set(LIB
bf_editor_physics
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_undo "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 90a09c87cc6..66cda0fc3f8 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -115,10 +115,6 @@ set(LIB
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
list(APPEND INC
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index 1c8a56e0608..a3b29f29354 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -52,9 +52,5 @@ set(LIB
bf_bmesh
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_editor_uvedit "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/freestyle/CMakeLists.txt b/source/blender/freestyle/CMakeLists.txt
index d16787714c9..948e68e52da 100644
--- a/source/blender/freestyle/CMakeLists.txt
+++ b/source/blender/freestyle/CMakeLists.txt
@@ -583,10 +583,6 @@ if(WITH_PYTHON_SAFETY)
add_definitions(-DWITH_PYTHON_SAFETY)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WIN32)
list(APPEND INC_SYS
${PTHREADS_INC}
diff --git a/source/blender/functions/FN_field.hh b/source/blender/functions/FN_field.hh
index e869927c33b..e42feac1644 100644
--- a/source/blender/functions/FN_field.hh
+++ b/source/blender/functions/FN_field.hh
@@ -87,8 +87,7 @@ class FieldNode {
public:
FieldNode(FieldNodeType node_type);
-
- virtual ~FieldNode() = default;
+ virtual ~FieldNode();
virtual const CPPType &output_cpp_type(int output_index) const = 0;
@@ -230,6 +229,7 @@ class FieldOperation : public FieldNode {
public:
FieldOperation(std::shared_ptr<const MultiFunction> function, Vector<GField> inputs = {});
FieldOperation(const MultiFunction &function, Vector<GField> inputs = {});
+ ~FieldOperation();
Span<GField> inputs() const;
const MultiFunction &multi_function() const;
@@ -259,6 +259,7 @@ class FieldInput : public FieldNode {
public:
FieldInput(const CPPType &type, std::string debug_name = "");
+ ~FieldInput();
/**
* Get the value of this specific input based on the given context. The returned virtual array,
diff --git a/source/blender/functions/intern/cpp_types.cc b/source/blender/functions/intern/cpp_types.cc
index 0bbfbc8cb10..7f1eb8bc1a7 100644
--- a/source/blender/functions/intern/cpp_types.cc
+++ b/source/blender/functions/intern/cpp_types.cc
@@ -31,6 +31,7 @@ MAKE_CPP_TYPE(float3, blender::float3, CPPTypeFlags::BasicType)
MAKE_CPP_TYPE(float4x4, blender::float4x4, CPPTypeFlags::BasicType)
MAKE_CPP_TYPE(int32, int32_t, CPPTypeFlags::BasicType)
+MAKE_CPP_TYPE(int8, int8_t, CPPTypeFlags::BasicType)
MAKE_CPP_TYPE(uint32, uint32_t, CPPTypeFlags::BasicType)
MAKE_CPP_TYPE(uint8, uint8_t, CPPTypeFlags::BasicType)
@@ -44,6 +45,7 @@ MAKE_FIELD_CPP_TYPE(Float2Field, float2);
MAKE_FIELD_CPP_TYPE(Float3Field, float3);
MAKE_FIELD_CPP_TYPE(ColorGeometry4fField, blender::ColorGeometry4f);
MAKE_FIELD_CPP_TYPE(BoolField, bool);
+MAKE_FIELD_CPP_TYPE(Int8Field, int8_t);
MAKE_FIELD_CPP_TYPE(Int32Field, int32_t);
MAKE_FIELD_CPP_TYPE(StringField, std::string);
diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc
index d6b83c42294..fe3041b8602 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -571,6 +571,13 @@ bool IndexFieldInput::is_equal_to(const fn::FieldNode &other) const
}
/* --------------------------------------------------------------------
+ * FieldNode.
+ */
+
+/* Avoid generating the destructor in every translation unit. */
+FieldNode::~FieldNode() = default;
+
+/* --------------------------------------------------------------------
* FieldOperation.
*/
@@ -581,6 +588,9 @@ FieldOperation::FieldOperation(std::shared_ptr<const MultiFunction> function,
owned_function_ = std::move(function);
}
+/* Avoid generating the destructor in every translation unit. */
+FieldOperation::~FieldOperation() = default;
+
/**
* Returns the field inputs used by all the provided fields.
* This tries to reuse an existing #FieldInputs whenever possible to avoid copying it.
@@ -655,6 +665,9 @@ FieldInput::FieldInput(const CPPType &type, std::string debug_name)
field_inputs_ = std::move(field_inputs);
}
+/* Avoid generating the destructor in every translation unit. */
+FieldInput::~FieldInput() = default;
+
/* --------------------------------------------------------------------
* FieldConstant.
*/
diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt
index 5ee75619259..a3f468a20dc 100644
--- a/source/blender/gpencil_modifiers/CMakeLists.txt
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -92,10 +92,6 @@ set(SRC
set(LIB
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_gpencil_modifiers "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 2b6b28bd649..cffea5e9dcc 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -375,7 +375,7 @@ set(GLSL_SRC
shaders/gpu_shader_common_obinfos_lib.glsl
- intern/gpu_shader_shared_utils.h
+ GPU_shader_shared_utils.h
)
set(GLSL_C)
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
index c02af763311..3076058c075 100644
--- a/source/blender/gpu/GPU_select.h
+++ b/source/blender/gpu/GPU_select.h
@@ -32,7 +32,7 @@ extern "C" {
struct rcti;
/** Flags for mode of operation. */
-enum {
+typedef enum eGPUSelectMode {
GPU_SELECT_ALL = 1,
/* gpu_select_query */
GPU_SELECT_NEAREST_FIRST_PASS = 2,
@@ -40,13 +40,32 @@ enum {
/* gpu_select_pick */
GPU_SELECT_PICK_ALL = 4,
GPU_SELECT_PICK_NEAREST = 5,
-};
+} eGPUSelectMode;
+
+/**
+ * The result of calling #GPU_select_begin & #GPU_select_end.
+ */
+typedef struct GPUSelectResult {
+ /** The selection identifier matching the value passed in by #GPU_select_load_id. */
+ unsigned int id;
+ /**
+ * The nearest depth.
+ * - Only supported by picking modes (#GPU_SELECT_PICK_ALL and #GPU_SELECT_PICK_NEAREST)
+ * since occlusion quires don't provide a convenient way of accessing the depth-buffer.
+ * - OpenGL's `GL_SELECT` supported both near and far depths,
+ * this has not been included as Blender doesn't need this however support could be added.
+ */
+ unsigned int depth;
+} GPUSelectResult;
/**
* Initialize and provide buffer for results.
*/
-void GPU_select_begin(
- unsigned int *buffer, unsigned int bufsize, const struct rcti *input, char mode, int oldhits);
+void GPU_select_begin(GPUSelectResult *buffer,
+ unsigned int buffer_len,
+ const struct rcti *input,
+ eGPUSelectMode mode,
+ int oldhits);
/**
* Loads a new selection id and ends previous query, if any.
* In second pass of selection it also returns
@@ -79,8 +98,8 @@ void GPU_select_cache_end(void);
*
* Note that comparing depth as uint is fine.
*/
-const uint *GPU_select_buffer_near(const uint *buffer, int hits);
-uint GPU_select_buffer_remove_by_id(uint *buffer, int hits, uint select_id);
+const GPUSelectResult *GPU_select_buffer_near(const GPUSelectResult *buffer, int hits);
+uint GPU_select_buffer_remove_by_id(GPUSelectResult *buffer, int hits, uint select_id);
/**
* Part of the solution copied from `rect_subregion_stride_calc`.
*/
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 972758febd4..05c992274eb 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -71,6 +71,8 @@ GPUShader *GPU_shader_create_ex(const char *vertcode,
GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info);
GPUShader *GPU_shader_create_from_info_name(const char *info_name);
+const GPUShaderCreateInfo *GPU_shader_create_info_get(const char *info_name);
+
struct GPU_ShaderCreateFromArray_Params {
const char **vert, **geom, **frag, **defs;
};
diff --git a/source/blender/gpu/GPU_shader_shared.h b/source/blender/gpu/GPU_shader_shared.h
index eeca7ee6caa..636a8f53ba6 100644
--- a/source/blender/gpu/GPU_shader_shared.h
+++ b/source/blender/gpu/GPU_shader_shared.h
@@ -22,7 +22,7 @@
*/
#ifndef USE_GPU_SHADER_CREATE_INFO
-# include "intern/gpu_shader_shared_utils.h"
+# include "GPU_shader_shared_utils.h"
#endif
struct NodeLinkData {
diff --git a/source/blender/gpu/intern/gpu_shader_shared_utils.h b/source/blender/gpu/GPU_shader_shared_utils.h
index 0d283fb1e66..0d283fb1e66 100644
--- a/source/blender/gpu/intern/gpu_shader_shared_utils.h
+++ b/source/blender/gpu/GPU_shader_shared_utils.h
diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h
index 22cd7eab927..bd52b8321bb 100644
--- a/source/blender/gpu/GPU_state.h
+++ b/source/blender/gpu/GPU_state.h
@@ -37,11 +37,14 @@ ENUM_OPERATORS(eGPUWriteMask, GPU_WRITE_COLOR)
typedef enum eGPUBarrier {
GPU_BARRIER_NONE = 0,
- GPU_BARRIER_SHADER_IMAGE_ACCESS = (1 << 0),
- GPU_BARRIER_TEXTURE_FETCH = (1 << 1),
- GPU_BARRIER_SHADER_STORAGE = (1 << 2),
- GPU_BARRIER_VERTEX_ATTRIB_ARRAY = (1 << 3),
- GPU_BARRIER_ELEMENT_ARRAY = (1 << 4),
+ GPU_BARRIER_COMMAND = (1 << 0),
+ GPU_BARRIER_FRAMEBUFFER = (1 << 1),
+ GPU_BARRIER_SHADER_IMAGE_ACCESS = (1 << 2),
+ GPU_BARRIER_SHADER_STORAGE = (1 << 3),
+ GPU_BARRIER_TEXTURE_FETCH = (1 << 4),
+ GPU_BARRIER_TEXTURE_UPDATE = (1 << 5),
+ GPU_BARRIER_VERTEX_ATTRIB_ARRAY = (1 << 6),
+ GPU_BARRIER_ELEMENT_ARRAY = (1 << 7),
} eGPUBarrier;
ENUM_OPERATORS(eGPUBarrier, GPU_BARRIER_ELEMENT_ARRAY)
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 6fae4a13918..7812c7a7257 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -272,7 +272,8 @@ void *GPU_texture_read(GPUTexture *tex, eGPUDataFormat data_format, int miplvl);
* Fills the whole texture with the same data for all pixels.
* \warning Only work for 2D texture for now.
* \warning Only clears the mip 0 of the texture.
- * \param data_format: data format of the pixel data. \note The format is float for unorm textures.
+ * \param data_format: data format of the pixel data.
+ * \note The format is float for unorm textures.
* \param data: 1 pixel worth of data to fill the texture with.
*/
void GPU_texture_clear(GPUTexture *tex, eGPUDataFormat data_format, const void *data);
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 568462ec2a6..e1c6901470a 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -711,10 +711,10 @@ static char *code_generate_vertex(GPUNodeGraph *graph,
LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
const char *type_str = gpu_data_type_to_string(attr->gputype);
const char *prefix = attr_prefix_get(attr->type);
- /* XXX FIXME : see notes in mesh_render_data_create() */
- /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
+ /* XXX FIXME: see notes in mesh_render_data_create() */
+ /* NOTE: Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
if (attr->type == CD_ORCO) {
- /* OPTI : orco is computed from local positions, but only if no modifier is present. */
+ /* OPTI: orco is computed from local positions, but only if no modifier is present. */
BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl);
BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n");
}
diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc
index 5b1eac2e82f..28f5b8b02b0 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.cc
+++ b/source/blender/gpu/intern/gpu_framebuffer.cc
@@ -437,7 +437,7 @@ void GPU_framebuffer_blit(GPUFrameBuffer *gpufb_read,
fb_read->blit_to(blit_buffers, read_slot, fb_write, write_slot, 0, 0);
- /* FIXME(fclem) sRGB is not saved. */
+ /* FIXME(@fclem): sRGB is not saved. */
prev_fb->bind(true);
}
diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh
index a936e889e57..e7505258d2a 100644
--- a/source/blender/gpu/intern/gpu_framebuffer_private.hh
+++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh
@@ -43,8 +43,9 @@ typedef enum GPUAttachmentType : int {
GPU_FB_COLOR_ATTACHMENT3,
GPU_FB_COLOR_ATTACHMENT4,
GPU_FB_COLOR_ATTACHMENT5,
- /* Number of maximum output slots.
- * We support 6 outputs for now (usually we wouldn't need more to preserve fill rate). */
+ GPU_FB_COLOR_ATTACHMENT6,
+ GPU_FB_COLOR_ATTACHMENT7,
+ /* Number of maximum output slots. */
/* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to
* the maximum number of COLOR attachments specified by glDrawBuffers. */
GPU_FB_MAX_ATTACHMENT,
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 958aab65b57..afef0e70ccc 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -43,22 +43,22 @@
* \{ */
/* Internal algorithm used */
-enum {
+typedef enum eGPUSelectAlgo {
/** glBegin/EndQuery(GL_SAMPLES_PASSED... ), `gpu_select_query.c`
* Only sets 4th component (ID) correctly. */
ALGO_GL_QUERY = 1,
/** Read depth buffer for every drawing pass and extract depths, `gpu_select_pick.c`
* Only sets 4th component (ID) correctly. */
ALGO_GL_PICK = 2,
-};
+} eGPUSelectAlgo;
typedef struct GPUSelectState {
/* To ignore selection id calls when not initialized */
bool select_is_active;
/* mode of operation */
- char mode;
+ eGPUSelectMode mode;
/* internal algorithm for selection */
- char algorithm;
+ eGPUSelectAlgo algorithm;
/* allow GPU_select_begin/end without drawing */
bool use_cache;
/**
@@ -80,7 +80,11 @@ static GPUSelectState g_select_state = {0};
/** \name Public API
* \{ */
-void GPU_select_begin(uint *buffer, uint bufsize, const rcti *input, char mode, int oldhits)
+void GPU_select_begin(GPUSelectResult *buffer,
+ const uint buffer_len,
+ const rcti *input,
+ eGPUSelectMode mode,
+ int oldhits)
{
if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
/* In the case hits was '-1',
@@ -119,12 +123,12 @@ void GPU_select_begin(uint *buffer, uint bufsize, const rcti *input, char mode,
switch (g_select_state.algorithm) {
case ALGO_GL_QUERY: {
- gpu_select_query_begin((uint(*)[4])buffer, bufsize / 4, input, mode, oldhits);
+ gpu_select_query_begin(buffer, buffer_len, input, mode, oldhits);
break;
}
default: /* ALGO_GL_PICK */
{
- gpu_select_pick_begin((uint(*)[4])buffer, bufsize / 4, input, mode);
+ gpu_select_pick_begin(buffer, buffer_len, input, mode);
break;
}
}
@@ -219,35 +223,35 @@ bool GPU_select_is_cached(void)
/** \name Utilities
* \{ */
-const uint *GPU_select_buffer_near(const uint *buffer, int hits)
+const GPUSelectResult *GPU_select_buffer_near(const GPUSelectResult *buffer, int hits)
{
- const uint *buffer_near = NULL;
+ const GPUSelectResult *buffer_near = NULL;
uint depth_min = (uint)-1;
for (int i = 0; i < hits; i++) {
- if (buffer[1] < depth_min) {
- BLI_assert(buffer[3] != -1);
- depth_min = buffer[1];
+ if (buffer->depth < depth_min) {
+ BLI_assert(buffer->id != -1);
+ depth_min = buffer->depth;
buffer_near = buffer;
}
- buffer += 4;
+ buffer++;
}
return buffer_near;
}
-uint GPU_select_buffer_remove_by_id(uint *buffer, int hits, uint select_id)
+uint GPU_select_buffer_remove_by_id(GPUSelectResult *buffer, int hits, uint select_id)
{
- uint *buffer_src = buffer;
- uint *buffer_dst = buffer;
+ GPUSelectResult *buffer_src = buffer;
+ GPUSelectResult *buffer_dst = buffer;
int hits_final = 0;
for (int i = 0; i < hits; i++) {
- if (buffer_src[3] != select_id) {
+ if (buffer_src->id != select_id) {
if (buffer_dst != buffer_src) {
- memcpy(buffer_dst, buffer_src, sizeof(int[4]));
+ memcpy(buffer_dst, buffer_src, sizeof(GPUSelectResult));
}
- buffer_dst += 4;
+ buffer_dst++;
hits_final += 1;
}
- buffer_src += 4;
+ buffer_src++;
}
return hits_final;
}
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
index ddd3dfc6879..a5c0b2b1a14 100644
--- a/source/blender/gpu/intern/gpu_select_pick.c
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -55,15 +55,19 @@
/** \name #SubRectStride
* \{ */
-/* For looping over a sub-region of a rect, could be moved into 'rct.c'. */
+/** For looping over a sub-region of a #rcti, could be moved into 'rct.c'. */
typedef struct SubRectStride {
- uint start; /* start here */
- uint span; /* read these */
- uint span_len; /* len times (read span 'len' times). */
- uint skip; /* skip those */
+ /** Start here. */
+ uint start;
+ /** Read these. */
+ uint span;
+ /** `len` times (read span 'len' times). */
+ uint span_len;
+ /** Skip those. */
+ uint skip;
} SubRectStride;
-/* we may want to change back to float if uint isn't well supported */
+/** We may want to change back to float if `uint` isn't well supported. */
typedef uint depth_t;
/**
@@ -104,11 +108,11 @@ BLI_INLINE bool depth_is_filled(const depth_t *prev, const depth_t *curr)
/* -------------------------------------------------------------------- */
/** \name #DepthBufCache
*
- * Result of reading #glReadPixels,
+ * Result of reading #GPU_framebuffer_read_depth,
* use for both cache and non-cached storage.
* \{ */
-/** Store result of #glReadPixels. */
+/** Store result of #GPU_framebuffer_read_depth. */
typedef struct DepthBufCache {
struct DepthBufCache *next, *prev;
uint id;
@@ -174,7 +178,7 @@ static bool depth_buf_subrect_depth_any_filled(const DepthBufCache *rect_src,
const DepthBufCache *rect_dst,
const SubRectStride *sub_rect)
{
- /* same as above but different rect sizes */
+ /* Same as above but different rectangle sizes. */
const depth_t *prev = rect_src->buf + sub_rect->start;
const depth_t *curr = rect_dst->buf + sub_rect->start;
for (uint i = 0; i < sub_rect->span_len; i++) {
@@ -235,66 +239,68 @@ static int depth_cmp(const void *v1, const void *v2)
/** \name Main Selection Begin/End/Load API
* \{ */
-/* depth sorting */
+/** Depth sorting. */
typedef struct GPUPickState {
- /* cache on initialization */
- uint (*buffer)[4];
+ /** Cache on initialization. */
+ GPUSelectResult *buffer;
+ uint buffer_len;
+ /** Mode of this operation. */
+ eGPUSelectMode mode;
- /* Buffer size (stores number of integers, for actual size multiply by sizeof integer). */
- uint bufsize;
- /* mode of operation */
- char mode;
-
- /* OpenGL drawing, never use when (is_cached == true). */
+ /** GPU drawing, never use when `is_cached == true`. */
struct {
- /* The current depth, accumulated as we draw */
+ /** The current depth, accumulated while drawing. */
DepthBufCache *rect_depth;
- /* Scratch buffer, avoid allocs every time (when not caching) */
+ /** Scratch buffer, avoid allocations every time (when not caching). */
DepthBufCache *rect_depth_test;
- /* Pass to glReadPixels (x, y, w, h) */
+ /** Pass to `GPU_framebuffer_read_depth(x, y, w, h)`. */
int clip_readpixels[4];
- /* Set after first draw */
+ /** Set after first draw. */
bool is_init;
uint prev_id;
- } gl;
+ } gpu;
- /* src: data stored in 'cache' and 'gl',
- * dst: use when cached region is smaller (where src -> dst isn't 1:1) */
+ /**
+ * `src`: data stored in 'cache' and 'gpu',
+ * `dst`: use when cached region is smaller (where `src` -> `dst` isn't 1:1).
+ */
struct {
rcti clip_rect;
uint rect_len;
} src, dst;
- /* Store cache between `GPU_select_cache_begin/end` */
+ /** Store cache between `GPU_select_cache_begin/end` */
bool use_cache;
bool is_cached;
struct {
- /* Cleanup used for iterating over both source and destination buffers:
- * src.clip_rect -> dst.clip_rect */
+ /**
+ * Cleanup used for iterating over both source and destination buffers:
+ * `src.clip_rect` -> `dst.clip_rect`.
+ */
SubRectStride sub_rect;
- /* List of DepthBufCache, sized of 'src.clip_rect' */
+ /** List of #DepthBufCache, sized of 'src.clip_rect'. */
ListBase bufs;
} cache;
- /* Picking methods. */
+ /** Picking methods. */
union {
- /* GPU_SELECT_PICK_ALL */
+ /** #GPU_SELECT_PICK_ALL */
struct {
DepthID *hits;
uint hits_len;
uint hits_len_alloc;
} all;
- /* GPU_SELECT_PICK_NEAREST */
+ /** #GPU_SELECT_PICK_NEAREST */
struct {
uint *rect_id;
} nearest;
};
- /* Previous state to restore after drawing. */
+ /** Previous state to restore after drawing. */
int viewport[4];
int scissor[4];
eGPUWriteMask write_mask;
@@ -303,37 +309,44 @@ typedef struct GPUPickState {
static GPUPickState g_pick_state = {0};
-void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, char mode)
+void gpu_select_pick_begin(GPUSelectResult *buffer,
+ const uint buffer_len,
+ const rcti *input,
+ eGPUSelectMode mode)
{
GPUPickState *ps = &g_pick_state;
#ifdef DEBUG_PRINT
- printf("%s: mode=%d, use_cache=%d, is_cache=%d\n", __func__, mode, ps->use_cache, ps->is_cached);
+ printf("%s: mode=%d, use_cache=%d, is_cache=%d\n",
+ __func__,
+ (int)mode,
+ ps->use_cache,
+ ps->is_cached);
#endif
GPU_debug_group_begin("Selection Pick");
- ps->bufsize = bufsize;
ps->buffer = buffer;
+ ps->buffer_len = buffer_len;
ps->mode = mode;
const uint rect_len = (uint)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input));
ps->dst.clip_rect = *input;
ps->dst.rect_len = rect_len;
- /* Restrict OpenGL operations for when we don't have cache */
+ /* Avoids unnecessary GPU operations when cache is available and they are unnecessary. */
if (ps->is_cached == false) {
ps->write_mask = GPU_write_mask_get();
ps->depth_test = GPU_depth_test_get();
GPU_scissor_get(ps->scissor);
- /* disable writing to the framebuffer */
+ /* Disable writing to the frame-buffer. */
GPU_color_mask(false, false, false, false);
GPU_depth_mask(true);
- /* Always use #GL_LEQUAL even though GPU_SELECT_PICK_ALL always clears the buffer. This is
- * because individual objects themselves might have sections that overlap and we need these
- * to have the correct distance information. */
+ /* Always use #GPU_DEPTH_LESS_EQUAL even though #GPU_SELECT_PICK_ALL always clears the buffer.
+ * This is because individual objects themselves might have sections that overlap and we need
+ * these to have the correct distance information. */
GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
float viewport[4];
@@ -342,35 +355,35 @@ void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, c
ps->src.clip_rect = *input;
ps->src.rect_len = rect_len;
- ps->gl.clip_readpixels[0] = (int)viewport[0];
- ps->gl.clip_readpixels[1] = (int)viewport[1];
- ps->gl.clip_readpixels[2] = BLI_rcti_size_x(&ps->src.clip_rect);
- ps->gl.clip_readpixels[3] = BLI_rcti_size_y(&ps->src.clip_rect);
+ ps->gpu.clip_readpixels[0] = (int)viewport[0];
+ ps->gpu.clip_readpixels[1] = (int)viewport[1];
+ ps->gpu.clip_readpixels[2] = BLI_rcti_size_x(&ps->src.clip_rect);
+ ps->gpu.clip_readpixels[3] = BLI_rcti_size_y(&ps->src.clip_rect);
- GPU_viewport(UNPACK4(ps->gl.clip_readpixels));
+ GPU_viewport(UNPACK4(ps->gpu.clip_readpixels));
/* It's possible we don't want to clear depth buffer,
* so existing elements are masked by current z-buffer. */
GPU_clear_depth(1.0f);
/* scratch buffer (read new values here) */
- ps->gl.rect_depth_test = depth_buf_malloc(rect_len);
- ps->gl.rect_depth = depth_buf_malloc(rect_len);
+ ps->gpu.rect_depth_test = depth_buf_malloc(rect_len);
+ ps->gpu.rect_depth = depth_buf_malloc(rect_len);
- /* set initial 'far' value */
+ /* Set initial 'far' value. */
for (uint i = 0; i < rect_len; i++) {
- ps->gl.rect_depth->buf[i] = DEPTH_MAX;
+ ps->gpu.rect_depth->buf[i] = DEPTH_MAX;
}
- ps->gl.is_init = false;
- ps->gl.prev_id = 0;
+ ps->gpu.is_init = false;
+ ps->gpu.prev_id = 0;
}
else {
- /* Using cache (ps->is_cached == true) */
- /* src.clip_rect -> dst.clip_rect */
+ /* Using cache `ps->is_cached == true`. */
+ /* `src.clip_rect` -> `dst.clip_rect`. */
rect_subregion_stride_calc(&ps->src.clip_rect, &ps->dst.clip_rect, &ps->cache.sub_rect);
- BLI_assert(ps->gl.rect_depth == NULL);
- BLI_assert(ps->gl.rect_depth_test == NULL);
+ BLI_assert(ps->gpu.rect_depth == NULL);
+ BLI_assert(ps->gpu.rect_depth_test == NULL);
}
if (mode == GPU_SELECT_PICK_ALL) {
@@ -379,7 +392,7 @@ void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, c
ps->all.hits_len_alloc = ALLOC_DEPTHS;
}
else {
- /* Set to 0xff for SELECT_ID_NONE */
+ /* Set to 0xff for #SELECT_ID_NONE. */
ps->nearest.rect_id = MEM_mallocN(sizeof(uint) * ps->dst.rect_len, __func__);
memset(ps->nearest.rect_id, 0xff, sizeof(uint) * ps->dst.rect_len);
}
@@ -411,7 +424,7 @@ static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr)
}
}
else {
- /* same as above but different rect sizes */
+ /* Same as above but different rectangle sizes. */
const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start;
for (uint i = 0; i < ps->cache.sub_rect.span_len; i++) {
const depth_t *curr_end = curr + ps->cache.sub_rect.span;
@@ -424,7 +437,7 @@ static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr)
#undef EVAL_TEST
- /* ensure enough space */
+ /* Ensure enough space. */
if (UNLIKELY(ps->all.hits_len == ps->all.hits_len_alloc)) {
ps->all.hits_len_alloc += ALLOC_DEPTHS;
ps->all.hits = MEM_reallocN(ps->all.hits, ps->all.hits_len_alloc * sizeof(*ps->all.hits));
@@ -439,7 +452,7 @@ static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev,
{
GPUPickState *ps = &g_pick_state;
const uint id = rect_curr->id;
- /* keep track each pixels ID in 'nearest.rect_id' */
+ /* Keep track each pixels ID in `nearest.rect_id`. */
if (id != SELECT_ID_NONE) {
uint *id_ptr = ps->nearest.rect_id;
@@ -483,8 +496,8 @@ bool gpu_select_pick_load_id(uint id, bool end)
{
GPUPickState *ps = &g_pick_state;
- if (ps->gl.is_init) {
- if (id == ps->gl.prev_id && !end) {
+ if (ps->gpu.is_init) {
+ if (id == ps->gpu.prev_id && !end) {
/* No need to read if we are still drawing for the same id since
* all these depths will be merged / de-duplicated in the end. */
return true;
@@ -493,21 +506,21 @@ bool gpu_select_pick_load_id(uint id, bool end)
const uint rect_len = ps->src.rect_len;
GPUFrameBuffer *fb = GPU_framebuffer_active_get();
GPU_framebuffer_read_depth(
- fb, UNPACK4(ps->gl.clip_readpixels), GPU_DATA_UINT, ps->gl.rect_depth_test->buf);
+ fb, UNPACK4(ps->gpu.clip_readpixels), GPU_DATA_UINT, ps->gpu.rect_depth_test->buf);
/* Perform initial check since most cases the array remains unchanged. */
bool do_pass = false;
if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
- if (depth_buf_rect_depth_any(ps->gl.rect_depth_test, rect_len)) {
- ps->gl.rect_depth_test->id = ps->gl.prev_id;
- gpu_select_load_id_pass_all(ps->gl.rect_depth_test);
+ if (depth_buf_rect_depth_any(ps->gpu.rect_depth_test, rect_len)) {
+ ps->gpu.rect_depth_test->id = ps->gpu.prev_id;
+ gpu_select_load_id_pass_all(ps->gpu.rect_depth_test);
do_pass = true;
}
}
else {
- if (depth_buf_rect_depth_any_filled(ps->gl.rect_depth, ps->gl.rect_depth_test, rect_len)) {
- ps->gl.rect_depth_test->id = ps->gl.prev_id;
- gpu_select_load_id_pass_nearest(ps->gl.rect_depth, ps->gl.rect_depth_test);
+ if (depth_buf_rect_depth_any_filled(ps->gpu.rect_depth, ps->gpu.rect_depth_test, rect_len)) {
+ ps->gpu.rect_depth_test->id = ps->gpu.prev_id;
+ gpu_select_load_id_pass_nearest(ps->gpu.rect_depth, ps->gpu.rect_depth_test);
do_pass = true;
}
}
@@ -515,11 +528,11 @@ bool gpu_select_pick_load_id(uint id, bool end)
if (do_pass) {
/* Store depth in cache */
if (ps->use_cache) {
- BLI_addtail(&ps->cache.bufs, ps->gl.rect_depth);
- ps->gl.rect_depth = depth_buf_malloc(ps->src.rect_len);
+ BLI_addtail(&ps->cache.bufs, ps->gpu.rect_depth);
+ ps->gpu.rect_depth = depth_buf_malloc(ps->src.rect_len);
}
- SWAP(DepthBufCache *, ps->gl.rect_depth, ps->gl.rect_depth_test);
+ SWAP(DepthBufCache *, ps->gpu.rect_depth, ps->gpu.rect_depth_test);
if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
/* (fclem) This is to be on the safe side. I don't know if this is required. */
@@ -533,8 +546,8 @@ bool gpu_select_pick_load_id(uint id, bool end)
}
}
- ps->gl.is_init = true;
- ps->gl.prev_id = id;
+ ps->gpu.is_init = true;
+ ps->gpu.prev_id = id;
return true;
}
@@ -548,9 +561,9 @@ uint gpu_select_pick_end(void)
#endif
if (ps->is_cached == false) {
- if (ps->gl.is_init) {
+ if (ps->gpu.is_init) {
/* force finishing last pass */
- gpu_select_pick_load_id(ps->gl.prev_id, true);
+ gpu_select_pick_load_id(ps->gpu.prev_id, true);
}
GPU_write_mask(ps->write_mask);
GPU_depth_test(ps->depth_test);
@@ -559,39 +572,39 @@ uint gpu_select_pick_end(void)
GPU_debug_group_end();
- /* assign but never free directly since it may be in cache */
+ /* Assign but never free directly since it may be in cache. */
DepthBufCache *rect_depth_final;
/* Store depth in cache */
if (ps->use_cache && !ps->is_cached) {
- BLI_addtail(&ps->cache.bufs, ps->gl.rect_depth);
- ps->gl.rect_depth = NULL;
+ BLI_addtail(&ps->cache.bufs, ps->gpu.rect_depth);
+ ps->gpu.rect_depth = NULL;
rect_depth_final = ps->cache.bufs.last;
}
else if (ps->is_cached) {
rect_depth_final = ps->cache.bufs.last;
}
else {
- /* common case, no cache */
- rect_depth_final = ps->gl.rect_depth;
+ /* Common case, no cache. */
+ rect_depth_final = ps->gpu.rect_depth;
}
- uint maxhits = g_pick_state.bufsize;
+ uint maxhits = g_pick_state.buffer_len;
DepthID *depth_data;
uint depth_data_len = 0;
if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
depth_data = ps->all.hits;
depth_data_len = ps->all.hits_len;
- /* move ownership */
+ /* Move ownership. */
ps->all.hits = NULL;
ps->all.hits_len = 0;
ps->all.hits_len_alloc = 0;
}
else {
- /* GPU_SELECT_PICK_NEAREST */
+ /* #GPU_SELECT_PICK_NEAREST */
- /* Over alloc (unlikely we have as many depths as pixels) */
+ /* Over allocate (unlikely we have as many depths as pixels). */
uint depth_data_len_first_pass = 0;
depth_data = MEM_mallocN(ps->dst.rect_len * sizeof(*depth_data), __func__);
@@ -624,7 +637,7 @@ uint gpu_select_pick_end(void)
}
}
else {
- /* same as above but different rect sizes */
+ /* Same as above but different rectangle sizes. */
uint i_src = ps->cache.sub_rect.start, i_dst = 0;
for (uint j = 0; j < ps->cache.sub_rect.span_len; j++) {
const uint i_src_end = i_src + ps->cache.sub_rect.span;
@@ -640,7 +653,7 @@ uint gpu_select_pick_end(void)
qsort(depth_data, depth_data_len_first_pass, sizeof(DepthID), depth_id_cmp);
- /* Sort by ID's then keep the best depth for each ID */
+ /* Sort by ID's then keep the best depth for each ID. */
depth_data_len = 0;
{
DepthID *depth_last = NULL;
@@ -657,25 +670,22 @@ uint gpu_select_pick_end(void)
}
/* Finally sort each unique (id, depth) pair by depth
- * so the final hit-list is sorted by depth (nearest first) */
+ * so the final hit-list is sorted by depth (nearest first). */
uint hits = 0;
if (depth_data_len > maxhits) {
hits = (uint)-1;
}
else {
- /* leave sorting up to the caller */
+ /* Leave sorting up to the caller. */
qsort(depth_data, depth_data_len, sizeof(DepthID), depth_cmp);
for (uint i = 0; i < depth_data_len; i++) {
#ifdef DEBUG_PRINT
printf(" hit: %u: depth %u\n", depth_data[i].id, depth_data[i].depth);
#endif
- /* first 3 are dummy values */
- g_pick_state.buffer[hits][0] = 1;
- g_pick_state.buffer[hits][1] = depth_data[i].depth;
- g_pick_state.buffer[hits][2] = 0x0; /* z-far is currently never used. */
- g_pick_state.buffer[hits][3] = depth_data[i].id;
+ g_pick_state.buffer[hits].depth = depth_data[i].depth;
+ g_pick_state.buffer[hits].id = depth_data[i].id;
hits++;
}
BLI_assert(hits < maxhits);
@@ -683,8 +693,8 @@ uint gpu_select_pick_end(void)
MEM_freeN(depth_data);
- MEM_SAFE_FREE(ps->gl.rect_depth);
- MEM_SAFE_FREE(ps->gl.rect_depth_test);
+ MEM_SAFE_FREE(ps->gpu.rect_depth);
+ MEM_SAFE_FREE(ps->gpu.rect_depth_test);
if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
/* 'hits' already freed as 'depth_data' */
@@ -744,8 +754,8 @@ void gpu_select_pick_cache_load_id(void)
#endif
LISTBASE_FOREACH (DepthBufCache *, rect_depth, &ps->cache.bufs) {
if (rect_depth->next != NULL) {
- /* we know the buffers differ, but this sub-region may not.
- * double check before adding an id-pass */
+ /* We know the buffers differ, but this sub-region may not.
+ * Double check before adding an id-pass. */
if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
if (depth_buf_subrect_depth_any(rect_depth->next, &ps->cache.sub_rect)) {
gpu_select_load_id_pass_all(rect_depth->next);
diff --git a/source/blender/gpu/intern/gpu_select_private.h b/source/blender/gpu/intern/gpu_select_private.h
index e5a84a037a6..0ec9f083c07 100644
--- a/source/blender/gpu/intern/gpu_select_private.h
+++ b/source/blender/gpu/intern/gpu_select_private.h
@@ -31,7 +31,10 @@ extern "C" {
/* gpu_select_pick */
-void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, char mode);
+void gpu_select_pick_begin(GPUSelectResult *buffer,
+ uint buffer_len,
+ const rcti *input,
+ eGPUSelectMode mode);
bool gpu_select_pick_load_id(uint id, bool end);
uint gpu_select_pick_end(void);
@@ -46,7 +49,7 @@ void gpu_select_pick_cache_load_id(void);
/* gpu_select_sample_query */
void gpu_select_query_begin(
- uint (*buffer)[4], uint bufsize, const rcti *input, char mode, int oldhits);
+ GPUSelectResult *buffer, uint buffer_len, const rcti *input, eGPUSelectMode mode, int oldhits);
bool gpu_select_query_load_id(uint id);
uint gpu_select_query_end(void);
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.cc b/source/blender/gpu/intern/gpu_select_sample_query.cc
index a430d4a9d62..7559358aaca 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.cc
+++ b/source/blender/gpu/intern/gpu_select_sample_query.cc
@@ -48,22 +48,22 @@ using namespace blender;
using namespace blender::gpu;
struct GPUSelectQueryState {
- /* Tracks whether a query has been issued so that gpu_load_id can end the previous one. */
+ /** Tracks whether a query has been issued so that gpu_load_id can end the previous one. */
bool query_issued;
- /* GPU queries abstraction. Contains an array of queries. */
+ /** GPU queries abstraction. Contains an array of queries. */
QueryPool *queries;
- /* Array holding the id corresponding id to each query. */
+ /** Array holding the id corresponding id to each query. */
Vector<uint> *ids;
- /* Cache on initialization. */
- uint (*buffer)[4];
- /* Buffer size (stores number of integers, for actual size multiply by `sizeof(int)`). */
- uint bufsize;
- /* Mode of operation. */
- char mode;
+ /** Cache on initialization. */
+ GPUSelectResult *buffer;
+ /** The capacity of the `buffer` array. */
+ uint buffer_len;
+ /** Mode of operation. */
+ eGPUSelectMode mode;
uint index;
int oldhits;
- /* Previous state to restore after drawing. */
+ /** Previous state to restore after drawing. */
int viewport[4];
int scissor[4];
eGPUWriteMask write_mask;
@@ -72,14 +72,17 @@ struct GPUSelectQueryState {
static GPUSelectQueryState g_query_state = {false};
-void gpu_select_query_begin(
- uint (*buffer)[4], uint bufsize, const rcti *input, char mode, int oldhits)
+void gpu_select_query_begin(GPUSelectResult *buffer,
+ uint buffer_len,
+ const rcti *input,
+ const eGPUSelectMode mode,
+ int oldhits)
{
GPU_debug_group_begin("Selection Queries");
g_query_state.query_issued = false;
- g_query_state.bufsize = bufsize;
g_query_state.buffer = buffer;
+ g_query_state.buffer_len = buffer_len;
g_query_state.mode = mode;
g_query_state.index = 0;
g_query_state.oldhits = oldhits;
@@ -111,7 +114,7 @@ void gpu_select_query_begin(
/* occlusion queries operates on fragments that pass tests and since we are interested on all
* objects in the view frustum independently of their order, we need to disable the depth test */
if (mode == GPU_SELECT_ALL) {
- /* glQueries on Windows+Intel drivers only works with depth testing turned on.
+ /* #glQueries on Windows+Intel drivers only works with depth testing turned on.
* See T62947 for details */
GPU_depth_test(GPU_DEPTH_ALWAYS);
GPU_depth_mask(true);
@@ -138,10 +141,11 @@ bool gpu_select_query_load_id(uint id)
g_query_state.query_issued = true;
if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) {
- /* Second pass should never run if first pass fails, can read past 'bufsize' in this case. */
+ /* Second pass should never run if first pass fails,
+ * can read past `buffer_len` in this case. */
BLI_assert(g_query_state.oldhits != -1);
if (g_query_state.index < g_query_state.oldhits) {
- if (g_query_state.buffer[g_query_state.index][3] == id) {
+ if (g_query_state.buffer[g_query_state.index].id == id) {
g_query_state.index++;
return true;
}
@@ -154,7 +158,7 @@ bool gpu_select_query_load_id(uint id)
uint gpu_select_query_end()
{
uint hits = 0;
- const uint maxhits = g_query_state.bufsize;
+ const uint maxhits = g_query_state.buffer_len;
if (g_query_state.query_issued) {
g_query_state.queries->end_query();
@@ -168,10 +172,8 @@ uint gpu_select_query_end()
if (result[i] != 0) {
if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
if (hits < maxhits) {
- g_query_state.buffer[hits][0] = 1;
- g_query_state.buffer[hits][1] = 0xFFFF;
- g_query_state.buffer[hits][2] = 0xFFFF;
- g_query_state.buffer[hits][3] = ids[i];
+ g_query_state.buffer[hits].depth = 0xFFFF;
+ g_query_state.buffer[hits].id = ids[i];
hits++;
}
else {
@@ -183,9 +185,8 @@ uint gpu_select_query_end()
int j;
/* search in buffer and make selected object first */
for (j = 0; j < g_query_state.oldhits; j++) {
- if (g_query_state.buffer[j][3] == ids[i]) {
- g_query_state.buffer[j][1] = 0;
- g_query_state.buffer[j][2] = 0;
+ if (g_query_state.buffer[j].id == ids[i]) {
+ g_query_state.buffer[j].depth = 0;
}
}
break;
diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc
index 2d6b1d171b0..7db34917ad7 100644
--- a/source/blender/gpu/intern/gpu_shader.cc
+++ b/source/blender/gpu/intern/gpu_shader.cc
@@ -250,6 +250,11 @@ GPUShader *GPU_shader_create_compute(const char *computecode,
shname);
}
+const GPUShaderCreateInfo *GPU_shader_create_info_get(const char *info_name)
+{
+ return gpu_shader_create_info_get(info_name);
+}
+
GPUShader *GPU_shader_create_from_info_name(const char *info_name)
{
using namespace blender::gpu::shader;
@@ -299,22 +304,23 @@ GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
std::string defines = shader->defines_declare(info);
std::string resources = shader->resources_declare(info);
- char *shader_shared_utils = nullptr;
defines += "#define USE_GPU_SHADER_CREATE_INFO\n";
- Vector<char *> typedefs;
- for (auto filename : info.typedef_sources_) {
- typedefs.append(gpu_shader_dependency_get_source(filename.c_str()));
+ Vector<const char *> typedefs;
+ if (!info.typedef_sources_.is_empty() || !info.typedef_source_generated.empty()) {
+ typedefs.append(gpu_shader_dependency_get_source("GPU_shader_shared_utils.h").c_str());
+ }
+ if (!info.typedef_source_generated.empty()) {
+ typedefs.append(info.typedef_source_generated.c_str());
}
- if (!typedefs.is_empty()) {
- shader_shared_utils = gpu_shader_dependency_get_source("gpu_shader_shared_utils.h");
+ for (auto filename : info.typedef_sources_) {
+ typedefs.append(gpu_shader_dependency_get_source(filename).c_str());
}
if (!info.vertex_source_.is_empty()) {
- uint32_t builtins = 0;
+ auto code = gpu_shader_dependency_get_resolved_source(info.vertex_source_);
std::string interface = shader->vertex_interface_declare(info);
- char *code = gpu_shader_dependency_get_resolved_source(info.vertex_source_.c_str(), &builtins);
Vector<const char *> sources;
standard_defines(sources);
@@ -323,26 +329,19 @@ GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
sources.append("#define USE_GEOMETRY_SHADER\n");
}
sources.append(defines.c_str());
- if (!typedefs.is_empty()) {
- sources.append(shader_shared_utils);
- }
- for (auto *types : typedefs) {
- sources.append(types);
- }
+ sources.extend(typedefs);
sources.append(resources.c_str());
sources.append(interface.c_str());
- sources.append(code);
+ sources.extend(code);
+ sources.extend(info.dependencies_generated);
+ sources.append(info.vertex_source_generated.c_str());
shader->vertex_shader_from_glsl(sources);
-
- free(code);
}
if (!info.fragment_source_.is_empty()) {
- uint32_t builtins = 0;
+ auto code = gpu_shader_dependency_get_resolved_source(info.fragment_source_);
std::string interface = shader->fragment_interface_declare(info);
- char *code = gpu_shader_dependency_get_resolved_source(info.fragment_source_.c_str(),
- &builtins);
Vector<const char *> sources;
standard_defines(sources);
@@ -351,79 +350,48 @@ GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
sources.append("#define USE_GEOMETRY_SHADER\n");
}
sources.append(defines.c_str());
- if (!typedefs.is_empty()) {
- sources.append(shader_shared_utils);
- }
- for (auto *types : typedefs) {
- sources.append(types);
- }
+ sources.extend(typedefs);
sources.append(resources.c_str());
sources.append(interface.c_str());
- sources.append(code);
+ sources.extend(code);
+ sources.extend(info.dependencies_generated);
+ sources.append(info.fragment_source_generated.c_str());
shader->fragment_shader_from_glsl(sources);
-
- free(code);
}
if (!info.geometry_source_.is_empty()) {
- uint32_t builtins = 0;
- std::string interface = shader->geometry_interface_declare(info);
+ auto code = gpu_shader_dependency_get_resolved_source(info.geometry_source_);
std::string layout = shader->geometry_layout_declare(info);
- char *code = gpu_shader_dependency_get_resolved_source(info.geometry_source_.c_str(),
- &builtins);
+ std::string interface = shader->geometry_interface_declare(info);
Vector<const char *> sources;
standard_defines(sources);
sources.append("#define GPU_GEOMETRY_SHADER\n");
sources.append(defines.c_str());
- if (!typedefs.is_empty()) {
- sources.append(shader_shared_utils);
- }
- for (auto *types : typedefs) {
- sources.append(types);
- }
+ sources.extend(typedefs);
sources.append(resources.c_str());
sources.append(layout.c_str());
sources.append(interface.c_str());
- sources.append(code);
+ sources.extend(code);
shader->geometry_shader_from_glsl(sources);
-
- free(code);
}
if (!info.compute_source_.is_empty()) {
- uint32_t builtins = 0;
- char *code = gpu_shader_dependency_get_resolved_source(info.compute_source_.c_str(),
- &builtins);
+ auto code = gpu_shader_dependency_get_resolved_source(info.compute_source_);
std::string layout = shader->compute_layout_declare(info);
Vector<const char *> sources;
standard_defines(sources);
sources.append("#define GPU_COMPUTE_SHADER\n");
sources.append(defines.c_str());
- if (!typedefs.is_empty()) {
- sources.append(shader_shared_utils);
- }
- for (auto *types : typedefs) {
- sources.append(types);
- }
+ sources.extend(typedefs);
sources.append(resources.c_str());
sources.append(layout.c_str());
- sources.append(code);
+ sources.extend(code);
shader->compute_shader_from_glsl(sources);
-
- free(code);
- }
-
- for (auto *types : typedefs) {
- free(types);
- }
-
- if (shader_shared_utils) {
- free(shader_shared_utils);
}
if (!shader->finalize(&info)) {
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.cc b/source/blender/gpu/intern/gpu_shader_create_info.cc
index 492b247e192..4c306cf64ce 100644
--- a/source/blender/gpu/intern/gpu_shader_create_info.cc
+++ b/source/blender/gpu/intern/gpu_shader_create_info.cc
@@ -34,6 +34,7 @@
#include "gpu_shader_create_info.hh"
#include "gpu_shader_create_info_private.hh"
+#include "gpu_shader_dependency_private.h"
#include "gpu_shader_private.hh"
#undef GPU_SHADER_INTERFACE_INFO
@@ -61,11 +62,6 @@ void ShaderCreateInfo::finalize()
/* Recursive. */
const_cast<ShaderCreateInfo &>(info).finalize();
-#if 0 /* Enabled for debugging merging. TODO(fclem) exception handling and error reporting in \
- console. */
- std::cout << "Merging : " << info_name << " > " << name_ << std::endl;
-#endif
-
interface_names_size_ += info.interface_names_size_;
vertex_inputs_.extend(info.vertex_inputs_);
@@ -82,37 +78,72 @@ void ShaderCreateInfo::finalize()
validate(info);
+ auto assert_no_overlap = [&](const bool test, const StringRefNull error) {
+ if (!test) {
+ std::cout << name_ << ": Validation failed while merging " << info.name_ << " : ";
+ std::cout << error << std::endl;
+ BLI_assert(0);
+ }
+ };
+
if (info.compute_layout_.local_size_x != -1) {
- compute_layout_.local_size_x = info.compute_layout_.local_size_x;
- compute_layout_.local_size_y = info.compute_layout_.local_size_y;
- compute_layout_.local_size_z = info.compute_layout_.local_size_z;
+ assert_no_overlap(compute_layout_.local_size_x == -1, "Compute layout already defined");
+ compute_layout_ = info.compute_layout_;
}
if (!info.vertex_source_.is_empty()) {
- BLI_assert(vertex_source_.is_empty());
+ assert_no_overlap(vertex_source_.is_empty(), "Vertex source already existing");
vertex_source_ = info.vertex_source_;
}
if (!info.geometry_source_.is_empty()) {
- BLI_assert(geometry_source_.is_empty());
+ assert_no_overlap(geometry_source_.is_empty(), "Geometry source already existing");
geometry_source_ = info.geometry_source_;
geometry_layout_ = info.geometry_layout_;
}
if (!info.fragment_source_.is_empty()) {
- BLI_assert(fragment_source_.is_empty());
+ assert_no_overlap(fragment_source_.is_empty(), "Fragment source already existing");
fragment_source_ = info.fragment_source_;
}
if (!info.compute_source_.is_empty()) {
- BLI_assert(compute_source_.is_empty());
+ assert_no_overlap(compute_source_.is_empty(), "Compute source already existing");
compute_source_ = info.compute_source_;
}
do_static_compilation_ = do_static_compilation_ || info.do_static_compilation_;
}
+
+ if (auto_resource_location_) {
+ int images = 0, samplers = 0, ubos = 0, ssbos = 0;
+
+ auto set_resource_slot = [&](Resource &res) {
+ switch (res.bind_type) {
+ case Resource::BindType::UNIFORM_BUFFER:
+ res.slot = ubos++;
+ break;
+ case Resource::BindType::STORAGE_BUFFER:
+ res.slot = ssbos++;
+ break;
+ case Resource::BindType::SAMPLER:
+ res.slot = samplers++;
+ break;
+ case Resource::BindType::IMAGE:
+ res.slot = images++;
+ break;
+ }
+ };
+
+ for (auto &res : batch_resources_) {
+ set_resource_slot(res);
+ }
+ for (auto &res : pass_resources_) {
+ set_resource_slot(res);
+ }
+ }
}
void ShaderCreateInfo::validate(const ShaderCreateInfo &other_info)
{
- {
+ if (!auto_resource_location_) {
/* Check same bind-points usage in OGL. */
Set<int> images, samplers, ubos, ssbos;
@@ -132,26 +163,26 @@ void ShaderCreateInfo::validate(const ShaderCreateInfo &other_info)
};
auto print_error_msg = [&](const Resource &res) {
- std::cerr << name_ << ": Validation failed : Overlapping ";
+ std::cout << name_ << ": Validation failed : Overlapping ";
switch (res.bind_type) {
case Resource::BindType::UNIFORM_BUFFER:
- std::cerr << "Uniform Buffer " << res.uniformbuf.name;
+ std::cout << "Uniform Buffer " << res.uniformbuf.name;
break;
case Resource::BindType::STORAGE_BUFFER:
- std::cerr << "Storage Buffer " << res.storagebuf.name;
+ std::cout << "Storage Buffer " << res.storagebuf.name;
break;
case Resource::BindType::SAMPLER:
- std::cerr << "Sampler " << res.sampler.name;
+ std::cout << "Sampler " << res.sampler.name;
break;
case Resource::BindType::IMAGE:
- std::cerr << "Image " << res.image.name;
+ std::cout << "Image " << res.image.name;
break;
default:
- std::cerr << "Unknown Type";
+ std::cout << "Unknown Type";
break;
}
- std::cerr << " (" << res.slot << ") while merging " << other_info.name_ << std::endl;
+ std::cout << " (" << res.slot << ") while merging " << other_info.name_ << std::endl;
};
for (auto &res : batch_resources_) {
@@ -167,7 +198,7 @@ void ShaderCreateInfo::validate(const ShaderCreateInfo &other_info)
}
}
{
- /* TODO(fclem) Push constant validation. */
+ /* TODO(@fclem): Push constant validation. */
}
}
@@ -209,6 +240,15 @@ void gpu_shader_create_info_init()
draw_modelmat = draw_modelmat_legacy;
}
+ for (ShaderCreateInfo *info : g_create_infos->values()) {
+ if (info->do_static_compilation_) {
+ info->builtins_ |= gpu_shader_dependency_get_builtins(info->vertex_source_);
+ info->builtins_ |= gpu_shader_dependency_get_builtins(info->fragment_source_);
+ info->builtins_ |= gpu_shader_dependency_get_builtins(info->geometry_source_);
+ info->builtins_ |= gpu_shader_dependency_get_builtins(info->compute_source_);
+ }
+ }
+
/* TEST */
// gpu_shader_create_info_compile_all();
}
@@ -302,6 +342,7 @@ const GPUShaderCreateInfo *gpu_shader_create_info_get(const char *info_name)
{
if (g_create_infos->contains(info_name) == false) {
printf("Error: Cannot find shader create info named \"%s\"\n", info_name);
+ return nullptr;
}
ShaderCreateInfo *info = g_create_infos->lookup(info_name);
return reinterpret_cast<const GPUShaderCreateInfo *>(info);
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh
index 63c6e94f4c8..ee5a79220b9 100644
--- a/source/blender/gpu/intern/gpu_shader_create_info.hh
+++ b/source/blender/gpu/intern/gpu_shader_create_info.hh
@@ -30,8 +30,11 @@
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
+#include "GPU_material.h"
#include "GPU_texture.h"
+#include <iostream>
+
namespace blender::gpu::shader {
#ifndef GPU_SHADER_CREATE_INFO
@@ -62,7 +65,61 @@ enum class Type {
BOOL,
};
+/* All of these functions is a bit out of place */
+static inline Type to_type(const eGPUType type)
+{
+ switch (type) {
+ case GPU_FLOAT:
+ return Type::FLOAT;
+ case GPU_VEC2:
+ return Type::VEC2;
+ case GPU_VEC3:
+ return Type::VEC3;
+ case GPU_VEC4:
+ return Type::VEC4;
+ case GPU_MAT3:
+ return Type::MAT3;
+ case GPU_MAT4:
+ return Type::MAT4;
+ default:
+ BLI_assert_msg(0, "Error: Cannot convert eGPUType to shader::Type.");
+ return Type::FLOAT;
+ }
+}
+
+static inline std::ostream &operator<<(std::ostream &stream, const Type type)
+{
+ switch (type) {
+ case Type::FLOAT:
+ return stream << "float";
+ case Type::VEC2:
+ return stream << "vec2";
+ case Type::VEC3:
+ return stream << "vec3";
+ case Type::VEC4:
+ return stream << "vec4";
+ case Type::MAT3:
+ return stream << "mat3";
+ case Type::MAT4:
+ return stream << "mat4";
+ default:
+ BLI_assert(0);
+ return stream;
+ }
+}
+
+static inline std::ostream &operator<<(std::ostream &stream, const eGPUType type)
+{
+ switch (type) {
+ case GPU_CLOSURE:
+ return stream << "Closure";
+ default:
+ return stream << to_type(type);
+ }
+}
+
enum class BuiltinBits {
+ NONE = 0,
/**
* Allow getting barycentric coordinates inside the fragment shader.
* \note Emulated on OpenGL.
@@ -72,6 +129,10 @@ enum class BuiltinBits {
FRONT_FACING = (1 << 4),
GLOBAL_INVOCATION_ID = (1 << 5),
INSTANCE_ID = (1 << 6),
+ /**
+ * Allow setting the target layer when the output is a layered framebuffer.
+ * \note Emulated through geometry shader on older hardware.
+ */
LAYER = (1 << 7),
LOCAL_INVOCATION_ID = (1 << 8),
LOCAL_INVOCATION_INDEX = (1 << 9),
@@ -125,10 +186,13 @@ enum class ImageType {
/* Storage qualifiers. */
enum class Qualifier {
- RESTRICT = (1 << 0),
- READ_ONLY = (1 << 1),
- WRITE_ONLY = (1 << 2),
- QUALIFIER_MAX = (WRITE_ONLY << 1) - 1,
+ /** Restrict flag is set by default. Unless specified otherwise. */
+ NO_RESTRICT = (1 << 0),
+ READ = (1 << 1),
+ WRITE = (1 << 2),
+ /** Shorthand version of combined flags. */
+ READ_WRITE = READ | WRITE,
+ QUALIFIER_MAX = (WRITE << 1) - 1,
};
ENUM_OPERATORS(Qualifier, Qualifier::QUALIFIER_MAX);
@@ -221,16 +285,45 @@ struct ShaderCreateInfo {
bool do_static_compilation_ = false;
/** If true, all additionally linked create info will be merged into this one. */
bool finalized_ = false;
+ /** If true, all resources will have an automatic location assigned. */
+ bool auto_resource_location_ = false;
/**
* Maximum length of all the resource names including each null terminator.
* Only for names used by gpu::ShaderInterface.
*/
size_t interface_names_size_ = 0;
+ /** Manually set builtins. */
+ BuiltinBits builtins_ = BuiltinBits::NONE;
+ /** Manually set generated code. */
+ std::string vertex_source_generated = "";
+ std::string fragment_source_generated = "";
+ std::string typedef_source_generated = "";
+ /** Manually set generated dependencies. */
+ Vector<const char *, 0> dependencies_generated;
+
+#define TEST_EQUAL(a, b, _member) \
+ if (!((a)._member == (b)._member)) { \
+ return false; \
+ }
+
+#define TEST_VECTOR_EQUAL(a, b, _vector) \
+ TEST_EQUAL(a, b, _vector.size()); \
+ for (auto i : _vector.index_range()) { \
+ TEST_EQUAL(a, b, _vector[i]); \
+ }
struct VertIn {
int index;
Type type;
StringRefNull name;
+
+ bool operator==(const VertIn &b)
+ {
+ TEST_EQUAL(*this, b, index);
+ TEST_EQUAL(*this, b, type);
+ TEST_EQUAL(*this, b, name);
+ return true;
+ }
};
Vector<VertIn> vertex_inputs_;
@@ -240,6 +333,15 @@ struct ShaderCreateInfo {
PrimitiveOut primitive_out;
/** Set to -1 by default to check if used. */
int max_vertices = -1;
+
+ bool operator==(const GeometryStageLayout &b)
+ {
+ TEST_EQUAL(*this, b, primitive_in);
+ TEST_EQUAL(*this, b, invocations);
+ TEST_EQUAL(*this, b, primitive_out);
+ TEST_EQUAL(*this, b, max_vertices);
+ return true;
+ }
};
GeometryStageLayout geometry_layout_;
@@ -247,8 +349,15 @@ struct ShaderCreateInfo {
int local_size_x = -1;
int local_size_y = -1;
int local_size_z = -1;
- };
+ bool operator==(const ComputeStageLayout &b)
+ {
+ TEST_EQUAL(*this, b, local_size_x);
+ TEST_EQUAL(*this, b, local_size_y);
+ TEST_EQUAL(*this, b, local_size_z);
+ return true;
+ }
+ };
ComputeStageLayout compute_layout_;
struct FragOut {
@@ -256,6 +365,15 @@ struct ShaderCreateInfo {
Type type;
DualBlend blend;
StringRefNull name;
+
+ bool operator==(const FragOut &b)
+ {
+ TEST_EQUAL(*this, b, index);
+ TEST_EQUAL(*this, b, type);
+ TEST_EQUAL(*this, b, blend);
+ TEST_EQUAL(*this, b, name);
+ return true;
+ }
};
Vector<FragOut> fragment_outputs_;
@@ -301,6 +419,35 @@ struct ShaderCreateInfo {
};
Resource(BindType type, int _slot) : bind_type(type), slot(_slot){};
+
+ bool operator==(const Resource &b)
+ {
+ TEST_EQUAL(*this, b, bind_type);
+ TEST_EQUAL(*this, b, slot);
+ switch (bind_type) {
+ case UNIFORM_BUFFER:
+ TEST_EQUAL(*this, b, uniformbuf.type_name);
+ TEST_EQUAL(*this, b, uniformbuf.name);
+ break;
+ case STORAGE_BUFFER:
+ TEST_EQUAL(*this, b, storagebuf.qualifiers);
+ TEST_EQUAL(*this, b, storagebuf.type_name);
+ TEST_EQUAL(*this, b, storagebuf.name);
+ break;
+ case SAMPLER:
+ TEST_EQUAL(*this, b, sampler.type);
+ TEST_EQUAL(*this, b, sampler.sampler);
+ TEST_EQUAL(*this, b, sampler.name);
+ break;
+ case IMAGE:
+ TEST_EQUAL(*this, b, image.format);
+ TEST_EQUAL(*this, b, image.type);
+ TEST_EQUAL(*this, b, image.qualifiers);
+ TEST_EQUAL(*this, b, image.name);
+ break;
+ }
+ return true;
+ }
};
/**
* Resources are grouped by frequency of change.
@@ -317,6 +464,14 @@ struct ShaderCreateInfo {
Type type;
StringRefNull name;
int array_size;
+
+ bool operator==(const PushConst &b)
+ {
+ TEST_EQUAL(*this, b, type);
+ TEST_EQUAL(*this, b, name);
+ TEST_EQUAL(*this, b, array_size);
+ return true;
+ }
};
Vector<PushConst> push_constants_;
@@ -538,6 +693,18 @@ struct ShaderCreateInfo {
return *(Self *)this;
}
+ Self &builtins(BuiltinBits builtin)
+ {
+ builtins_ |= builtin;
+ return *(Self *)this;
+ }
+
+ Self &auto_resource_location(bool value)
+ {
+ auto_resource_location_ = value;
+ return *(Self *)this;
+ }
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -608,6 +775,77 @@ struct ShaderCreateInfo {
void validate(const ShaderCreateInfo &other_info);
/** \} */
+
+ /* -------------------------------------------------------------------- */
+ /** \name Operators.
+ *
+ * \{ */
+
+ /* Comparison operator for GPUPass cache. We only compare if it will create the same shader code.
+ * So we do not compare name and some other internal stuff. */
+ bool operator==(const ShaderCreateInfo &b)
+ {
+ TEST_EQUAL(*this, b, builtins_);
+ TEST_EQUAL(*this, b, vertex_source_generated);
+ TEST_EQUAL(*this, b, fragment_source_generated);
+ TEST_EQUAL(*this, b, typedef_source_generated);
+ TEST_VECTOR_EQUAL(*this, b, vertex_inputs_);
+ TEST_EQUAL(*this, b, geometry_layout_);
+ TEST_EQUAL(*this, b, compute_layout_);
+ TEST_VECTOR_EQUAL(*this, b, fragment_outputs_);
+ TEST_VECTOR_EQUAL(*this, b, pass_resources_);
+ TEST_VECTOR_EQUAL(*this, b, batch_resources_);
+ TEST_VECTOR_EQUAL(*this, b, vertex_out_interfaces_);
+ TEST_VECTOR_EQUAL(*this, b, geometry_out_interfaces_);
+ TEST_VECTOR_EQUAL(*this, b, push_constants_);
+ TEST_VECTOR_EQUAL(*this, b, typedef_sources_);
+ TEST_EQUAL(*this, b, vertex_source_);
+ TEST_EQUAL(*this, b, geometry_source_);
+ TEST_EQUAL(*this, b, fragment_source_);
+ TEST_EQUAL(*this, b, compute_source_);
+ TEST_VECTOR_EQUAL(*this, b, additional_infos_);
+ TEST_VECTOR_EQUAL(*this, b, defines_);
+ return true;
+ }
+
+ /** Debug print */
+ friend std::ostream &operator<<(std::ostream &stream, const ShaderCreateInfo &info)
+ {
+ /* TODO(@fclem): Complete print. */
+
+ auto print_resource = [&](const Resource &res) {
+ switch (res.bind_type) {
+ case Resource::BindType::UNIFORM_BUFFER:
+ stream << "UNIFORM_BUFFER(" << res.slot << ", " << res.uniformbuf.name << ")"
+ << std::endl;
+ break;
+ case Resource::BindType::STORAGE_BUFFER:
+ stream << "STORAGE_BUFFER(" << res.slot << ", " << res.storagebuf.name << ")"
+ << std::endl;
+ break;
+ case Resource::BindType::SAMPLER:
+ stream << "SAMPLER(" << res.slot << ", " << res.sampler.name << ")" << std::endl;
+ break;
+ case Resource::BindType::IMAGE:
+ stream << "IMAGE(" << res.slot << ", " << res.image.name << ")" << std::endl;
+ break;
+ }
+ };
+
+ /* TODO(@fclem): Order the resources. */
+ for (auto &res : info.batch_resources_) {
+ print_resource(res);
+ }
+ for (auto &res : info.pass_resources_) {
+ print_resource(res);
+ }
+ return stream;
+ }
+
+ /** \} */
+
+#undef TEST_EQUAL
+#undef TEST_VECTOR_EQUAL
};
} // namespace blender::gpu::shader
diff --git a/source/blender/gpu/intern/gpu_shader_dependency.cc b/source/blender/gpu/intern/gpu_shader_dependency.cc
index 5e03f7d0767..06ad0817bfb 100644
--- a/source/blender/gpu/intern/gpu_shader_dependency.cc
+++ b/source/blender/gpu/intern/gpu_shader_dependency.cc
@@ -59,7 +59,6 @@ struct GPUSource {
/* Scan for builtins. */
/* FIXME: This can trigger false positive caused by disabled #if blocks. */
/* TODO(fclem): Could be made faster by scanning once. */
- /* TODO(fclem): BARYCENTRIC_COORD. */
if (source.find("gl_FragCoord", 0)) {
builtins |= shader::BuiltinBits::FRAG_COORD;
}
@@ -72,9 +71,6 @@ struct GPUSource {
if (source.find("gl_InstanceID", 0)) {
builtins |= shader::BuiltinBits::INSTANCE_ID;
}
- if (source.find("gl_Layer", 0)) {
- builtins |= shader::BuiltinBits::LAYER;
- }
if (source.find("gl_LocalInvocationID", 0)) {
builtins |= shader::BuiltinBits::LOCAL_INVOCATION_ID;
}
@@ -336,13 +332,21 @@ struct GPUSource {
}
/* Returns the final string with all includes done. */
- void build(std::string &str, shader::BuiltinBits &out_builtins)
+ void build(Vector<const char *> &result) const
+ {
+ for (auto *dep : dependencies) {
+ result.append(dep->source.c_str());
+ }
+ result.append(source.c_str());
+ }
+
+ shader::BuiltinBits builtins_get() const
{
+ shader::BuiltinBits out_builtins = shader::BuiltinBits::NONE;
for (auto *dep : dependencies) {
- out_builtins |= builtins;
- str += dep->source;
+ out_builtins |= dep->builtins;
}
- str += source;
+ return out_builtins;
}
};
@@ -377,18 +381,47 @@ void gpu_shader_dependency_exit()
delete g_sources;
}
-char *gpu_shader_dependency_get_resolved_source(const char *shader_source_name, uint32_t *builtins)
+namespace blender::gpu::shader {
+
+BuiltinBits gpu_shader_dependency_get_builtins(const StringRefNull shader_source_name)
{
+ if (shader_source_name.is_empty()) {
+ return shader::BuiltinBits::NONE;
+ }
+ if (g_sources->contains(shader_source_name) == false) {
+ std::cout << "Error: Could not find \"" << shader_source_name
+ << "\" in the list of registered source.\n";
+ BLI_assert(0);
+ return shader::BuiltinBits::NONE;
+ }
GPUSource *source = g_sources->lookup(shader_source_name);
- std::string str;
- shader::BuiltinBits out_builtins;
- source->build(str, out_builtins);
- *builtins |= (uint32_t)out_builtins;
- return strdup(str.c_str());
+ return source->builtins_get();
}
-char *gpu_shader_dependency_get_source(const char *shader_source_name)
+Vector<const char *> gpu_shader_dependency_get_resolved_source(
+ const StringRefNull shader_source_name)
+{
+ Vector<const char *> result;
+ GPUSource *source = g_sources->lookup(shader_source_name);
+ source->build(result);
+ return result;
+}
+
+StringRefNull gpu_shader_dependency_get_source(const StringRefNull shader_source_name)
{
GPUSource *src = g_sources->lookup(shader_source_name);
- return strdup(src->source.c_str());
+ return src->source;
}
+
+StringRefNull gpu_shader_dependency_get_filename_from_source_string(
+ const StringRefNull source_string)
+{
+ for (auto &source : g_sources->values()) {
+ if (source->source.c_str() == source_string.c_str()) {
+ return source->filename;
+ }
+ }
+ return "";
+}
+
+} // namespace blender::gpu::shader
diff --git a/source/blender/gpu/intern/gpu_shader_dependency_private.h b/source/blender/gpu/intern/gpu_shader_dependency_private.h
index b129ca74a48..13261dd2021 100644
--- a/source/blender/gpu/intern/gpu_shader_dependency_private.h
+++ b/source/blender/gpu/intern/gpu_shader_dependency_private.h
@@ -34,11 +34,32 @@ void gpu_shader_dependency_init(void);
void gpu_shader_dependency_exit(void);
-/* User must free the resulting string using free. */
-char *gpu_shader_dependency_get_resolved_source(const char *shader_source_name,
- uint32_t *builtins);
-char *gpu_shader_dependency_get_source(const char *shader_source_name);
-
#ifdef __cplusplus
}
#endif
+
+#ifdef __cplusplus
+
+# include "BLI_string_ref.hh"
+# include "BLI_vector.hh"
+
+# include "gpu_shader_create_info.hh"
+
+namespace blender::gpu::shader {
+
+BuiltinBits gpu_shader_dependency_get_builtins(const StringRefNull source_name);
+
+Vector<const char *> gpu_shader_dependency_get_resolved_source(const StringRefNull source_name);
+StringRefNull gpu_shader_dependency_get_source(const StringRefNull source_name);
+
+/**
+ * \brief Find the name of the file from which the given string was generated.
+ * \return Return filename or empty string.
+ * \note source_string needs to be identical to the one given by gpu_shader_dependency_get_source()
+ */
+StringRefNull gpu_shader_dependency_get_filename_from_source_string(
+ const StringRefNull source_string);
+
+} // namespace blender::gpu::shader
+
+#endif
diff --git a/source/blender/gpu/intern/gpu_shader_interface.hh b/source/blender/gpu/intern/gpu_shader_interface.hh
index 7f99619c98c..514cfc01f09 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.hh
+++ b/source/blender/gpu/intern/gpu_shader_interface.hh
@@ -68,6 +68,7 @@ class ShaderInterface {
uint16_t enabled_ubo_mask_ = 0;
uint8_t enabled_ima_mask_ = 0;
uint64_t enabled_tex_mask_ = 0;
+ uint16_t enabled_ssbo_mask_ = 0;
/** Location of builtin uniforms. Fast access, no lookup needed. */
int32_t builtins_[GPU_NUM_UNIFORMS];
int32_t builtin_blocks_[GPU_NUM_UNIFORM_BLOCKS];
diff --git a/source/blender/gpu/intern/gpu_shader_log.cc b/source/blender/gpu/intern/gpu_shader_log.cc
index 12459b4b721..d20e49d3085 100644
--- a/source/blender/gpu/intern/gpu_shader_log.cc
+++ b/source/blender/gpu/intern/gpu_shader_log.cc
@@ -26,7 +26,9 @@
#include "BLI_dynstr.h"
#include "BLI_string.h"
#include "BLI_string_utils.h"
+#include "BLI_vector.hh"
+#include "gpu_shader_dependency_private.h"
#include "gpu_shader_private.hh"
#include "GPU_platform.h"
@@ -41,6 +43,14 @@ namespace blender::gpu {
/** \name Debug functions
* \{ */
+/* Number of lines before and after the error line to print for compilation errors. */
+#define DEBUG_CONTEXT_LINES 0
+/**
+ * Print dependencies sources list before the shader report.
+ * Useful to debug include order or missing dependencies.
+ */
+#define DEBUG_DEPENDENCIES 0
+
void Shader::print_log(Span<const char *> sources,
char *log,
const char *stage,
@@ -61,6 +71,30 @@ void Shader::print_log(Span<const char *> sources,
BLI_dynstr_appendf(dynstr, "\n");
+#if DEBUG_DEPENDENCIES
+ BLI_dynstr_appendf(
+ dynstr, "%s%sIncluded files (in order):%s\n", info_col, line_prefix, reset_col);
+#endif
+
+ Vector<int64_t> sources_end_line;
+ for (StringRefNull src : sources) {
+ int64_t cursor = 0, line_count = 0;
+ while ((cursor = src.find('\n', cursor) + 1)) {
+ line_count++;
+ }
+ if (sources_end_line.is_empty() == false) {
+ line_count += sources_end_line.last();
+ }
+ sources_end_line.append(line_count);
+#if DEBUG_DEPENDENCIES
+ StringRefNull filename = shader::gpu_shader_dependency_get_filename_from_source_string(src);
+ if (!filename.is_empty()) {
+ BLI_dynstr_appendf(
+ dynstr, "%s%s %s%s\n", info_col, line_prefix, filename.c_str(), reset_col);
+ }
+#endif
+ }
+
char *log_line = log, *line_end;
LogCursor previous_location;
@@ -73,12 +107,32 @@ void Shader::print_log(Span<const char *> sources,
continue;
}
+ /* Silence not useful lines. */
+ StringRef logref = StringRefNull(log_line).substr(0, (size_t)line_end - (size_t)log_line);
+ if (logref.endswith(" shader failed to compile with the following errors:") ||
+ logref.endswith(" No code generated")) {
+ log_line += (size_t)line_end - (size_t)log_line;
+ continue;
+ }
+
GPULogItem log_item;
log_line = parser->parse_line(log_line, log_item);
+ /* Sanitize output. Really bad values can happen when the error line is buggy. */
+ if (log_item.cursor.source >= sources.size()) {
+ log_item.cursor.source = -1;
+ }
+ if (log_item.cursor.row >= sources_end_line.last()) {
+ log_item.cursor.source = -1;
+ log_item.cursor.row = -1;
+ }
+
if (log_item.cursor.row == -1) {
found_line_id = false;
}
+ else if (log_item.source_base_row && log_item.cursor.source > 0) {
+ log_item.cursor.row += sources_end_line[log_item.cursor.source - 1];
+ }
const char *src_line = sources_combined;
@@ -98,15 +152,14 @@ void Shader::print_log(Span<const char *> sources,
/* error_line is 1 based in this case. */
int src_line_index = 1;
while ((src_line_end = strchr(src_line, '\n'))) {
- if (src_line_index == log_item.cursor.row) {
+ if (src_line_index >= log_item.cursor.row) {
found_line_id = true;
break;
}
-/* TODO(fclem) Make this an option to display N lines before error. */
-#if 0 /* Uncomment to print shader file up to the error line to have more context. */
- BLI_dynstr_appendf(dynstr, "%5d | ", src_line_index);
- BLI_dynstr_nappend(dynstr, src_line, (src_line_end + 1) - src_line);
-#endif
+ if (src_line_index >= log_item.cursor.row - DEBUG_CONTEXT_LINES) {
+ BLI_dynstr_appendf(dynstr, "%5d | ", src_line_index);
+ BLI_dynstr_nappend(dynstr, src_line, (src_line_end + 1) - src_line);
+ }
/* Continue to next line. */
src_line = src_line_end + 1;
src_line_index++;
@@ -129,10 +182,53 @@ void Shader::print_log(Span<const char *> sources,
BLI_dynstr_appendf(dynstr, "^");
}
BLI_dynstr_appendf(dynstr, "\n");
+
+ /* Skip the error line. */
+ src_line = src_line_end + 1;
+ src_line_index++;
+ while ((src_line_end = strchr(src_line, '\n'))) {
+ if (src_line_index > log_item.cursor.row + DEBUG_CONTEXT_LINES) {
+ break;
+ }
+ BLI_dynstr_appendf(dynstr, "%5d | ", src_line_index);
+ BLI_dynstr_nappend(dynstr, src_line, (src_line_end + 1) - src_line);
+ /* Continue to next line. */
+ src_line = src_line_end + 1;
+ src_line_index++;
+ }
}
}
BLI_dynstr_appendf(dynstr, line_prefix);
+ /* Search the correct source index. */
+ int row_in_file = log_item.cursor.row;
+ int source_index = log_item.cursor.source;
+ if (source_index <= 0) {
+ for (auto i : sources_end_line.index_range()) {
+ if (log_item.cursor.row <= sources_end_line[i]) {
+ source_index = i;
+ break;
+ }
+ }
+ }
+ if (source_index > 0) {
+ row_in_file -= sources_end_line[source_index - 1];
+ }
+ /* Print the filename the error line is comming from. */
+ if (source_index > 0) {
+ StringRefNull filename = shader::gpu_shader_dependency_get_filename_from_source_string(
+ sources[source_index]);
+ if (!filename.is_empty()) {
+ BLI_dynstr_appendf(dynstr,
+ "%s%s:%d:%d: %s",
+ info_col,
+ filename.c_str(),
+ row_in_file,
+ log_item.cursor.column + 1,
+ reset_col);
+ }
+ }
+
if (log_item.severity == Severity::Error) {
BLI_dynstr_appendf(dynstr, "%s%s%s: ", err_col, "Error", info_col);
}
diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh
index 3bfecdefba7..93c33811ee0 100644
--- a/source/blender/gpu/intern/gpu_shader_private.hh
+++ b/source/blender/gpu/intern/gpu_shader_private.hh
@@ -120,6 +120,7 @@ struct LogCursor {
struct GPULogItem {
LogCursor cursor;
+ bool source_base_row = false;
Severity severity = Severity::Unknown;
};
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc
index 92d180f1140..2ee7c0503f4 100644
--- a/source/blender/gpu/opengl/gl_backend.cc
+++ b/source/blender/gpu/opengl/gl_backend.cc
@@ -248,6 +248,8 @@ static void detect_workarounds()
GLContext::direct_state_access_support = false;
GLContext::fixed_restart_index_support = false;
GLContext::geometry_shader_invocations = false;
+ GLContext::layered_rendering_support = false;
+ GLContext::native_barycentric_support = false;
GLContext::multi_bind_support = false;
GLContext::multi_draw_indirect_support = false;
GLContext::shader_draw_parameters_support = false;
@@ -445,6 +447,8 @@ bool GLContext::direct_state_access_support = false;
bool GLContext::explicit_location_support = false;
bool GLContext::geometry_shader_invocations = false;
bool GLContext::fixed_restart_index_support = false;
+bool GLContext::layered_rendering_support = false;
+bool GLContext::native_barycentric_support = false;
bool GLContext::multi_bind_support = false;
bool GLContext::multi_draw_indirect_support = false;
bool GLContext::shader_draw_parameters_support = false;
@@ -505,6 +509,8 @@ void GLBackend::capabilities_init()
GLContext::explicit_location_support = GLEW_VERSION_4_3;
GLContext::geometry_shader_invocations = GLEW_ARB_gpu_shader5;
GLContext::fixed_restart_index_support = GLEW_ARB_ES3_compatibility;
+ GLContext::layered_rendering_support = GLEW_AMD_vertex_shader_layer;
+ GLContext::native_barycentric_support = GLEW_AMD_shader_explicit_vertex_parameter;
GLContext::multi_bind_support = GLEW_ARB_multi_bind;
GLContext::multi_draw_indirect_support = GLEW_ARB_multi_draw_indirect;
GLContext::shader_draw_parameters_support = GLEW_ARB_shader_draw_parameters;
diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh
index dd22418972b..b7a74863ac4 100644
--- a/source/blender/gpu/opengl/gl_context.hh
+++ b/source/blender/gpu/opengl/gl_context.hh
@@ -72,6 +72,8 @@ class GLContext : public Context {
static bool explicit_location_support;
static bool geometry_shader_invocations;
static bool fixed_restart_index_support;
+ static bool layered_rendering_support;
+ static bool native_barycentric_support;
static bool multi_bind_support;
static bool multi_draw_indirect_support;
static bool shader_draw_parameters_support;
diff --git a/source/blender/gpu/opengl/gl_framebuffer.hh b/source/blender/gpu/opengl/gl_framebuffer.hh
index 9ebe549efe7..00a7676dd3f 100644
--- a/source/blender/gpu/opengl/gl_framebuffer.hh
+++ b/source/blender/gpu/opengl/gl_framebuffer.hh
@@ -141,6 +141,8 @@ static inline GLenum to_gl(const GPUAttachmentType type)
ATTACHMENT(COLOR_ATTACHMENT3);
ATTACHMENT(COLOR_ATTACHMENT4);
ATTACHMENT(COLOR_ATTACHMENT5);
+ ATTACHMENT(COLOR_ATTACHMENT6);
+ ATTACHMENT(COLOR_ATTACHMENT7);
default:
BLI_assert(0);
return GL_COLOR_ATTACHMENT0;
diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc
index f0a4b5b7f58..275f2c96bbd 100644
--- a/source/blender/gpu/opengl/gl_shader.cc
+++ b/source/blender/gpu/opengl/gl_shader.cc
@@ -127,6 +127,74 @@ static const char *to_string(const Type &type)
}
}
+static const char *to_string(const eGPUTextureFormat &type)
+{
+ switch (type) {
+ case GPU_RGBA8UI:
+ return "rgba8ui";
+ case GPU_RGBA8I:
+ return "rgba8i";
+ case GPU_RGBA8:
+ return "rgba8";
+ case GPU_RGBA32UI:
+ return "rgba32ui";
+ case GPU_RGBA32I:
+ return "rgba32i";
+ case GPU_RGBA32F:
+ return "rgba32f";
+ case GPU_RGBA16UI:
+ return "rgba16ui";
+ case GPU_RGBA16I:
+ return "rgba16i";
+ case GPU_RGBA16F:
+ return "rgba16f";
+ case GPU_RGBA16:
+ return "rgba16";
+ case GPU_RG8UI:
+ return "rg8ui";
+ case GPU_RG8I:
+ return "rg8i";
+ case GPU_RG8:
+ return "rg8";
+ case GPU_RG32UI:
+ return "rg32ui";
+ case GPU_RG32I:
+ return "rg32i";
+ case GPU_RG32F:
+ return "rg32f";
+ case GPU_RG16UI:
+ return "rg16ui";
+ case GPU_RG16I:
+ return "rg16i";
+ case GPU_RG16F:
+ return "rg16f";
+ case GPU_RG16:
+ return "rg16";
+ case GPU_R8UI:
+ return "r8ui";
+ case GPU_R8I:
+ return "r8i";
+ case GPU_R8:
+ return "r8";
+ case GPU_R32UI:
+ return "r32ui";
+ case GPU_R32I:
+ return "r32i";
+ case GPU_R32F:
+ return "r32f";
+ case GPU_R16UI:
+ return "r16ui";
+ case GPU_R16I:
+ return "r16i";
+ case GPU_R16F:
+ return "r16f";
+ case GPU_R16:
+ return "r16";
+ default:
+ return "unkown";
+ }
+}
+
static const char *to_string(const PrimitiveIn &layout)
{
switch (layout) {
@@ -277,15 +345,15 @@ static void print_image_type(std::ostream &os,
static std::ostream &print_qualifier(std::ostream &os, const Qualifier &qualifiers)
{
- if ((qualifiers & Qualifier::RESTRICT) == Qualifier::RESTRICT) {
+ if (bool(qualifiers & Qualifier::NO_RESTRICT) == false) {
os << "restrict ";
}
- if ((qualifiers & Qualifier::READ_ONLY) == Qualifier::READ_ONLY) {
- os << "readonly ";
- }
- if ((qualifiers & Qualifier::WRITE_ONLY) == Qualifier::WRITE_ONLY) {
+ if (bool(qualifiers & Qualifier::READ) == false) {
os << "writeonly ";
}
+ if (bool(qualifiers & Qualifier::WRITE) == false) {
+ os << "readonly ";
+ }
return os;
}
@@ -294,7 +362,7 @@ static void print_resource(std::ostream &os, const ShaderCreateInfo::Resource &r
if (GLContext::explicit_location_support) {
os << "layout(binding = " << res.slot;
if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
- os << ", " << res.image.format;
+ os << ", " << to_string(res.image.format);
}
else if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) {
os << ", std140";
@@ -370,7 +438,7 @@ static void print_interface(std::ostream &os,
const StageInterfaceInfo &iface,
const StringRefNull &suffix = "")
{
- /* TODO(fclem) Move that to interface check. */
+ /* TODO(@fclem): Move that to interface check. */
// if (iface.instance_name.is_empty()) {
// BLI_assert_msg(0, "Interfaces require an instance name for geometry shader.");
// std::cout << iface.name << ": Interfaces require an instance name for geometry shader.\n";
@@ -426,9 +494,28 @@ std::string GLShader::resources_declare(const ShaderCreateInfo &info) const
return ss.str();
}
+static std::string main_function_wrapper(std::string &pre_main, std::string &post_main)
+{
+ std::stringstream ss;
+ /* Prototype for the original main. */
+ ss << "\n";
+ ss << "void main_function_();\n";
+ /* Wrapper to the main function in order to inject code processing on globals. */
+ ss << "void main() {\n";
+ ss << pre_main;
+ ss << " main_function_();\n";
+ ss << post_main;
+ ss << "}\n";
+ /* Rename the original main. */
+ ss << "#define main main_function_\n";
+ ss << "\n";
+ return ss.str();
+}
+
std::string GLShader::vertex_interface_declare(const ShaderCreateInfo &info) const
{
std::stringstream ss;
+ std::string post_main = "";
ss << "\n/* Inputs. */\n";
for (const ShaderCreateInfo::VertIn &attr : info.vertex_inputs_) {
@@ -443,13 +530,35 @@ std::string GLShader::vertex_interface_declare(const ShaderCreateInfo &info) con
for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
print_interface(ss, "out", *iface);
}
+ if (!GLContext::layered_rendering_support && bool(info.builtins_ & BuiltinBits::LAYER)) {
+ ss << "out int gpu_Layer;\n";
+ }
+ if (bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD)) {
+ if (!GLContext::native_barycentric_support) {
+ /* Disabled or unsupported. */
+ }
+ else if (GLEW_AMD_shader_explicit_vertex_parameter) {
+ /* Need this for stable barycentric. */
+ ss << "flat out vec4 gpu_pos_flat;\n";
+ ss << "out vec4 gpu_pos;\n";
+
+ post_main += " gpu_pos = gpu_pos_flat = gl_Position;\n";
+ }
+ }
ss << "\n";
+
+ if (post_main.empty() == false) {
+ std::string pre_main = "";
+ ss << main_function_wrapper(pre_main, post_main);
+ }
return ss.str();
}
std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) const
{
std::stringstream ss;
+ std::string pre_main = "";
+
ss << "\n/* Interfaces. */\n";
const Vector<StageInterfaceInfo *> &in_interfaces = (info.geometry_source_.is_empty()) ?
info.vertex_out_interfaces_ :
@@ -457,6 +566,32 @@ std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) c
for (const StageInterfaceInfo *iface : in_interfaces) {
print_interface(ss, "in", *iface);
}
+ if (bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD)) {
+ if (!GLContext::native_barycentric_support) {
+ ss << "smooth in vec3 gpu_BaryCoord;\n";
+ ss << "noperspective in vec3 gpu_BaryCoordNoPersp;\n";
+ }
+ else if (GLEW_AMD_shader_explicit_vertex_parameter) {
+ /* NOTE(fclem): This won't work with geometry shader. Hopefully, we don't need geometry
+ * shader workaround if this extension/feature is detected. */
+ ss << "\n/* Stable Barycentric Coordinates. */\n";
+ ss << "flat in vec4 gpu_pos_flat;\n";
+ ss << "__explicitInterpAMD in vec4 gpu_pos;\n";
+ /* Globals. */
+ ss << "vec3 gpu_BaryCoord;\n";
+ ss << "vec3 gpu_BaryCoordNoPersp;\n";
+ ss << "\n";
+ ss << "vec2 stable_bary_(vec2 in_bary) {\n";
+ ss << " vec3 bary = vec3(in_bary, 1.0 - in_bary.x - in_bary.y);\n";
+ ss << " if (interpolateAtVertexAMD(gpu_pos, 0) == gpu_pos_flat) { return bary.zxy; }\n";
+ ss << " if (interpolateAtVertexAMD(gpu_pos, 2) == gpu_pos_flat) { return bary.yzx; }\n";
+ ss << " return bary.xyz;\n";
+ ss << "}\n";
+
+ pre_main += " gpu_BaryCoord = stable_bary_(gl_BaryCoordSmoothAMD);\n";
+ pre_main += " gpu_BaryCoordNoPersp = stable_bary_(gl_BaryCoordNoPerspAMD);\n";
+ }
+ }
ss << "\n/* Outputs. */\n";
for (const ShaderCreateInfo::FragOut &output : info.fragment_outputs_) {
ss << "layout(location = " << output.index;
@@ -474,6 +609,11 @@ std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) c
ss << "out " << to_string(output.type) << " " << output.name << ";\n";
}
ss << "\n";
+
+ if (pre_main.empty() == false) {
+ std::string post_main = "";
+ ss << main_function_wrapper(pre_main, post_main);
+ }
return ss.str();
}
@@ -505,7 +645,7 @@ static StageInterfaceInfo *find_interface_by_name(const Vector<StageInterfaceInf
const StringRefNull &name)
{
for (auto *iface : ifaces) {
- if (iface->name == name) {
+ if (iface->instance_name == name) {
return iface;
}
}
@@ -514,8 +654,8 @@ static StageInterfaceInfo *find_interface_by_name(const Vector<StageInterfaceInf
std::string GLShader::geometry_interface_declare(const ShaderCreateInfo &info) const
{
-
std::stringstream ss;
+
ss << "\n/* Interfaces. */\n";
for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
bool has_matching_output_iface = find_interface_by_name(info.geometry_out_interfaces_,
@@ -549,6 +689,76 @@ std::string GLShader::compute_layout_declare(const ShaderCreateInfo &info) const
ss << "\n";
return ss.str();
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Passthrough geometry shader emulation
+ *
+ * \{ */
+
+std::string GLShader::workaround_geometry_shader_source_create(
+ const shader::ShaderCreateInfo &info)
+{
+ std::stringstream ss;
+
+ const bool do_layer_workaround = !GLContext::layered_rendering_support &&
+ bool(info.builtins_ & BuiltinBits::LAYER);
+ const bool do_barycentric_workaround = !GLContext::native_barycentric_support &&
+ bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD);
+
+ shader::ShaderCreateInfo info_modified = info;
+ info_modified.geometry_out_interfaces_ = info_modified.vertex_out_interfaces_;
+ /**
+ * NOTE(@fclem): Assuming we will render TRIANGLES. This will not work with other primitive
+ * types. In this case, it might not trigger an error on some implementations.
+ */
+ info_modified.geometry_layout(PrimitiveIn::TRIANGLES, PrimitiveOut::TRIANGLE_STRIP, 3);
+
+ ss << geometry_layout_declare(info_modified);
+ ss << geometry_interface_declare(info_modified);
+ if (do_layer_workaround) {
+ ss << "in int gpu_Layer[];\n";
+ }
+ if (do_barycentric_workaround) {
+ ss << "smooth out vec3 gpu_BaryCoord;\n";
+ ss << "noperspective out vec3 gpu_BaryCoordNoPersp;\n";
+ }
+ ss << "\n";
+
+ ss << "void main()\n";
+ ss << "{\n";
+ if (do_layer_workaround) {
+ ss << " gl_Layer = gpu_Layer[0];\n";
+ }
+ for (auto i : IndexRange(3)) {
+ for (auto iface : info_modified.vertex_out_interfaces_) {
+ for (auto &inout : iface->inouts) {
+ ss << " " << iface->instance_name << "_out." << inout.name;
+ ss << " = " << iface->instance_name << "_in[" << i << "]." << inout.name << ";\n";
+ }
+ }
+ if (do_barycentric_workaround) {
+ ss << " gpu_BaryCoordNoPersp = gpu_BaryCoord =";
+ ss << " vec3(" << int(i == 0) << ", " << int(i == 1) << ", " << int(i == 2) << ");\n";
+ }
+ ss << " gl_Position = gl_in[" << i << "].gl_Position;\n";
+ ss << " EmitVertex();\n";
+ }
+ ss << "}\n";
+ return ss.str();
+}
+
+bool GLShader::do_geometry_shader_injection(const shader::ShaderCreateInfo *info)
+{
+ BuiltinBits builtins = info->builtins_;
+ if (!GLContext::native_barycentric_support && bool(builtins & BuiltinBits::BARYCENTRIC_COORD)) {
+ return true;
+ }
+ if (!GLContext::layered_rendering_support && bool(builtins & BuiltinBits::LAYER)) {
+ return true;
+ }
+ return false;
+}
/** \} */
@@ -559,7 +769,7 @@ std::string GLShader::compute_layout_declare(const ShaderCreateInfo &info) const
static char *glsl_patch_default_get()
{
/** Used for shader patching. Init once. */
- static char patch[700] = "\0";
+ static char patch[1024] = "\0";
if (patch[0] != '\0') {
return patch;
}
@@ -596,13 +806,20 @@ static char *glsl_patch_default_get()
STR_CONCAT(patch, slen, "#extension GL_ARB_texture_cube_map_array : enable\n");
STR_CONCAT(patch, slen, "#define GPU_ARB_texture_cube_map_array\n");
}
- if (GLEW_ARB_conservative_depth) {
+ if (!GLEW_VERSION_4_2 && GLEW_ARB_conservative_depth) {
STR_CONCAT(patch, slen, "#extension GL_ARB_conservative_depth : enable\n");
}
if (GPU_shader_image_load_store_support()) {
STR_CONCAT(patch, slen, "#extension GL_ARB_shader_image_load_store: enable\n");
STR_CONCAT(patch, slen, "#extension GL_ARB_shading_language_420pack: enable\n");
}
+ if (GLContext::layered_rendering_support) {
+ STR_CONCAT(patch, slen, "#extension GL_AMD_vertex_shader_layer: enable\n");
+ STR_CONCAT(patch, slen, "#define gpu_Layer gl_Layer\n");
+ }
+ if (GLContext::native_barycentric_support) {
+ STR_CONCAT(patch, slen, "#extension GL_AMD_shader_explicit_vertex_parameter: enable\n");
+ }
/* Fallbacks. */
if (!GLContext::shader_draw_parameters_support) {
@@ -612,6 +829,9 @@ static char *glsl_patch_default_get()
/* Vulkan GLSL compat. */
STR_CONCAT(patch, slen, "#define gpu_InstanceIndex (gl_InstanceID + gpu_BaseInstance)\n");
+ /* Array compat. */
+ STR_CONCAT(patch, slen, "#define array(_type) _type[]\n");
+
/* Derivative sign can change depending on implementation. */
STR_CONCATF(patch, slen, "#define DFDX_SIGN %1.1f\n", GLContext::derivative_signs[0]);
STR_CONCATF(patch, slen, "#define DFDY_SIGN %1.1f\n", GLContext::derivative_signs[1]);
@@ -719,6 +939,14 @@ bool GLShader::finalize(const shader::ShaderCreateInfo *info)
return false;
}
+ if (info && do_geometry_shader_injection(info)) {
+ std::string source = workaround_geometry_shader_source_create(*info);
+ Vector<const char *> sources;
+ sources.append("version");
+ sources.append(source.c_str());
+ geometry_shader_from_glsl(sources);
+ }
+
glLinkProgram(shader_program_);
GLint status;
diff --git a/source/blender/gpu/opengl/gl_shader.hh b/source/blender/gpu/opengl/gl_shader.hh
index a82ab026c16..cc1c93142f8 100644
--- a/source/blender/gpu/opengl/gl_shader.hh
+++ b/source/blender/gpu/opengl/gl_shader.hh
@@ -94,6 +94,14 @@ class GLShader : public Shader {
/** Create, compile and attach the shader stage to the shader program. */
GLuint create_shader_stage(GLenum gl_stage, MutableSpan<const char *> sources);
+ /**
+ * \brief features available on newer implementation such as native barycentric coordinates
+ * and layered rendering, necessitate a geometry shader to work on older hardware.
+ */
+ std::string workaround_geometry_shader_source_create(const shader::ShaderCreateInfo &info);
+
+ bool do_geometry_shader_injection(const shader::ShaderCreateInfo *info);
+
MEM_CXX_CLASS_ALLOC_FUNCS("GLShader");
};
diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc
index 71b908665d3..0a31f8dee7f 100644
--- a/source/blender/gpu/opengl/gl_shader_interface.cc
+++ b/source/blender/gpu/opengl/gl_shader_interface.cc
@@ -117,7 +117,28 @@ static inline int image_binding(int32_t program,
switch (type) {
case GL_IMAGE_1D:
case GL_IMAGE_2D:
- case GL_IMAGE_3D: {
+ case GL_IMAGE_3D:
+ case GL_IMAGE_CUBE:
+ case GL_IMAGE_BUFFER:
+ case GL_IMAGE_1D_ARRAY:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_IMAGE_CUBE_MAP_ARRAY:
+ case GL_INT_IMAGE_1D:
+ case GL_INT_IMAGE_2D:
+ case GL_INT_IMAGE_3D:
+ case GL_INT_IMAGE_CUBE:
+ case GL_INT_IMAGE_BUFFER:
+ case GL_INT_IMAGE_1D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_CUBE_MAP_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_1D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_BUFFER:
+ case GL_UNSIGNED_INT_IMAGE_1D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: {
/* For now just assign a consecutive index. In the future, we should set it in
* the shader using layout(binding = i) and query its value. */
int binding = *image_len;
@@ -298,6 +319,7 @@ GLShaderInterface::GLShaderInterface(GLuint program)
input->binding = input->location = binding;
name_buffer_offset += this->set_input_name(input, name, name_len);
+ enabled_ssbo_mask_ |= (input->binding != -1) ? (1lu << input->binding) : 0lu;
}
/* Builtin Uniforms */
@@ -455,7 +477,7 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI
if (res.bind_type == ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER) {
copy_input_name(input, res.storagebuf.name, name_buffer_, name_buffer_offset);
input->location = input->binding = res.slot;
- enabled_ubo_mask_ |= (1 << input->binding);
+ enabled_ssbo_mask_ |= (1 << input->binding);
input++;
}
}
@@ -497,7 +519,7 @@ GLShaderInterface::~GLShaderInterface()
void GLShaderInterface::ref_add(GLVaoCache *ref)
{
for (int i = 0; i < refs_.size(); i++) {
- if (refs_[i] == NULL) {
+ if (refs_[i] == nullptr) {
refs_[i] = ref;
return;
}
@@ -509,7 +531,7 @@ void GLShaderInterface::ref_remove(GLVaoCache *ref)
{
for (int i = 0; i < refs_.size(); i++) {
if (refs_[i] == ref) {
- refs_[i] = NULL;
+ refs_[i] = nullptr;
break; /* cannot have duplicates */
}
}
diff --git a/source/blender/gpu/opengl/gl_shader_log.cc b/source/blender/gpu/opengl/gl_shader_log.cc
index 174cc63ad81..0ee70b54f52 100644
--- a/source/blender/gpu/opengl/gl_shader_log.cc
+++ b/source/blender/gpu/opengl/gl_shader_log.cc
@@ -60,6 +60,15 @@ char *GLLogParser::parse_line(char *log_line, GPULogItem &log_item)
log_item.cursor.row = log_item.cursor.column;
log_item.cursor.column = -1;
}
+ else if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OFFICIAL) &&
+ /* WORKAROUND(@fclem): Both Mesa and amdgpu-pro are reported as official. */
+ StringRefNull(GPU_platform_version()).find(" Mesa ") == -1) {
+ /* source:row */
+ log_item.cursor.source = log_item.cursor.row;
+ log_item.cursor.row = log_item.cursor.column;
+ log_item.cursor.column = -1;
+ log_item.source_base_row = true;
+ }
else {
/* line:char */
}
diff --git a/source/blender/gpu/opengl/gl_state.hh b/source/blender/gpu/opengl/gl_state.hh
index 83ff3ffc9e9..5985f1583f2 100644
--- a/source/blender/gpu/opengl/gl_state.hh
+++ b/source/blender/gpu/opengl/gl_state.hh
@@ -124,11 +124,20 @@ static inline GLbitfield to_gl(eGPUBarrier barrier_bits)
if (barrier_bits & GPU_BARRIER_SHADER_IMAGE_ACCESS) {
barrier |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
}
+ if (barrier_bits & GPU_BARRIER_SHADER_STORAGE) {
+ barrier |= GL_SHADER_STORAGE_BARRIER_BIT;
+ }
if (barrier_bits & GPU_BARRIER_TEXTURE_FETCH) {
barrier |= GL_TEXTURE_FETCH_BARRIER_BIT;
}
- if (barrier_bits & GPU_BARRIER_SHADER_STORAGE) {
- barrier |= GL_SHADER_STORAGE_BARRIER_BIT;
+ if (barrier_bits & GPU_BARRIER_TEXTURE_UPDATE) {
+ barrier |= GL_TEXTURE_UPDATE_BARRIER_BIT;
+ }
+ if (barrier_bits & GPU_BARRIER_COMMAND) {
+ barrier |= GL_COMMAND_BARRIER_BIT;
+ }
+ if (barrier_bits & GPU_BARRIER_FRAMEBUFFER) {
+ barrier |= GL_FRAMEBUFFER_BARRIER_BIT;
}
if (barrier_bits & GPU_BARRIER_VERTEX_ATTRIB_ARRAY) {
barrier |= GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
index 01a16e194ca..ab6024b073d 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
@@ -18,7 +18,7 @@ void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
result.radiance = out_Diffuse_0.radiance;
- /* TODO(fclem) Try to not use this. */
+ /* TODO(@fclem): Try to not use this. */
closure_load_ssr_data(vec3(0.0), 0.0, in_Diffuse_0.N, -1.0, result);
}
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 bba84c2be52..c97fc090fe2 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
@@ -166,7 +166,7 @@ void node_bsdf_principled(vec4 base_color,
float btdf = (do_multiscatter != 0.0) ?
1.0 :
btdf_lut(NV, in_Refraction_3.roughness, in_Refraction_3.ior).x;
- /* TODO(fclem) This could be going to a transmission render pass instead. */
+ /* TODO(@fclem): This could be going to a transmission render pass instead. */
out_Refraction_3.radiance *= btdf;
out_Refraction_3.radiance = render_pass_glossy_mask(vec3(1), out_Refraction_3.radiance);
out_Refraction_3.radiance *= base_color.rgb;
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
index 7cbc7218f5c..8a42a131f43 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
@@ -21,7 +21,7 @@ void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Cl
result.radiance = out_Refraction_0.radiance;
- /* TODO(fclem) Try to not use this. */
+ /* TODO(@fclem): Try to not use this. */
result.ssr_normal = normal_encode(mat3(ViewMatrix) * in_Refraction_0.N,
viewCameraVec(viewPosition));
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
index d0c159cdf37..20b634aa801 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
@@ -22,7 +22,7 @@ void node_subsurface_scattering(vec4 color,
closure_load_sss_data(scale, out_Diffuse_0.radiance, color.rgb, int(sss_id), result);
- /* TODO(fclem) Try to not use this. */
+ /* TODO(@fclem): Try to not use this. */
closure_load_ssr_data(vec3(0.0), 0.0, in_Diffuse_0.N, -1.0, result);
}
diff --git a/source/blender/io/collada/CMakeLists.txt b/source/blender/io/collada/CMakeLists.txt
index e1645083116..9ce3389257d 100644
--- a/source/blender/io/collada/CMakeLists.txt
+++ b/source/blender/io/collada/CMakeLists.txt
@@ -135,10 +135,6 @@ if(WITH_BUILDINFO)
add_definitions(-DWITH_BUILDINFO)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(CMAKE_COMPILER_IS_GNUCXX)
# COLLADAFWArray.h gives error with gcc 4.5
string(APPEND CMAKE_CXX_FLAGS " -fpermissive")
diff --git a/source/blender/io/usd/intern/usd_reader_camera.cc b/source/blender/io/usd/intern/usd_reader_camera.cc
index 2732ed5770d..1d001e19140 100644
--- a/source/blender/io/usd/intern/usd_reader_camera.cc
+++ b/source/blender/io/usd/intern/usd_reader_camera.cc
@@ -72,7 +72,7 @@ void USDCameraReader::read_object_data(Main *bmain, const double motionSampleTim
cam_prim.GetHorizontalApertureAttr().Get(&horAp, motionSampleTime);
bcam->lens = val.Get<float>();
- /* TODO(makowalski) */
+ /* TODO(@makowalski): support sensor size. */
#if 0
bcam->sensor_x = 0.0f;
bcam->sensor_y = 0.0f;
diff --git a/source/blender/io/usd/intern/usd_writer_material.cc b/source/blender/io/usd/intern/usd_writer_material.cc
index 52ad349fb98..5ce04339503 100644
--- a/source/blender/io/usd/intern/usd_writer_material.cc
+++ b/source/blender/io/usd/intern/usd_writer_material.cc
@@ -286,7 +286,7 @@ static void create_uvmap_shader(const USDExporterContext &usd_export_context,
}
bNode *uv_node = traverse_channel(tex_node_sock, SH_NODE_UVMAP);
- if (uv_node == NULL) {
+ if (uv_node == nullptr) {
continue;
}
@@ -391,7 +391,7 @@ static void export_in_memory_texture(Image *ima,
BKE_image_path_ensure_ext_from_imformat(file_name, &imageFormat);
char export_path[FILE_MAX];
- BLI_path_join(export_path, FILE_MAX, export_dir.c_str(), file_name, NULL);
+ BLI_path_join(export_path, FILE_MAX, export_dir.c_str(), file_name, nullptr);
if (!allow_overwrite && BLI_exists(export_path)) {
return;
@@ -590,7 +590,7 @@ static std::string get_tex_image_asset_path(bNode *node,
BLI_split_file_part(path.c_str(), file_path, FILE_MAX);
if (export_params.relative_texture_paths) {
- BLI_path_join(exp_path, FILE_MAX, ".", "textures", file_path, NULL);
+ BLI_path_join(exp_path, FILE_MAX, ".", "textures", file_path, nullptr);
}
else {
/* Create absolute path in the textures directory. */
@@ -602,7 +602,7 @@ static std::string get_tex_image_asset_path(bNode *node,
char dir_path[FILE_MAX];
BLI_split_dir_part(stage_path.c_str(), dir_path, FILE_MAX);
- BLI_path_join(exp_path, FILE_MAX, dir_path, "textures", file_path, NULL);
+ BLI_path_join(exp_path, FILE_MAX, dir_path, "textures", file_path, nullptr);
}
return exp_path;
}
@@ -697,7 +697,7 @@ static void copy_single_file(Image *ima, const std::string &dest_dir, const bool
BLI_split_file_part(source_path, file_name, FILE_MAX);
char dest_path[FILE_MAX];
- BLI_path_join(dest_path, FILE_MAX, dest_dir.c_str(), file_name, NULL);
+ BLI_path_join(dest_path, FILE_MAX, dest_dir.c_str(), file_name, nullptr);
if (!allow_overwrite && BLI_exists(dest_path)) {
return;
@@ -743,7 +743,7 @@ static void export_texture(bNode *node,
BLI_split_dir_part(stage_path.c_str(), usd_dir_path, FILE_MAX);
char tex_dir_path[FILE_MAX];
- BLI_path_join(tex_dir_path, FILE_MAX, usd_dir_path, "textures", SEP_STR, NULL);
+ BLI_path_join(tex_dir_path, FILE_MAX, usd_dir_path, "textures", SEP_STR, nullptr);
BLI_dir_create_recursive(tex_dir_path);
diff --git a/source/blender/io/wavefront_obj/CMakeLists.txt b/source/blender/io/wavefront_obj/CMakeLists.txt
index 296dd70b5a2..0b1be7946cf 100644
--- a/source/blender/io/wavefront_obj/CMakeLists.txt
+++ b/source/blender/io/wavefront_obj/CMakeLists.txt
@@ -56,6 +56,12 @@ set(LIB
bf_blenkernel
)
+if(WITH_TBB)
+ add_definitions(-DWITH_TBB)
+ list(APPEND INC_SYS ${TBB_INCLUDE_DIRS})
+ list(APPEND LIB ${TBB_LIBRARIES})
+endif()
+
blender_add_lib(bf_wavefront_obj "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
if(WITH_GTESTS)
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
index 38163af64b6..13d1a4fdde6 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
@@ -52,68 +52,75 @@ const char *DEFORM_GROUP_DISABLED = "off";
* So an empty material name is written. */
const char *MATERIAL_GROUP_DISABLED = "";
-void OBJWriter::write_vert_uv_normal_indices(Span<int> vert_indices,
+void OBJWriter::write_vert_uv_normal_indices(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ Span<int> vert_indices,
Span<int> uv_indices,
Span<int> normal_indices) const
{
BLI_assert(vert_indices.size() == uv_indices.size() &&
vert_indices.size() == normal_indices.size());
- file_handler_->write<eOBJSyntaxElement::poly_element_begin>();
+ fh.write<eOBJSyntaxElement::poly_element_begin>();
for (int j = 0; j < vert_indices.size(); j++) {
- file_handler_->write<eOBJSyntaxElement::vertex_uv_normal_indices>(
- vert_indices[j] + index_offsets_.vertex_offset + 1,
- uv_indices[j] + index_offsets_.uv_vertex_offset + 1,
- normal_indices[j] + index_offsets_.normal_offset + 1);
+ fh.write<eOBJSyntaxElement::vertex_uv_normal_indices>(
+ vert_indices[j] + offsets.vertex_offset + 1,
+ uv_indices[j] + offsets.uv_vertex_offset + 1,
+ normal_indices[j] + offsets.normal_offset + 1);
}
- file_handler_->write<eOBJSyntaxElement::poly_element_end>();
+ fh.write<eOBJSyntaxElement::poly_element_end>();
}
-void OBJWriter::write_vert_normal_indices(Span<int> vert_indices,
+void OBJWriter::write_vert_normal_indices(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ Span<int> vert_indices,
Span<int> /*uv_indices*/,
Span<int> normal_indices) const
{
BLI_assert(vert_indices.size() == normal_indices.size());
- file_handler_->write<eOBJSyntaxElement::poly_element_begin>();
+ fh.write<eOBJSyntaxElement::poly_element_begin>();
for (int j = 0; j < vert_indices.size(); j++) {
- file_handler_->write<eOBJSyntaxElement::vertex_normal_indices>(
- vert_indices[j] + index_offsets_.vertex_offset + 1,
- normal_indices[j] + index_offsets_.normal_offset + 1);
+ fh.write<eOBJSyntaxElement::vertex_normal_indices>(vert_indices[j] + offsets.vertex_offset + 1,
+ normal_indices[j] + offsets.normal_offset +
+ 1);
}
- file_handler_->write<eOBJSyntaxElement::poly_element_end>();
+ fh.write<eOBJSyntaxElement::poly_element_end>();
}
-void OBJWriter::write_vert_uv_indices(Span<int> vert_indices,
+void OBJWriter::write_vert_uv_indices(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ Span<int> vert_indices,
Span<int> uv_indices,
Span<int> /*normal_indices*/) const
{
BLI_assert(vert_indices.size() == uv_indices.size());
- file_handler_->write<eOBJSyntaxElement::poly_element_begin>();
+ fh.write<eOBJSyntaxElement::poly_element_begin>();
for (int j = 0; j < vert_indices.size(); j++) {
- file_handler_->write<eOBJSyntaxElement::vertex_uv_indices>(
- vert_indices[j] + index_offsets_.vertex_offset + 1,
- uv_indices[j] + index_offsets_.uv_vertex_offset + 1);
+ fh.write<eOBJSyntaxElement::vertex_uv_indices>(vert_indices[j] + offsets.vertex_offset + 1,
+ uv_indices[j] + offsets.uv_vertex_offset + 1);
}
- file_handler_->write<eOBJSyntaxElement::poly_element_end>();
+ fh.write<eOBJSyntaxElement::poly_element_end>();
}
-void OBJWriter::write_vert_indices(Span<int> vert_indices,
+void OBJWriter::write_vert_indices(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ Span<int> vert_indices,
Span<int> /*uv_indices*/,
Span<int> /*normal_indices*/) const
{
- file_handler_->write<eOBJSyntaxElement::poly_element_begin>();
+ fh.write<eOBJSyntaxElement::poly_element_begin>();
for (const int vert_index : vert_indices) {
- file_handler_->write<eOBJSyntaxElement::vertex_indices>(vert_index +
- index_offsets_.vertex_offset + 1);
+ fh.write<eOBJSyntaxElement::vertex_indices>(vert_index + offsets.vertex_offset + 1);
}
- file_handler_->write<eOBJSyntaxElement::poly_element_end>();
+ fh.write<eOBJSyntaxElement::poly_element_end>();
}
void OBJWriter::write_header() const
{
using namespace std::string_literals;
- file_handler_->write<eOBJSyntaxElement::string>("# Blender "s + BKE_blender_version_string() +
- "\n");
- file_handler_->write<eOBJSyntaxElement::string>("# www.blender.org\n");
+ FormatHandler<eFileType::OBJ> fh;
+ fh.write<eOBJSyntaxElement::string>("# Blender "s + BKE_blender_version_string() + "\n");
+ fh.write<eOBJSyntaxElement::string>("# www.blender.org\n");
+ fh.write_to_file(outfile_);
}
void OBJWriter::write_mtllib_name(const StringRefNull mtl_filepath) const
@@ -122,10 +129,13 @@ void OBJWriter::write_mtllib_name(const StringRefNull mtl_filepath) const
char mtl_file_name[FILE_MAXFILE];
char mtl_dir_name[FILE_MAXDIR];
BLI_split_dirfile(mtl_filepath.data(), mtl_dir_name, mtl_file_name, FILE_MAXDIR, FILE_MAXFILE);
- file_handler_->write<eOBJSyntaxElement::mtllib>(mtl_file_name);
+ FormatHandler<eFileType::OBJ> fh;
+ fh.write<eOBJSyntaxElement::mtllib>(mtl_file_name);
+ fh.write_to_file(outfile_);
}
-void OBJWriter::write_object_group(const OBJMesh &obj_mesh_data) const
+void OBJWriter::write_object_group(FormatHandler<eFileType::OBJ> &fh,
+ const OBJMesh &obj_mesh_data) const
{
/* "o object_name" is not mandatory. A valid .OBJ file may contain neither
* "o name" nor "g group_name". */
@@ -138,54 +148,52 @@ void OBJWriter::write_object_group(const OBJMesh &obj_mesh_data) const
const char *object_material_name = obj_mesh_data.get_object_material_name(0);
if (export_params_.export_materials && export_params_.export_material_groups &&
object_material_name) {
- file_handler_->write<eOBJSyntaxElement::object_group>(object_name + "_" + object_mesh_name +
- "_" + object_material_name);
- return;
+ fh.write<eOBJSyntaxElement::object_group>(object_name + "_" + object_mesh_name + "_" +
+ object_material_name);
+ }
+ else {
+ fh.write<eOBJSyntaxElement::object_group>(object_name + "_" + object_mesh_name);
}
- file_handler_->write<eOBJSyntaxElement::object_group>(object_name + "_" + object_mesh_name);
}
-void OBJWriter::write_object_name(const OBJMesh &obj_mesh_data) const
+void OBJWriter::write_object_name(FormatHandler<eFileType::OBJ> &fh,
+ const OBJMesh &obj_mesh_data) const
{
const char *object_name = obj_mesh_data.get_object_name();
if (export_params_.export_object_groups) {
- write_object_group(obj_mesh_data);
+ write_object_group(fh, obj_mesh_data);
return;
}
- file_handler_->write<eOBJSyntaxElement::object_name>(object_name);
+ fh.write<eOBJSyntaxElement::object_name>(object_name);
}
-void OBJWriter::write_vertex_coords(const OBJMesh &obj_mesh_data) const
+void OBJWriter::write_vertex_coords(FormatHandler<eFileType::OBJ> &fh,
+ const OBJMesh &obj_mesh_data) const
{
const int tot_vertices = obj_mesh_data.tot_vertices();
for (int i = 0; i < tot_vertices; i++) {
float3 vertex = obj_mesh_data.calc_vertex_coords(i, export_params_.scaling_factor);
- file_handler_->write<eOBJSyntaxElement::vertex_coords>(vertex[0], vertex[1], vertex[2]);
+ fh.write<eOBJSyntaxElement::vertex_coords>(vertex[0], vertex[1], vertex[2]);
}
}
-void OBJWriter::write_uv_coords(OBJMesh &r_obj_mesh_data) const
+void OBJWriter::write_uv_coords(FormatHandler<eFileType::OBJ> &fh, OBJMesh &r_obj_mesh_data) const
{
- Vector<std::array<float, 2>> uv_coords;
- /* UV indices are calculated and stored in an OBJMesh member here. */
- r_obj_mesh_data.store_uv_coords_and_indices(uv_coords);
-
- for (const std::array<float, 2> &uv_vertex : uv_coords) {
- file_handler_->write<eOBJSyntaxElement::uv_vertex_coords>(uv_vertex[0], uv_vertex[1]);
+ for (const float2 &uv_vertex : r_obj_mesh_data.get_uv_coords()) {
+ fh.write<eOBJSyntaxElement::uv_vertex_coords>(uv_vertex[0], uv_vertex[1]);
}
}
-void OBJWriter::write_poly_normals(OBJMesh &obj_mesh_data)
+void OBJWriter::write_poly_normals(FormatHandler<eFileType::OBJ> &fh, OBJMesh &obj_mesh_data)
{
- obj_mesh_data.ensure_mesh_normals();
- Vector<float3> normals;
- obj_mesh_data.store_normal_coords_and_indices(normals);
- for (const float3 &normal : normals) {
- file_handler_->write<eOBJSyntaxElement::normal>(normal[0], normal[1], normal[2]);
+ /* Poly normals should be calculated earlier via store_normal_coords_and_indices. */
+ for (const float3 &normal : obj_mesh_data.get_normal_coords()) {
+ fh.write<eOBJSyntaxElement::normal>(normal[0], normal[1], normal[2]);
}
}
-int OBJWriter::write_smooth_group(const OBJMesh &obj_mesh_data,
+int OBJWriter::write_smooth_group(FormatHandler<eFileType::OBJ> &fh,
+ const OBJMesh &obj_mesh_data,
const int poly_index,
const int last_poly_smooth_group) const
{
@@ -203,11 +211,12 @@ int OBJWriter::write_smooth_group(const OBJMesh &obj_mesh_data,
/* Group has already been written, even if it is "s 0". */
return current_group;
}
- file_handler_->write<eOBJSyntaxElement::smooth_group>(current_group);
+ fh.write<eOBJSyntaxElement::smooth_group>(current_group);
return current_group;
}
-int16_t OBJWriter::write_poly_material(const OBJMesh &obj_mesh_data,
+int16_t OBJWriter::write_poly_material(FormatHandler<eFileType::OBJ> &fh,
+ const OBJMesh &obj_mesh_data,
const int poly_index,
const int16_t last_poly_mat_nr,
std::function<const char *(int)> matname_fn) const
@@ -221,23 +230,25 @@ int16_t OBJWriter::write_poly_material(const OBJMesh &obj_mesh_data,
if (last_poly_mat_nr == current_mat_nr) {
return current_mat_nr;
}
+
if (current_mat_nr == NOT_FOUND) {
- file_handler_->write<eOBJSyntaxElement::poly_usemtl>(MATERIAL_GROUP_DISABLED);
+ fh.write<eOBJSyntaxElement::poly_usemtl>(MATERIAL_GROUP_DISABLED);
return current_mat_nr;
}
if (export_params_.export_object_groups) {
- write_object_group(obj_mesh_data);
+ write_object_group(fh, obj_mesh_data);
}
const char *mat_name = matname_fn(current_mat_nr);
if (!mat_name) {
mat_name = MATERIAL_GROUP_DISABLED;
}
- file_handler_->write<eOBJSyntaxElement::poly_usemtl>(mat_name);
+ fh.write<eOBJSyntaxElement::poly_usemtl>(mat_name);
return current_mat_nr;
}
-int16_t OBJWriter::write_vertex_group(const OBJMesh &obj_mesh_data,
+int16_t OBJWriter::write_vertex_group(FormatHandler<eFileType::OBJ> &fh,
+ const OBJMesh &obj_mesh_data,
const int poly_index,
const int16_t last_poly_vertex_group) const
{
@@ -251,11 +262,12 @@ int16_t OBJWriter::write_vertex_group(const OBJMesh &obj_mesh_data,
return current_group;
}
if (current_group == NOT_FOUND) {
- file_handler_->write<eOBJSyntaxElement::object_group>(DEFORM_GROUP_DISABLED);
- return current_group;
+ fh.write<eOBJSyntaxElement::object_group>(DEFORM_GROUP_DISABLED);
+ }
+ else {
+ fh.write<eOBJSyntaxElement::object_group>(
+ obj_mesh_data.get_poly_deform_group_name(current_group));
}
- file_handler_->write<eOBJSyntaxElement::object_group>(
- obj_mesh_data.get_poly_deform_group_name(current_group));
return current_group;
}
@@ -278,7 +290,9 @@ OBJWriter::func_vert_uv_normal_indices OBJWriter::get_poly_element_writer(
return &OBJWriter::write_vert_indices;
}
-void OBJWriter::write_poly_elements(const OBJMesh &obj_mesh_data,
+void OBJWriter::write_poly_elements(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ const OBJMesh &obj_mesh_data,
std::function<const char *(int)> matname_fn)
{
int last_poly_smooth_group = NEGATIVE_INIT;
@@ -294,16 +308,19 @@ void OBJWriter::write_poly_elements(const OBJMesh &obj_mesh_data,
Span<int> poly_uv_indices = obj_mesh_data.calc_poly_uv_indices(i);
Vector<int> poly_normal_indices = obj_mesh_data.calc_poly_normal_indices(i);
- last_poly_smooth_group = write_smooth_group(obj_mesh_data, i, last_poly_smooth_group);
- last_poly_vertex_group = write_vertex_group(obj_mesh_data, i, last_poly_vertex_group);
- last_poly_mat_nr = write_poly_material(obj_mesh_data, i, last_poly_mat_nr, matname_fn);
- (this->*poly_element_writer)(poly_vertex_indices, poly_uv_indices, poly_normal_indices);
+ last_poly_smooth_group = write_smooth_group(fh, obj_mesh_data, i, last_poly_smooth_group);
+ last_poly_vertex_group = write_vertex_group(fh, obj_mesh_data, i, last_poly_vertex_group);
+ last_poly_mat_nr = write_poly_material(fh, obj_mesh_data, i, last_poly_mat_nr, matname_fn);
+ (this->*poly_element_writer)(
+ fh, offsets, poly_vertex_indices, poly_uv_indices, poly_normal_indices);
}
}
-void OBJWriter::write_edges_indices(const OBJMesh &obj_mesh_data) const
+void OBJWriter::write_edges_indices(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ const OBJMesh &obj_mesh_data) const
{
- obj_mesh_data.ensure_mesh_edges();
+ /* Note: ensure_mesh_edges should be called before. */
const int tot_edges = obj_mesh_data.tot_edges();
for (int edge_index = 0; edge_index < tot_edges; edge_index++) {
const std::optional<std::array<int, 2>> vertex_indices =
@@ -311,13 +328,13 @@ void OBJWriter::write_edges_indices(const OBJMesh &obj_mesh_data) const
if (!vertex_indices) {
continue;
}
- file_handler_->write<eOBJSyntaxElement::edge>(
- (*vertex_indices)[0] + index_offsets_.vertex_offset + 1,
- (*vertex_indices)[1] + index_offsets_.vertex_offset + 1);
+ fh.write<eOBJSyntaxElement::edge>((*vertex_indices)[0] + offsets.vertex_offset + 1,
+ (*vertex_indices)[1] + offsets.vertex_offset + 1);
}
}
-void OBJWriter::write_nurbs_curve(const OBJCurve &obj_nurbs_data) const
+void OBJWriter::write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh,
+ const OBJCurve &obj_nurbs_data) const
{
const int total_splines = obj_nurbs_data.total_splines();
for (int spline_idx = 0; spline_idx < total_splines; spline_idx++) {
@@ -325,15 +342,15 @@ void OBJWriter::write_nurbs_curve(const OBJCurve &obj_nurbs_data) const
for (int vertex_idx = 0; vertex_idx < total_vertices; vertex_idx++) {
const float3 vertex_coords = obj_nurbs_data.vertex_coordinates(
spline_idx, vertex_idx, export_params_.scaling_factor);
- file_handler_->write<eOBJSyntaxElement::vertex_coords>(
+ fh.write<eOBJSyntaxElement::vertex_coords>(
vertex_coords[0], vertex_coords[1], vertex_coords[2]);
}
const char *nurbs_name = obj_nurbs_data.get_curve_name();
const int nurbs_degree = obj_nurbs_data.get_nurbs_degree(spline_idx);
- file_handler_->write<eOBJSyntaxElement::object_group>(nurbs_name);
- file_handler_->write<eOBJSyntaxElement::cstype>();
- file_handler_->write<eOBJSyntaxElement::nurbs_degree>(nurbs_degree);
+ fh.write<eOBJSyntaxElement::object_group>(nurbs_name);
+ fh.write<eOBJSyntaxElement::cstype>();
+ fh.write<eOBJSyntaxElement::nurbs_degree>(nurbs_degree);
/**
* The numbers written here are indices into the vertex coordinates written
* earlier, relative to the line that is going to be written.
@@ -342,23 +359,24 @@ void OBJWriter::write_nurbs_curve(const OBJCurve &obj_nurbs_data) const
* 0.0 1.0 -1 -2 -3 -4 -1 -2 -3 for a cyclic curve with 4 vertices.
*/
const int total_control_points = obj_nurbs_data.total_spline_control_points(spline_idx);
- file_handler_->write<eOBJSyntaxElement::curve_element_begin>();
+ fh.write<eOBJSyntaxElement::curve_element_begin>();
for (int i = 0; i < total_control_points; i++) {
/* "+1" to keep indices one-based, even if they're negative: i.e., -1 refers to the
* last vertex coordinate, -2 second last. */
- file_handler_->write<eOBJSyntaxElement::vertex_indices>(-((i % total_vertices) + 1));
+ fh.write<eOBJSyntaxElement::vertex_indices>(-((i % total_vertices) + 1));
}
- file_handler_->write<eOBJSyntaxElement::curve_element_end>();
+ fh.write<eOBJSyntaxElement::curve_element_end>();
/**
* In `parm u 0 0.1 ..` line:, (total control points + 2) equidistant numbers in the
* parameter range are inserted. However for curves with endpoint flag,
* first degree+1 numbers are zeroes, and last degree+1 numbers are ones
*/
+
const short flagsu = obj_nurbs_data.get_nurbs_flagu(spline_idx);
const bool cyclic = flagsu & CU_NURB_CYCLIC;
const bool endpoint = !cyclic && (flagsu & CU_NURB_ENDPOINT);
- file_handler_->write<eOBJSyntaxElement::nurbs_parameter_begin>();
+ fh.write<eOBJSyntaxElement::nurbs_parameter_begin>();
for (int i = 1; i <= total_control_points + 2; i++) {
float parm = 1.0f * i / (total_control_points + 2 + 1);
if (endpoint) {
@@ -369,21 +387,14 @@ void OBJWriter::write_nurbs_curve(const OBJCurve &obj_nurbs_data) const
parm = 1;
}
}
- file_handler_->write<eOBJSyntaxElement::nurbs_parameters>(parm);
+ fh.write<eOBJSyntaxElement::nurbs_parameters>(parm);
}
- file_handler_->write<eOBJSyntaxElement::nurbs_parameter_end>();
+ fh.write<eOBJSyntaxElement::nurbs_parameter_end>();
- file_handler_->write<eOBJSyntaxElement::nurbs_group_end>();
+ fh.write<eOBJSyntaxElement::nurbs_group_end>();
}
}
-void OBJWriter::update_index_offsets(const OBJMesh &obj_mesh_data)
-{
- index_offsets_.vertex_offset += obj_mesh_data.tot_vertices();
- index_offsets_.uv_vertex_offset += obj_mesh_data.tot_uv_vertices();
- index_offsets_.normal_offset += obj_mesh_data.tot_normal_indices();
-}
-
/* -------------------------------------------------------------------- */
/** \name .MTL writers.
* \{ */
@@ -406,18 +417,31 @@ MTLWriter::MTLWriter(const char *obj_filepath) noexcept(false)
if (!ok) {
throw std::system_error(ENAMETOOLONG, std::system_category(), "");
}
- file_handler_ = std::make_unique<FormattedFileHandler<eFileType::MTL>>(mtl_filepath_);
+ outfile_ = BLI_fopen(mtl_filepath_.c_str(), "wb");
+ if (!outfile_) {
+ throw std::system_error(errno, std::system_category(), "Cannot open file " + mtl_filepath_);
+ }
+}
+MTLWriter::~MTLWriter()
+{
+ if (outfile_) {
+ fmt_handler_.write_to_file(outfile_);
+ if (std::fclose(outfile_)) {
+ std::cerr << "Error: could not close the file '" << mtl_filepath_
+ << "' properly, it may be corrupted." << std::endl;
+ }
+ }
}
-void MTLWriter::write_header(const char *blen_filepath) const
+void MTLWriter::write_header(const char *blen_filepath)
{
using namespace std::string_literals;
const char *blen_basename = (blen_filepath && blen_filepath[0] != '\0') ?
BLI_path_basename(blen_filepath) :
"None";
- file_handler_->write<eMTLSyntaxElement::string>("# Blender "s + BKE_blender_version_string() +
- " MTL File: '" + blen_basename + "'\n");
- file_handler_->write<eMTLSyntaxElement::string>("# www.blender.org\n");
+ fmt_handler_.write<eMTLSyntaxElement::string>("# Blender "s + BKE_blender_version_string() +
+ " MTL File: '" + blen_basename + "'\n");
+ fmt_handler_.write<eMTLSyntaxElement::string>("# www.blender.org\n");
}
StringRefNull MTLWriter::mtl_file_path() const
@@ -427,18 +451,18 @@ StringRefNull MTLWriter::mtl_file_path() const
void MTLWriter::write_bsdf_properties(const MTLMaterial &mtl_material)
{
- file_handler_->write<eMTLSyntaxElement::Ns>(mtl_material.Ns);
- file_handler_->write<eMTLSyntaxElement::Ka>(
+ fmt_handler_.write<eMTLSyntaxElement::Ns>(mtl_material.Ns);
+ fmt_handler_.write<eMTLSyntaxElement::Ka>(
mtl_material.Ka.x, mtl_material.Ka.y, mtl_material.Ka.z);
- file_handler_->write<eMTLSyntaxElement::Kd>(
+ fmt_handler_.write<eMTLSyntaxElement::Kd>(
mtl_material.Kd.x, mtl_material.Kd.y, mtl_material.Kd.z);
- file_handler_->write<eMTLSyntaxElement::Ks>(
+ fmt_handler_.write<eMTLSyntaxElement::Ks>(
mtl_material.Ks.x, mtl_material.Ks.y, mtl_material.Ks.z);
- file_handler_->write<eMTLSyntaxElement::Ke>(
+ fmt_handler_.write<eMTLSyntaxElement::Ke>(
mtl_material.Ke.x, mtl_material.Ke.y, mtl_material.Ke.z);
- file_handler_->write<eMTLSyntaxElement::Ni>(mtl_material.Ni);
- file_handler_->write<eMTLSyntaxElement::d>(mtl_material.d);
- file_handler_->write<eMTLSyntaxElement::illum>(mtl_material.illum);
+ fmt_handler_.write<eMTLSyntaxElement::Ni>(mtl_material.Ni);
+ fmt_handler_.write<eMTLSyntaxElement::d>(mtl_material.d);
+ fmt_handler_.write<eMTLSyntaxElement::illum>(mtl_material.illum);
}
void MTLWriter::write_texture_map(
@@ -461,8 +485,8 @@ void MTLWriter::write_texture_map(
#define SYNTAX_DISPATCH(eMTLSyntaxElement) \
if (texture_map.key == eMTLSyntaxElement) { \
- file_handler_->write<eMTLSyntaxElement>(translation + scale + map_bump_strength, \
- texture_map.value.image_path); \
+ fmt_handler_.write<eMTLSyntaxElement>(translation + scale + map_bump_strength, \
+ texture_map.value.image_path); \
return; \
}
@@ -486,8 +510,8 @@ void MTLWriter::write_materials()
mtlmaterials_.end(),
[](const MTLMaterial &a, const MTLMaterial &b) { return a.name < b.name; });
for (const MTLMaterial &mtlmat : mtlmaterials_) {
- file_handler_->write<eMTLSyntaxElement::string>("\n");
- file_handler_->write<eMTLSyntaxElement::newmtl>(mtlmat.name);
+ fmt_handler_.write<eMTLSyntaxElement::string>("\n");
+ fmt_handler_.write<eMTLSyntaxElement::newmtl>(mtlmat.name);
write_bsdf_properties(mtlmat);
for (const Map<const eMTLSyntaxElement, tex_map_XX>::Item &texture_map :
mtlmat.texture_maps.items()) {
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh
index 7385d9fabe2..2620d65f28c 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh
@@ -49,14 +49,29 @@ struct IndexOffsets {
class OBJWriter : NonMovable, NonCopyable {
private:
const OBJExportParams &export_params_;
- std::unique_ptr<FormattedFileHandler<eFileType::OBJ>> file_handler_ = nullptr;
- IndexOffsets index_offsets_{0, 0, 0};
+ std::string outfile_path_;
+ FILE *outfile_;
public:
OBJWriter(const char *filepath, const OBJExportParams &export_params) noexcept(false)
- : export_params_(export_params)
+ : export_params_(export_params), outfile_path_(filepath), outfile_(nullptr)
{
- file_handler_ = std::make_unique<FormattedFileHandler<eFileType::OBJ>>(filepath);
+ outfile_ = BLI_fopen(filepath, "wb");
+ if (!outfile_) {
+ throw std::system_error(errno, std::system_category(), "Cannot open file " + outfile_path_);
+ }
+ }
+ ~OBJWriter()
+ {
+ if (outfile_ && std::fclose(outfile_)) {
+ std::cerr << "Error: could not close the file '" << outfile_path_
+ << "' properly, it may be corrupted." << std::endl;
+ }
+ }
+
+ FILE *get_outfile() const
+ {
+ return outfile_;
}
void write_header() const;
@@ -64,11 +79,11 @@ class OBJWriter : NonMovable, NonCopyable {
/**
* Write object's name or group.
*/
- void write_object_name(const OBJMesh &obj_mesh_data) const;
+ void write_object_name(FormatHandler<eFileType::OBJ> &fh, const OBJMesh &obj_mesh_data) const;
/**
* Write an object's group with mesh and/or material name appended conditionally.
*/
- void write_object_group(const OBJMesh &obj_mesh_data) const;
+ void write_object_group(FormatHandler<eFileType::OBJ> &fh, const OBJMesh &obj_mesh_data) const;
/**
* Write file name of Material Library in .OBJ file.
*/
@@ -76,21 +91,22 @@ class OBJWriter : NonMovable, NonCopyable {
/**
* Write vertex coordinates for all vertices as "v x y z".
*/
- void write_vertex_coords(const OBJMesh &obj_mesh_data) const;
+ void write_vertex_coords(FormatHandler<eFileType::OBJ> &fh, const OBJMesh &obj_mesh_data) const;
/**
* Write UV vertex coordinates for all vertices as `vt u v`.
* \note UV indices are stored here, but written with polygons later.
*/
- void write_uv_coords(OBJMesh &obj_mesh_data) const;
+ void write_uv_coords(FormatHandler<eFileType::OBJ> &fh, OBJMesh &obj_mesh_data) const;
/**
* Write loop normals for smooth-shaded polygons, and polygon normals otherwise, as "vn x y z".
* \note Normal indices ares stored here, but written with polygons later.
*/
- void write_poly_normals(OBJMesh &obj_mesh_data);
+ void write_poly_normals(FormatHandler<eFileType::OBJ> &fh, OBJMesh &obj_mesh_data);
/**
* Write smooth group if polygon at the given index is shaded smooth else "s 0"
*/
- int write_smooth_group(const OBJMesh &obj_mesh_data,
+ int write_smooth_group(FormatHandler<eFileType::OBJ> &fh,
+ const OBJMesh &obj_mesh_data,
int poly_index,
int last_poly_smooth_group) const;
/**
@@ -98,14 +114,16 @@ class OBJWriter : NonMovable, NonCopyable {
* \return #mat_nr of the polygon at the given index.
* \note It doesn't write to the material library.
*/
- int16_t write_poly_material(const OBJMesh &obj_mesh_data,
+ int16_t write_poly_material(FormatHandler<eFileType::OBJ> &fh,
+ const OBJMesh &obj_mesh_data,
int poly_index,
int16_t last_poly_mat_nr,
std::function<const char *(int)> matname_fn) const;
/**
* Write the name of the deform group of a polygon.
*/
- int16_t write_vertex_group(const OBJMesh &obj_mesh_data,
+ int16_t write_vertex_group(FormatHandler<eFileType::OBJ> &fh,
+ const OBJMesh &obj_mesh_data,
int poly_index,
int16_t last_poly_vertex_group) const;
/**
@@ -115,25 +133,25 @@ class OBJWriter : NonMovable, NonCopyable {
* name used in the .obj file.
* \note UV indices were stored while writing UV vertices.
*/
- void write_poly_elements(const OBJMesh &obj_mesh_data,
+ void write_poly_elements(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ const OBJMesh &obj_mesh_data,
std::function<const char *(int)> matname_fn);
/**
* Write loose edges of a mesh as "l v1 v2".
*/
- void write_edges_indices(const OBJMesh &obj_mesh_data) const;
+ void write_edges_indices(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ const OBJMesh &obj_mesh_data) const;
/**
* Write a NURBS curve to the .OBJ file in parameter form.
*/
- void write_nurbs_curve(const OBJCurve &obj_nurbs_data) const;
-
- /**
- * When there are multiple objects in a frame, the indices of previous objects' coordinates or
- * normals add up.
- */
- void update_index_offsets(const OBJMesh &obj_mesh_data);
+ void write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh, const OBJCurve &obj_nurbs_data) const;
private:
- using func_vert_uv_normal_indices = void (OBJWriter::*)(Span<int> vert_indices,
+ using func_vert_uv_normal_indices = void (OBJWriter::*)(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ Span<int> vert_indices,
Span<int> uv_indices,
Span<int> normal_indices) const;
/**
@@ -144,25 +162,33 @@ class OBJWriter : NonMovable, NonCopyable {
/**
* Write one line of polygon indices as "f v1/vt1/vn1 v2/vt2/vn2 ...".
*/
- void write_vert_uv_normal_indices(Span<int> vert_indices,
+ void write_vert_uv_normal_indices(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ Span<int> vert_indices,
Span<int> uv_indices,
Span<int> normal_indices) const;
/**
* Write one line of polygon indices as "f v1//vn1 v2//vn2 ...".
*/
- void write_vert_normal_indices(Span<int> vert_indices,
+ void write_vert_normal_indices(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ Span<int> vert_indices,
Span<int> /*uv_indices*/,
Span<int> normal_indices) const;
/**
* Write one line of polygon indices as "f v1/vt1 v2/vt2 ...".
*/
- void write_vert_uv_indices(Span<int> vert_indices,
+ void write_vert_uv_indices(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ Span<int> vert_indices,
Span<int> uv_indices,
Span<int> /*normal_indices*/) const;
/**
* Write one line of polygon indices as "f v1 v2 ...".
*/
- void write_vert_indices(Span<int> vert_indices,
+ void write_vert_indices(FormatHandler<eFileType::OBJ> &fh,
+ const IndexOffsets &offsets,
+ Span<int> vert_indices,
Span<int> /*uv_indices*/,
Span<int> /*normal_indices*/) const;
};
@@ -172,7 +198,8 @@ class OBJWriter : NonMovable, NonCopyable {
*/
class MTLWriter : NonMovable, NonCopyable {
private:
- std::unique_ptr<FormattedFileHandler<eFileType::MTL>> file_handler_ = nullptr;
+ FormatHandler<eFileType::MTL> fmt_handler_;
+ FILE *outfile_;
std::string mtl_filepath_;
Vector<MTLMaterial> mtlmaterials_;
/* Map from a Material* to an index into mtlmaterials_. */
@@ -183,8 +210,9 @@ class MTLWriter : NonMovable, NonCopyable {
* Create the .MTL file.
*/
MTLWriter(const char *obj_filepath) noexcept(false);
+ ~MTLWriter();
- void write_header(const char *blen_filepath) const;
+ void write_header(const char *blen_filepath);
/**
* Write all of the material specifications to the MTL file.
* For consistency of output from run to run (useful for testing),
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh
index 2eb2b66335d..e5b731aa51d 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh
@@ -24,6 +24,7 @@
#include <string>
#include <system_error>
#include <type_traits>
+#include <vector>
#include "BLI_compiler_attrs.h"
#include "BLI_fileops.h"
@@ -124,6 +125,14 @@ constexpr bool is_type_integral = (... && std::is_integral_v<std::decay_t<T>>);
template<typename... T>
constexpr bool is_type_string_related = (... && std::is_constructible_v<std::string, T>);
+/* GCC (at least 9.3) while compiling the obj_exporter_tests.cc with optimizations on,
+ * results in "obj_export_io.hh:205:18: warning: ‘%s’ directive output truncated writing 34 bytes
+ * into a region of size 6" and similar warnings. Yes the output is truncated, and that is covered
+ * as an edge case by tests on purpose. */
+#if defined __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-truncation"
+#endif
template<typename... T>
constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key)
{
@@ -264,31 +273,44 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eMTLSyntaxElement key
}
}
}
+#if defined __GNUC__
+# pragma GCC diagnostic pop
+#endif
/**
- * File format and syntax agnostic file writer.
+ * File format and syntax agnostic file buffer writer.
+ * All writes are done into an internal chunked memory buffer
+ * (list of default 64 kilobyte blocks).
+ * Call write_fo_file once in a while to write the memory buffer(s)
+ * into the given file.
*/
-template<eFileType filetype> class FormattedFileHandler : NonCopyable, NonMovable {
+template<eFileType filetype,
+ size_t buffer_chunk_size = 64 * 1024,
+ size_t write_local_buffer_size = 1024>
+class FormatHandler : NonCopyable, NonMovable {
private:
- std::FILE *outfile_ = nullptr;
- std::string outfile_path_;
+ typedef std::vector<char> VectorChar;
+ std::vector<VectorChar> blocks_;
public:
- FormattedFileHandler(std::string outfile_path) noexcept(false)
- : outfile_path_(std::move(outfile_path))
+ /* Write contents to the buffer(s) into a file, and clear the buffers. */
+ void write_to_file(FILE *f)
{
- outfile_ = BLI_fopen(outfile_path_.c_str(), "w");
- if (!outfile_) {
- throw std::system_error(errno, std::system_category(), "Cannot open file " + outfile_path_);
- }
+ for (const auto &b : blocks_)
+ fwrite(b.data(), 1, b.size(), f);
+ blocks_.clear();
}
- ~FormattedFileHandler()
+ std::string get_as_string() const
{
- if (outfile_ && std::fclose(outfile_)) {
- std::cerr << "Error: could not close the file '" << outfile_path_
- << "' properly, it may be corrupted." << std::endl;
- }
+ std::string s;
+ for (const auto &b : blocks_)
+ s.append(b.data(), b.size());
+ return s;
+ }
+ size_t get_block_count() const
+ {
+ return blocks_.size();
}
/**
@@ -298,7 +320,7 @@ template<eFileType filetype> class FormattedFileHandler : NonCopyable, NonMovabl
* `eFileType::MTL`.
*/
template<typename FileTypeTraits<filetype>::SyntaxType key, typename... T>
- constexpr void write(T &&...args) const
+ constexpr void write(T &&...args)
{
/* Get format syntax, number of arguments expected and whether types of given arguments are
* valid.
@@ -339,13 +361,47 @@ template<eFileType filetype> class FormattedFileHandler : NonCopyable, NonMovabl
}
}
- template<typename... T> constexpr void write_impl(const char *fmt, T &&...args) const
+ /* Ensure the last block contains at least this amount of free space.
+ * If not, add a new block with max of block size & the amount of space needed. */
+ void ensure_space(size_t at_least)
+ {
+ if (blocks_.empty() || (blocks_.back().capacity() - blocks_.back().size() < at_least)) {
+ VectorChar &b = blocks_.emplace_back(VectorChar());
+ b.reserve(std::max(at_least, buffer_chunk_size));
+ }
+ }
+
+ template<typename... T> constexpr void write_impl(const char *fmt, T &&...args)
{
if constexpr (sizeof...(T) == 0) {
- std::fputs(fmt, outfile_);
+ /* No arguments: just emit the format string. */
+ size_t len = strlen(fmt);
+ ensure_space(len);
+ VectorChar &bb = blocks_.back();
+ bb.insert(bb.end(), fmt, fmt + len);
}
else {
- std::fprintf(outfile_, fmt, convert_to_primitive(std::forward<T>(args))...);
+ /* Format into a local buffer. */
+ char buf[write_local_buffer_size];
+ int needed = std::snprintf(
+ buf, write_local_buffer_size, fmt, convert_to_primitive(std::forward<T>(args))...);
+ if (needed < 0)
+ throw std::system_error(
+ errno, std::system_category(), "Failed to format obj export string into a buffer");
+ ensure_space(needed + 1); /* Ensure space for zero terminator. */
+ VectorChar &bb = blocks_.back();
+ if (needed < write_local_buffer_size) {
+ /* String formatted successfully into the local buffer, copy it. */
+ bb.insert(bb.end(), buf, buf + needed);
+ }
+ else {
+ /* Would need more space than the local buffer: insert said space and format again into
+ * that. */
+ size_t bbEnd = bb.size();
+ bb.insert(bb.end(), needed, ' ');
+ std::snprintf(
+ bb.data() + bbEnd, needed + 1, fmt, convert_to_primitive(std::forward<T>(args))...);
+ }
}
}
};
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
index 14e50d726c0..468631cdd82 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
@@ -69,16 +69,28 @@ OBJMesh::OBJMesh(Depsgraph *depsgraph, const OBJExportParams &export_params, Obj
*/
OBJMesh::~OBJMesh()
{
- free_mesh_if_needed();
- if (poly_smooth_groups_) {
- MEM_freeN(poly_smooth_groups_);
- }
+ clear();
}
void OBJMesh::free_mesh_if_needed()
{
if (mesh_eval_needs_free_ && export_mesh_eval_) {
BKE_id_free(nullptr, export_mesh_eval_);
+ export_mesh_eval_ = nullptr;
+ mesh_eval_needs_free_ = false;
+ }
+}
+
+void OBJMesh::clear()
+{
+ free_mesh_if_needed();
+ uv_indices_.clear_and_make_inline();
+ uv_coords_.clear_and_make_inline();
+ loop_to_normal_index_.clear_and_make_inline();
+ normal_coords_.clear_and_make_inline();
+ if (poly_smooth_groups_) {
+ MEM_freeN(poly_smooth_groups_);
+ poly_smooth_groups_ = nullptr;
}
}
@@ -256,7 +268,7 @@ Vector<int> OBJMesh::calc_poly_vertex_indices(const int poly_index) const
return r_poly_vertex_indices;
}
-void OBJMesh::store_uv_coords_and_indices(Vector<std::array<float, 2>> &r_uv_coords)
+void OBJMesh::store_uv_coords_and_indices()
{
const MPoly *mpoly = export_mesh_eval_->mpoly;
const MLoop *mloop = export_mesh_eval_->mloop;
@@ -276,7 +288,7 @@ void OBJMesh::store_uv_coords_and_indices(Vector<std::array<float, 2>> &r_uv_coo
uv_indices_.resize(totpoly);
/* At least total vertices of a mesh will be present in its texture map. So
* reserve minimum space early. */
- r_uv_coords.reserve(totvert);
+ uv_coords_.reserve(totvert);
tot_uv_vertices_ = 0;
for (int vertex_index = 0; vertex_index < totvert; vertex_index++) {
@@ -288,11 +300,10 @@ void OBJMesh::store_uv_coords_and_indices(Vector<std::array<float, 2>> &r_uv_coo
const int vertices_in_poly = mpoly[uv_vert->poly_index].totloop;
/* Store UV vertex coordinates. */
- r_uv_coords.resize(tot_uv_vertices_);
+ uv_coords_.resize(tot_uv_vertices_);
const int loopstart = mpoly[uv_vert->poly_index].loopstart;
Span<float> vert_uv_coords(mloopuv[loopstart + uv_vert->loop_of_poly_index].uv, 2);
- r_uv_coords[tot_uv_vertices_ - 1][0] = vert_uv_coords[0];
- r_uv_coords[tot_uv_vertices_ - 1][1] = vert_uv_coords[1];
+ uv_coords_[tot_uv_vertices_ - 1] = float2(vert_uv_coords[0], vert_uv_coords[1]);
/* Store UV vertex indices. */
uv_indices_[uv_vert->poly_index].resize(vertices_in_poly);
@@ -340,7 +351,7 @@ static float3 round_float3_to_n_digits(const float3 &v, int round_digits)
return ans;
}
-void OBJMesh::store_normal_coords_and_indices(Vector<float3> &r_normal_coords)
+void OBJMesh::store_normal_coords_and_indices()
{
/* We'll round normal components to 4 digits.
* This will cover up some minor differences
@@ -371,7 +382,7 @@ void OBJMesh::store_normal_coords_and_indices(Vector<float3> &r_normal_coords)
if (loop_norm_index == -1) {
loop_norm_index = cur_normal_index++;
normal_to_index.add(rounded_loop_normal, loop_norm_index);
- r_normal_coords.append(rounded_loop_normal);
+ normal_coords_.append(rounded_loop_normal);
}
loop_to_normal_index_[loop_index] = loop_norm_index;
}
@@ -383,7 +394,7 @@ void OBJMesh::store_normal_coords_and_indices(Vector<float3> &r_normal_coords)
if (poly_norm_index == -1) {
poly_norm_index = cur_normal_index++;
normal_to_index.add(rounded_poly_normal, poly_norm_index);
- r_normal_coords.append(rounded_poly_normal);
+ normal_coords_.append(rounded_poly_normal);
}
for (int i = 0; i < mpoly.totloop; ++i) {
int loop_index = mpoly.loopstart + i;
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh
index f3ace140006..4cfbffdcebc 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh
@@ -82,11 +82,19 @@ class OBJMesh : NonCopyable {
* Per-polygon-per-vertex UV vertex indices.
*/
Vector<Vector<int>> uv_indices_;
+ /*
+ * UV vertices.
+ */
+ Vector<float2> uv_coords_;
/**
* Per-loop normal index.
*/
Vector<int> loop_to_normal_index_;
/*
+ * Normal coords.
+ */
+ Vector<float3> normal_coords_;
+ /*
* Total number of normal indices (maximum entry, plus 1, in
* the loop_to_norm_index_ vector).
*/
@@ -108,6 +116,9 @@ class OBJMesh : NonCopyable {
OBJMesh(Depsgraph *depsgraph, const OBJExportParams &export_params, Object *mesh_object);
~OBJMesh();
+ /* Clear various arrays to release potentially large memory allocations. */
+ void clear();
+
int tot_vertices() const;
int tot_polygons() const;
int tot_uv_vertices() const;
@@ -165,10 +176,14 @@ class OBJMesh : NonCopyable {
Vector<int> calc_poly_vertex_indices(int poly_index) const;
/**
* Calculate UV vertex coordinates of an Object.
- *
- * \note Also store the UV vertex indices in the member variable.
+ * Stores the coordinates and UV vertex indices in the member variables.
*/
- void store_uv_coords_and_indices(Vector<std::array<float, 2>> &r_uv_coords);
+ void store_uv_coords_and_indices();
+ /* Get UV coordinates computed by store_uv_coords_and_indices. */
+ const Vector<float2> &get_uv_coords() const
+ {
+ return uv_coords_;
+ }
Span<int> calc_poly_uv_indices(int poly_index) const;
/**
* Calculate polygon normal of a polygon at given index.
@@ -177,10 +192,15 @@ class OBJMesh : NonCopyable {
*/
float3 calc_poly_normal(int poly_index) const;
/**
- * Find the unique normals of the mesh and return them in \a r_normal_coords.
- * Store the indices into that vector with for each loop in this #OBJMesh.
+ * Find the unique normals of the mesh and stores them in a member variable.
+ * Also stores the indices into that vector with for each loop.
*/
- void store_normal_coords_and_indices(Vector<float3> &r_normal_coords);
+ void store_normal_coords_and_indices();
+ /* Get normals calculate by store_normal_coords_and_indices. */
+ const Vector<float3> &get_normal_coords() const
+ {
+ return normal_coords_;
+ }
/**
* Calculate a polygon's polygon/loop normal indices.
* \param poly_index Index of the polygon to calculate indices for.
diff --git a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc
index 0c753ccdcac..187f50277f1 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc
@@ -25,6 +25,7 @@
#include "BKE_scene.h"
#include "BLI_path_util.h"
+#include "BLI_task.hh"
#include "BLI_vector.hh"
#include "DEG_depsgraph_query.h"
@@ -155,44 +156,97 @@ static void write_mesh_objects(Vector<std::unique_ptr<OBJMesh>> exportable_as_me
MTLWriter *mtl_writer,
const OBJExportParams &export_params)
{
+ /* Parallelization is over meshes/objects, which means
+ * we have to have the output text buffer for each object,
+ * and write them all into the file at the end. */
+ size_t count = exportable_as_mesh.size();
+ std::vector<FormatHandler<eFileType::OBJ>> buffers(count);
+
+ /* Serial: gather material indices, ensure normals & edges. */
+ Vector<Vector<int>> mtlindices;
if (mtl_writer) {
obj_writer.write_mtllib_name(mtl_writer->mtl_file_path());
+ mtlindices.reserve(count);
}
-
- /* Smooth groups and UV vertex indices may make huge memory allocations, so they should be freed
- * right after they're written, instead of waiting for #blender::Vector to clean them up after
- * all the objects are exported. */
for (auto &obj_mesh : exportable_as_mesh) {
- obj_writer.write_object_name(*obj_mesh);
- obj_writer.write_vertex_coords(*obj_mesh);
- Vector<int> obj_mtlindices;
+ OBJMesh &obj = *obj_mesh;
+ if (mtl_writer) {
+ mtlindices.append(mtl_writer->add_materials(obj));
+ }
+ if (export_params.export_normals) {
+ obj.ensure_mesh_normals();
+ }
+ obj.ensure_mesh_edges();
+ }
- if (obj_mesh->tot_polygons() > 0) {
- if (export_params.export_smooth_groups) {
- obj_mesh->calc_smooth_groups(export_params.smooth_groups_bitflags);
- }
+ /* Parallel over meshes: store normal coords & indices, uv coords and indices. */
+ blender::threading::parallel_for(IndexRange(count), 1, [&](IndexRange range) {
+ for (const int i : range) {
+ OBJMesh &obj = *exportable_as_mesh[i];
if (export_params.export_normals) {
- obj_writer.write_poly_normals(*obj_mesh);
+ obj.store_normal_coords_and_indices();
}
if (export_params.export_uv) {
- obj_writer.write_uv_coords(*obj_mesh);
- }
- if (mtl_writer) {
- obj_mtlindices = mtl_writer->add_materials(*obj_mesh);
+ obj.store_uv_coords_and_indices();
}
- /* This function takes a 0-indexed slot index for the obj_mesh object and
- * returns the material name that we are using in the .obj file for it. */
- std::function<const char *(int)> matname_fn = [&](int s) -> const char * {
- if (!mtl_writer || s < 0 || s >= obj_mtlindices.size()) {
- return nullptr;
+ }
+ });
+
+ /* Serial: calculate index offsets; these are sequentially added
+ * over all meshes, and requite normal/uv indices to be calculated. */
+ Vector<IndexOffsets> index_offsets;
+ index_offsets.reserve(count);
+ IndexOffsets offsets{0, 0, 0};
+ for (auto &obj_mesh : exportable_as_mesh) {
+ OBJMesh &obj = *obj_mesh;
+ index_offsets.append(offsets);
+ offsets.vertex_offset += obj.tot_vertices();
+ offsets.uv_vertex_offset += obj.tot_uv_vertices();
+ offsets.normal_offset += obj.tot_normal_indices();
+ }
+
+ /* Parallel over meshes: main result writing. */
+ blender::threading::parallel_for(IndexRange(count), 1, [&](IndexRange range) {
+ for (const int i : range) {
+ OBJMesh &obj = *exportable_as_mesh[i];
+ auto &fh = buffers[i];
+
+ obj_writer.write_object_name(fh, obj);
+ obj_writer.write_vertex_coords(fh, obj);
+
+ if (obj.tot_polygons() > 0) {
+ if (export_params.export_smooth_groups) {
+ obj.calc_smooth_groups(export_params.smooth_groups_bitflags);
+ }
+ if (export_params.export_normals) {
+ obj_writer.write_poly_normals(fh, obj);
}
- return mtl_writer->mtlmaterial_name(obj_mtlindices[s]);
- };
- obj_writer.write_poly_elements(*obj_mesh, matname_fn);
+ if (export_params.export_uv) {
+ obj_writer.write_uv_coords(fh, obj);
+ }
+ /* This function takes a 0-indexed slot index for the obj_mesh object and
+ * returns the material name that we are using in the .obj file for it. */
+ const auto *obj_mtlindices = mtlindices.is_empty() ? nullptr : &mtlindices[i];
+ std::function<const char *(int)> matname_fn = [&](int s) -> const char * {
+ if (!obj_mtlindices || s < 0 || s >= obj_mtlindices->size()) {
+ return nullptr;
+ }
+ return mtl_writer->mtlmaterial_name((*obj_mtlindices)[s]);
+ };
+ obj_writer.write_poly_elements(fh, index_offsets[i], obj, matname_fn);
+ }
+ obj_writer.write_edges_indices(fh, index_offsets[i], obj);
+
+ /* Nothing will need this object's data after this point, release
+ * various arrays here. */
+ obj.clear();
}
- obj_writer.write_edges_indices(*obj_mesh);
+ });
- obj_writer.update_index_offsets(*obj_mesh);
+ /* Write all the object text buffers into the output file. */
+ FILE *f = obj_writer.get_outfile();
+ for (auto &b : buffers) {
+ b.write_to_file(f);
}
}
@@ -202,11 +256,13 @@ static void write_mesh_objects(Vector<std::unique_ptr<OBJMesh>> exportable_as_me
static void write_nurbs_curve_objects(const Vector<std::unique_ptr<OBJCurve>> &exportable_as_nurbs,
const OBJWriter &obj_writer)
{
+ FormatHandler<eFileType::OBJ> fh;
/* #OBJCurve doesn't have any dynamically allocated memory, so it's fine
* to wait for #blender::Vector to clean the objects up. */
for (const std::unique_ptr<OBJCurve> &obj_curve : exportable_as_nurbs) {
- obj_writer.write_nurbs_curve(*obj_curve);
+ obj_writer.write_nurbs_curve(fh, *obj_curve);
}
+ fh.write_to_file(obj_writer.get_outfile());
}
void export_frame(Depsgraph *depsgraph, const OBJExportParams &export_params, const char *filepath)
diff --git a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
index ecae93f8f7a..01f201897cf 100644
--- a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
+++ b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
@@ -238,6 +238,38 @@ TEST(obj_exporter_writer, mtllib)
BLI_delete(out_file_path.c_str(), false, false);
}
+TEST(obj_exporter_writer, format_handler_buffer_chunking)
+{
+ /* Use a tiny buffer chunk size, so that the test below ends up creating several blocks. */
+ FormatHandler<eFileType::OBJ, 16, 8> h;
+ h.write<eOBJSyntaxElement::object_name>("abc");
+ h.write<eOBJSyntaxElement::object_name>("abcd");
+ h.write<eOBJSyntaxElement::object_name>("abcde");
+ h.write<eOBJSyntaxElement::object_name>("abcdef");
+ h.write<eOBJSyntaxElement::object_name>("012345678901234567890123456789abcd");
+ h.write<eOBJSyntaxElement::object_name>("123");
+ h.write<eOBJSyntaxElement::curve_element_begin>();
+ h.write<eOBJSyntaxElement::new_line>();
+ h.write<eOBJSyntaxElement::nurbs_parameter_begin>();
+ h.write<eOBJSyntaxElement::new_line>();
+
+ size_t got_blocks = h.get_block_count();
+ ASSERT_EQ(got_blocks, 7);
+
+ std::string got_string = h.get_as_string();
+ using namespace std::string_literals;
+ const char *expected = R"(o abc
+o abcd
+o abcde
+o abcdef
+o 012345678901234567890123456789abcd
+o 123
+curv 0.0 1.0
+parm u 0.0
+)";
+ ASSERT_EQ(got_string, expected);
+}
+
/* Return true if string #a and string #b are equal after their first newline. */
static bool strings_equal_after_first_lines(const std::string &a, const std::string &b)
{
@@ -385,8 +417,10 @@ TEST_F(obj_exporter_regression_test, nurbs_curves_as_nurbs)
_export.params.up_axis = OBJ_AXIS_Z_UP;
_export.params.export_materials = false;
_export.params.export_curves_as_nurbs = true;
- compare_obj_export_to_golden(
- "io_tests/blend_geometry/nurbs_curves.blend", "io_tests/obj/nurbs_curves.obj", "", _export.params);
+ compare_obj_export_to_golden("io_tests/blend_geometry/nurbs_curves.blend",
+ "io_tests/obj/nurbs_curves.obj",
+ "",
+ _export.params);
}
TEST_F(obj_exporter_regression_test, nurbs_as_mesh)
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 82b20483902..1ca724b7108 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -478,9 +478,6 @@ typedef struct bPose {
short flag;
char _pad[2];
- /** Proxy layer: copy from armature, gets synced. */
- unsigned int proxy_layer;
- char _pad1[4];
/** Local action time of this pose. */
float ctime;
@@ -503,8 +500,6 @@ typedef struct bPose {
/** Settings for visualization of bone animation. */
bAnimVizSettings avs;
- /** Proxy active bone name, MAXBONENAME. */
- char proxy_act_bone[64];
} bPose;
/* Pose->flag */
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index 566ffd19669..1005b5186aa 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -77,7 +77,7 @@ typedef struct Bone {
/** dist, weight: for non-deformgroup deforms. */
float dist, weight;
/**
- * The width for block bones.
+ * The width for block bones. The final X/Z bone widths are double these values.
*
* \note keep in this order for transform code which stores a pointer to `xwidth`,
* accessing length and `zwidth` as offsets.
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index d587bd8082b..53b1a60e53e 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -714,8 +714,6 @@ typedef enum eBConstraint_Flags {
CONSTRAINT_SPACEONCE = (1 << 6),
/* influence ipo is on constraint itself, not in action channel */
CONSTRAINT_OWN_IPO = (1 << 7),
- /* indicates that constraint was added locally (i.e. didn't come from the proxy-lib) */
- CONSTRAINT_PROXY_LOCAL = (1 << 8),
/* indicates that constraint is temporarily disabled (only used in GE) */
CONSTRAINT_OFF = (1 << 9),
/* use bbone curve shape when calculating headtail values (also used by dependency graph!) */
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index 629a5e88de7..9c34d78c944 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -162,8 +162,8 @@ typedef enum CustomDataType {
/* CD_LOCATION = 43, */ /* UNUSED */
/* CD_RADIUS = 44, */ /* UNUSED */
- CD_HAIRCURVE = 45,
- CD_HAIRMAPPING = 46,
+ CD_PROP_INT8 = 45,
+ /* CD_HAIRMAPPING = 46, */ /* UNUSED, can be reused. */
CD_PROP_COLOR = 47,
CD_PROP_FLOAT3 = 48,
@@ -223,6 +223,7 @@ typedef enum CustomDataType {
#define CD_MASK_PROP_FLOAT3 (1ULL << CD_PROP_FLOAT3)
#define CD_MASK_PROP_FLOAT2 (1ULL << CD_PROP_FLOAT2)
#define CD_MASK_PROP_BOOL (1ULL << CD_PROP_BOOL)
+#define CD_MASK_PROP_INT8 (1ULL << CD_PROP_INT8)
#define CD_MASK_HAIRLENGTH (1ULL << CD_HAIRLENGTH)
@@ -235,7 +236,8 @@ typedef enum CustomDataType {
/* All generic attributes. */
#define CD_MASK_PROP_ALL \
(CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 | CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 | \
- CD_MASK_PROP_COLOR | CD_MASK_PROP_STRING | CD_MASK_MLOOPCOL | CD_MASK_PROP_BOOL)
+ CD_MASK_PROP_COLOR | CD_MASK_PROP_STRING | CD_MASK_MLOOPCOL | CD_MASK_PROP_BOOL | \
+ CD_MASK_PROP_INT8)
typedef struct CustomData_MeshMasks {
uint64_t vmask;
diff --git a/source/blender/makesdna/DNA_hair_types.h b/source/blender/makesdna/DNA_hair_types.h
index 2e819b32033..5d54a4bb8cc 100644
--- a/source/blender/makesdna/DNA_hair_types.h
+++ b/source/blender/makesdna/DNA_hair_types.h
@@ -27,48 +27,71 @@
extern "C" {
#endif
-typedef struct HairCurve {
- /* Index of first point of hair curve. */
- int firstpoint;
- /* Number of points in hair curve, must be 2 or higher. */
- int numpoints;
-} HairCurve;
-
-/* Hair attachment to a mesh.
- * TODO: attach to tessellated triangles or polygons?
- * TODO: what type of interpolation to use for uv? */
-typedef struct HairMapping {
- float uv[2];
- int poly;
-} HairMapping;
+/**
+ * A reusable data structure for geometry consisting of many curves. All control point data is
+ * stored contiguously for better efficiency. Data for each curve is stored as a slice of the
+ * main #point_data array.
+ *
+ * The data structure is meant to be embedded in other data-blocks to allow reusing
+ * curve-processing algorithms for multiple Blender data-block types.
+ */
+typedef struct CurvesGeometry {
+ /**
+ * A runtime pointer to the "position" attribute data.
+ * \note This data is owned by #point_data.
+ */
+ float (*position)[3];
+ /**
+ * A runtime pointer to the "radius" attribute data.
+ * \note This data is owned by #point_data.
+ */
+ float *radius;
+
+ /**
+ * The start index of each curve in the point data. The size of each curve can be calculated by
+ * subtracting the offset from the next offset. That is valid even for the last curve because
+ * this array is allocated with a length one larger than the number of splines.
+ *
+ * \note This is *not* stored in #CustomData because its size is one larger than #curve_data.
+ */
+ int *offsets;
+
+ /**
+ * All attributes stored on control points (#ATTR_DOMAIN_POINT).
+ */
+ CustomData point_data;
+
+ /**
+ * All attributes stored on curves (#ATTR_DOMAIN_CURVE).
+ */
+ CustomData curve_data;
+
+ /**
+ * The total number of control points in all curves.
+ */
+ int point_size;
+ /**
+ * The number of curves in the data-block.
+ */
+ int curve_size;
+} CurvesGeometry;
typedef struct Hair {
ID id;
- struct AnimData *adt; /* animation data (must be immediately after id) */
+ /* Animation data (must be immediately after id). */
+ struct AnimData *adt;
- int flag;
- int _pad1[1];
+ CurvesGeometry geometry;
- /* Geometry */
- float (*co)[3];
- float *radius;
- struct HairCurve *curves;
- struct HairMaping *mapping;
- int totpoint;
- int totcurve;
-
- /* Custom Data */
- struct CustomData pdata;
- struct CustomData cdata;
+ int flag;
int attributes_active_index;
- int _pad3;
- /* Material */
+ /* Materials. */
struct Material **mat;
short totcol;
short _pad2[3];
- /* Draw Cache */
+ /* Draw Cache. */
void *batch_cache;
} Hair;
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 22c523901c0..f2493bd5b85 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -48,7 +48,6 @@ typedef struct MVert {
/** #MVert.flag */
enum {
/* SELECT = (1 << 0), */
- ME_VERT_TMP_TAG = (1 << 2),
ME_HIDE = (1 << 4),
ME_VERT_FACEDOT = (1 << 5),
/* ME_VERT_MERGED = (1 << 6), */
@@ -266,6 +265,9 @@ typedef struct MStringProperty {
typedef struct MBoolProperty {
uint8_t b;
} MBoolProperty;
+typedef struct MInt8Property {
+ int8_t i;
+} MInt8Property;
/** \} */
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 2bfd2e71eb7..fd77e8b9f1d 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -514,8 +514,10 @@ typedef struct bNodeTree {
/** Information about how inputs and outputs of the node group interact with fields. */
FieldInferencingInterfaceHandle *field_inferencing_interface;
- /** Set init on fileread. */
- int type, init;
+ int type;
+
+ char _pad1[4];
+
/**
* Sockets in groups have unique identifiers, adding new sockets always
* will increase this counter.
@@ -599,9 +601,6 @@ typedef struct bNodeTree {
#define NTREE_TEXTURE 2
#define NTREE_GEOMETRY 3
-/** #NodeTree.init, flag */
-#define NTREE_TYPE_INIT 1
-
/** #NodeTree.flag */
#define NTREE_DS_EXPAND (1 << 0) /* for animation editors */
#define NTREE_COM_OPENCL (1 << 1) /* use opencl */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 602f968634e..ce735ad79c4 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -263,9 +263,10 @@ typedef struct Object {
/** String describing subobject info, MAX_ID_NAME-2. */
char parsubstr[64];
struct Object *parent, *track;
- /* If `ob->proxy` (or proxy_group), this object is proxy for object `ob->proxy`. */
- /* proxy_from is set in target back to the proxy. */
- struct Object *proxy, *proxy_group, *proxy_from;
+ /* Proxy pointer are deprecated, only kept for conversion to liboverrides. */
+ struct Object *proxy DNA_DEPRECATED;
+ struct Object *proxy_group DNA_DEPRECATED;
+ struct Object *proxy_from DNA_DEPRECATED;
/** Old animation system, deprecated for 2.5. */
struct Ipo *ipo DNA_DEPRECATED;
/* struct Path *path; */
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index a50d0524998..71a5c0eb2e5 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -101,7 +101,7 @@ typedef enum eTreeStoreElemType {
TSE_DRIVER_BASE = 16, /* NO ID */
/* TSE_DRIVER = 17, */ /* UNUSED */
- TSE_PROXY = 18,
+ /* TSE_PROXY = 18, */ /* UNUSED */
TSE_R_LAYER_BASE = 19,
TSE_R_LAYER = 20,
/* TSE_R_PASS = 21, */ /* UNUSED */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 15bb1ef920d..637dd216935 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -651,7 +651,6 @@ typedef struct UserDef_Experimental {
/* Debug options, always available. */
char use_undo_legacy;
char no_override_auto_resync;
- char no_proxy_to_override_conversion;
char use_cycles_debug;
char use_geometry_nodes_legacy;
char show_asset_debug_info;
@@ -666,7 +665,7 @@ typedef struct UserDef_Experimental {
char use_sculpt_tools_tilt;
char use_extended_asset_browser;
char use_override_templates;
- char _pad[1];
+ char _pad[2];
/** `makesdna` does not allow empty structs. */
} UserDef_Experimental;
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 114c0b40407..d94b95fc6f4 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -1555,8 +1555,18 @@ int main(int argc, char **argv)
base_directory = BASE_HEADER;
}
+ /* NOTE: #init_structDNA() in dna_genfile.c expects `sdna->data` is 4-bytes aligned.
+ * `DNAstr[]` buffer written by `makesdna` is used for this data, so make `DNAstr` forcefully
+ * 4-bytes aligned. */
+#ifdef __GNUC__
+# define FORCE_ALIGN_4 " __attribute__((aligned(4))) "
+#else
+# define FORCE_ALIGN_4 " "
+#endif
fprintf(file_dna, "extern const unsigned char DNAstr[];\n");
- fprintf(file_dna, "const unsigned char DNAstr[] = {\n");
+ fprintf(file_dna, "const unsigned char" FORCE_ALIGN_4 "DNAstr[] = {\n");
+#undef FORCE_ALIGN_4
+
if (make_structDNA(base_directory, file_dna, file_dna_offsets, file_dna_verify)) {
/* error */
fclose(file_dna);
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 1ade964854d..43439428ea7 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -104,6 +104,8 @@ extern StructRNA RNA_BuildGpencilModifier;
extern StructRNA RNA_BuildModifier;
extern StructRNA RNA_ByteColorAttribute;
extern StructRNA RNA_ByteColorAttributeValue;
+extern StructRNA RNA_ByteIntAttribute;
+extern StructRNA RNA_ByteIntAttributeValue;
extern StructRNA RNA_CacheFile;
extern StructRNA RNA_CacheFileLayer;
extern StructRNA RNA_Camera;
@@ -143,6 +145,7 @@ extern StructRNA RNA_CompositorNodeCombHSVA;
extern StructRNA RNA_CompositorNodeCombRGBA;
extern StructRNA RNA_CompositorNodeCombYCCA;
extern StructRNA RNA_CompositorNodeCombYUVA;
+extern StructRNA RNA_CompositorNodeCombineXYZ;
extern StructRNA RNA_CompositorNodeComposite;
extern StructRNA RNA_CompositorNodeCornerPin;
extern StructRNA RNA_CompositorNodeCrop;
@@ -187,6 +190,7 @@ extern StructRNA RNA_CompositorNodeRLayers;
extern StructRNA RNA_CompositorNodeRotate;
extern StructRNA RNA_CompositorNodeScale;
extern StructRNA RNA_CompositorNodeSceneTime;
+extern StructRNA RNA_CompositorNodeSeparateXYZ;
extern StructRNA RNA_CompositorNodeSepHSVA;
extern StructRNA RNA_CompositorNodeSepRGBA;
extern StructRNA RNA_CompositorNodeSepYCCA;
@@ -1512,10 +1516,21 @@ void RNA_collection_clear(PointerRNA *ptr, const char *name);
/**
* Check if the #IDproperty exists, for operators.
+ *
+ * \param use_ghost: Internally an #IDProperty may exist,
+ * without the RNA considering it to be "set", see #IDP_FLAG_GHOST.
+ * This is used for operators, where executing an operator that has run previously
+ * will re-use the last value (unless #PROP_SKIP_SAVE property is set).
+ * In this case, the presence of the an existing value shouldn't prevent it being initialized
+ * from the context. Even though the this value will be returned if it's requested,
+ * it's not considered to be set (as it would if the menu item or key-map defined it's value).
+ * Set `use_ghost` to true for default behavior, otherwise false to check if there is a value
+ * exists internally and would be returned on request.
*/
bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost);
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop);
void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop);
+/** See #RNA_property_is_set_ex documentation. */
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost);
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier);
bool RNA_property_is_idprop(const PropertyRNA *prop);
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index c5581c01921..e37eb9f7188 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -322,7 +322,7 @@ typedef enum PropertyFlag {
* FREE FLAGS: 2, 3, 4, 5, 6, 7, 8, 9, 12 and above.
*/
typedef enum PropertyOverrideFlag {
- /** Means the property can be overridden by a local 'proxy' of some linked datablock. */
+ /** Means that the property can be overridden by a local override of some linked datablock. */
PROPOVERRIDE_OVERRIDABLE_LIBRARY = (1 << 0),
/**
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 1ae036a254e..8fc634fc087 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -719,7 +719,8 @@ static ID *rna_ID_override_hierarchy_create(
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
ID *id_root_override = NULL;
- BKE_lib_override_library_create(bmain, scene, view_layer, id, id_reference, &id_root_override);
+ BKE_lib_override_library_create(
+ bmain, scene, view_layer, NULL, id, id_reference, &id_root_override);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
WM_main_add_notifier(NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL);
@@ -948,9 +949,9 @@ static void rna_ID_user_remap(ID *id, Main *bmain, ID *new_id)
}
}
-static struct ID *rna_ID_make_local(struct ID *self, Main *bmain, bool clear_proxy)
+static struct ID *rna_ID_make_local(struct ID *self, Main *bmain, bool UNUSED(clear_proxy))
{
- BKE_lib_id_make_local(bmain, self, clear_proxy ? 0 : LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING);
+ BKE_lib_id_make_local(bmain, self, 0);
ID *ret_id = self->newid ? self->newid : self;
BKE_id_newptr_and_tag_clear(self);
@@ -2088,13 +2089,7 @@ static void rna_def_ID(BlenderRNA *brna)
"Make this datablock local, return local one "
"(may be a copy of the original, in case it is also indirectly used)");
RNA_def_function_flag(func, FUNC_USE_MAIN);
- parm = RNA_def_boolean(
- func,
- "clear_proxy",
- true,
- "",
- "Whether to clear proxies (the default behavior, "
- "note that if object has to be duplicated to be made local, proxies are always cleared)");
+ parm = RNA_def_boolean(func, "clear_proxy", true, "", "Deprecated, has no effect");
parm = RNA_def_pointer(func, "id", "ID", "", "This ID, or the new ID if it was copied");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 28e50e80f32..b22d3654431 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -151,18 +151,9 @@ static void rna_Armature_edit_bone_remove(bArmature *arm,
RNA_POINTER_INVALIDATE(ebone_ptr);
}
-static void rna_Armature_update_layers(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Armature_update_layers(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
bArmature *arm = (bArmature *)ptr->owner_id;
- Object *ob;
-
- /* proxy lib exception, store it here so we can restore layers on file
- * load, since it would otherwise get lost due to being linked data */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ob->data == arm && ob->pose) {
- ob->pose->proxy_layer = arm->layer;
- }
- }
DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
WM_main_add_notifier(NC_GEOM | ND_DATA, arm);
diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c
index e79cbc838d4..e80c8559020 100644
--- a/source/blender/makesrna/intern/rna_asset.c
+++ b/source/blender/makesrna/intern/rna_asset.c
@@ -237,7 +237,7 @@ static void rna_AssetMetaData_catalog_id_set(PointerRNA *ptr, const char *value)
}
if (!BLI_uuid_parse_string(&new_uuid, value)) {
- // TODO(Sybren): raise ValueError exception once that's possible from an RNA setter.
+ /* TODO(@sybren): raise ValueError exception once that's possible from an RNA setter. */
printf("UUID %s not formatted correctly, ignoring new value\n", value);
return;
}
diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c
index 35da353a043..da835fb89c4 100644
--- a/source/blender/makesrna/intern/rna_attribute.c
+++ b/source/blender/makesrna/intern/rna_attribute.c
@@ -46,6 +46,7 @@ const EnumPropertyItem rna_enum_attribute_type_items[] = {
{CD_PROP_STRING, "STRING", 0, "String", "Text string"},
{CD_PROP_BOOL, "BOOLEAN", 0, "Boolean", "True or false"},
{CD_PROP_FLOAT2, "FLOAT2", 0, "2D Vector", "2D vector with floating-point values"},
+ {CD_PROP_INT8, "INT8", 0, "8-Bit Integer", "Smaller integer with a range from -128 to 127"},
{0, NULL, 0, NULL, NULL},
};
@@ -59,6 +60,7 @@ const EnumPropertyItem rna_enum_attribute_type_with_auto_items[] = {
{CD_PROP_STRING, "STRING", 0, "String", "Text string"},
{CD_PROP_BOOL, "BOOLEAN", 0, "Boolean", "True or false"},
{CD_PROP_FLOAT2, "FLOAT2", 0, "2D Vector", "2D vector with floating-point values"},
+ {CD_PROP_INT8, "INT8", 0, "8-Bit Integer", "Smaller integer with a range from -128 to 127"},
{0, NULL, 0, NULL, NULL},
};
@@ -133,6 +135,8 @@ static StructRNA *srna_by_custom_data_layer_type(const CustomDataType type)
return &RNA_BoolAttribute;
case CD_PROP_FLOAT2:
return &RNA_Float2Attribute;
+ case CD_PROP_INT8:
+ return &RNA_ByteIntAttribute;
default:
return NULL;
}
@@ -253,6 +257,9 @@ static void rna_Attribute_data_begin(CollectionPropertyIterator *iter, PointerRN
case CD_PROP_FLOAT2:
struct_size = sizeof(float[2]);
break;
+ case CD_PROP_INT8:
+ struct_size = sizeof(int8_t);
+ break;
default:
struct_size = 0;
length = 0;
@@ -294,6 +301,28 @@ static void rna_ByteColorAttributeValue_color_set(PointerRNA *ptr, const float *
linearrgb_to_srgb_uchar4(&mlcol->r, values);
}
+/* Int8 Attribute. */
+
+static int rna_ByteIntAttributeValue_get(PointerRNA *ptr)
+{
+ int8_t *value = (int8_t *)ptr->data;
+ return (int)(*value);
+}
+
+static void rna_ByteIntAttributeValue_set(PointerRNA *ptr, const int new_value)
+{
+ int8_t *value = (int8_t *)ptr->data;
+ if (new_value > INT8_MAX) {
+ *value = INT8_MAX;
+ }
+ else if (new_value < INT8_MIN) {
+ *value = INT8_MIN;
+ }
+ else {
+ *value = (int8_t)new_value;
+ }
+}
+
/* Attribute Group */
static PointerRNA rna_AttributeGroup_new(
@@ -648,6 +677,36 @@ static void rna_def_attribute_bool(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "b", 0x01);
}
+static void rna_def_attribute_int8(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ByteIntAttribute", "Attribute");
+ RNA_def_struct_sdna(srna, "CustomDataLayer");
+ RNA_def_struct_ui_text(srna, "8-bit Int Attribute", "8-bit int geometry attribute");
+
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ByteIntAttributeValue");
+ RNA_def_property_collection_funcs(prop,
+ "rna_Attribute_data_begin",
+ "rna_iterator_array_next",
+ "rna_iterator_array_end",
+ "rna_iterator_array_get",
+ "rna_Attribute_data_length",
+ NULL,
+ NULL,
+ NULL);
+
+ srna = RNA_def_struct(brna, "ByteIntAttributeValue", NULL);
+ RNA_def_struct_sdna(srna, "MInt8Property");
+ RNA_def_struct_ui_text(
+ srna, "8-bit Integer Attribute Value", "8-bit value in geometry attribute");
+ prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(
+ prop, "rna_ByteIntAttributeValue_get", "rna_ByteIntAttributeValue_set", NULL);
+}
+
static void rna_def_attribute_float2(BlenderRNA *brna)
{
StructRNA *srna;
@@ -723,6 +782,7 @@ static void rna_def_attribute(BlenderRNA *brna)
rna_def_attribute_string(brna);
rna_def_attribute_bool(brna);
rna_def_attribute_float2(brna);
+ rna_def_attribute_int8(brna);
}
/* Mesh/PointCloud/Hair.attributes */
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 0c993660f39..e3a06c44eee 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -3543,14 +3543,6 @@ void RNA_def_constraint(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_ACTIVE);
RNA_def_property_ui_text(prop, "Active", "Constraint is the one being edited");
- prop = RNA_def_property(srna, "is_proxy_local", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_PROXY_LOCAL);
- RNA_def_property_ui_text(
- prop,
- "Proxy Local",
- "Constraint was added in this proxy instance (i.e. did not belong to source Armature)");
-
/* values */
prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "enforce");
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 3f380cd1830..7ef2f757cd8 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -2228,7 +2228,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_solo_mode", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_SOLO_MODE);
RNA_def_property_ui_text(
- prop, "Solo Mode", "In Paint mode display only layers with keyframe in current frame");
+ prop, "Solo Mode", "In Draw Mode only display layers with keyframe in current frame");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* Layer is used as Ruler. */
diff --git a/source/blender/makesrna/intern/rna_hair.c b/source/blender/makesrna/intern/rna_hair.c
index 4ca66c6b583..30e1fd48c03 100644
--- a/source/blender/makesrna/intern/rna_hair.c
+++ b/source/blender/makesrna/intern/rna_hair.c
@@ -47,71 +47,97 @@ static Hair *rna_hair(PointerRNA *ptr)
return (Hair *)ptr->owner_id;
}
-static int rna_HairPoint_index_get(PointerRNA *ptr)
+static int rna_Hair_curve_offset_data_length(PointerRNA *ptr)
+{
+ const Hair *curves = rna_hair(ptr);
+ return curves->geometry.curve_size + 1;
+}
+
+static void rna_Hair_curve_offset_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ const Hair *curves = rna_hair(ptr);
+ rna_iterator_array_begin(iter,
+ (void *)curves->geometry.offsets,
+ sizeof(int),
+ curves->geometry.curve_size + 1,
+ false,
+ NULL);
+}
+
+static int rna_CurvePoint_index_get(PointerRNA *ptr)
{
const Hair *hair = rna_hair(ptr);
const float(*co)[3] = ptr->data;
- return (int)(co - hair->co);
+ return (int)(co - hair->geometry.position);
}
-static void rna_HairPoint_location_get(PointerRNA *ptr, float value[3])
+static void rna_CurvePoint_location_get(PointerRNA *ptr, float value[3])
{
copy_v3_v3(value, (const float *)ptr->data);
}
-static void rna_HairPoint_location_set(PointerRNA *ptr, const float value[3])
+static void rna_CurvePoint_location_set(PointerRNA *ptr, const float value[3])
{
copy_v3_v3((float *)ptr->data, value);
}
-static float rna_HairPoint_radius_get(PointerRNA *ptr)
+static float rna_CurvePoint_radius_get(PointerRNA *ptr)
{
const Hair *hair = rna_hair(ptr);
- if (hair->radius == NULL) {
+ if (hair->geometry.radius == NULL) {
return 0.0f;
}
const float(*co)[3] = ptr->data;
- return hair->radius[co - hair->co];
+ return hair->geometry.radius[co - hair->geometry.position];
}
-static void rna_HairPoint_radius_set(PointerRNA *ptr, float value)
+static void rna_CurvePoint_radius_set(PointerRNA *ptr, float value)
{
const Hair *hair = rna_hair(ptr);
- if (hair->radius == NULL) {
+ if (hair->geometry.radius == NULL) {
return;
}
const float(*co)[3] = ptr->data;
- hair->radius[co - hair->co] = value;
+ hair->geometry.radius[co - hair->geometry.position] = value;
}
-static char *rna_HairPoint_path(PointerRNA *ptr)
+static char *rna_CurvePoint_path(PointerRNA *ptr)
{
- return BLI_sprintfN("points[%d]", rna_HairPoint_index_get(ptr));
+ return BLI_sprintfN("points[%d]", rna_CurvePoint_index_get(ptr));
}
-static int rna_HairCurve_index_get(PointerRNA *ptr)
+static int rna_CurveSlice_index_get(PointerRNA *ptr)
{
Hair *hair = rna_hair(ptr);
- return (int)((HairCurve *)ptr->data - hair->curves);
+ return (int)((int *)ptr->data - hair->geometry.offsets);
}
-static char *rna_HairCurve_path(PointerRNA *ptr)
+static char *rna_CurveSlice_path(PointerRNA *ptr)
{
- return BLI_sprintfN("curves[%d]", rna_HairCurve_index_get(ptr));
+ return BLI_sprintfN("curves[%d]", rna_CurveSlice_index_get(ptr));
}
-static void rna_HairCurve_points_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+static void rna_CurveSlice_points_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Hair *hair = rna_hair(ptr);
- HairCurve *curve = ptr->data;
- float(*co)[3] = hair->co + curve->firstpoint;
- rna_iterator_array_begin(iter, co, sizeof(float[3]), curve->numpoints, 0, NULL);
+ const int *offset_ptr = (int *)ptr->data;
+ const int offset = *offset_ptr;
+ const int size = *(offset_ptr + 1) - offset;
+ float(*co)[3] = hair->geometry.position + *offset_ptr;
+ rna_iterator_array_begin(iter, co, sizeof(float[3]), size, 0, NULL);
+}
+
+static int rna_CurveSlice_first_point_index_get(PointerRNA *ptr)
+{
+ const int *offset_ptr = (int *)ptr->data;
+ return *offset_ptr;
}
-static int rna_HairCurve_points_length(PointerRNA *ptr)
+static int rna_CurveSlice_points_length_get(PointerRNA *ptr)
{
- HairCurve *curve = ptr->data;
- return curve->numpoints;
+ const int *offset_ptr = (int *)ptr->data;
+ const int offset = *offset_ptr;
+ return *(offset_ptr + 1) - offset;
}
static void rna_Hair_update_data(struct Main *UNUSED(bmain),
@@ -134,25 +160,26 @@ static void rna_def_hair_point(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- srna = RNA_def_struct(brna, "HairPoint", NULL);
- RNA_def_struct_ui_text(srna, "Hair Point", "Hair curve control point");
- RNA_def_struct_path_func(srna, "rna_HairPoint_path");
+ srna = RNA_def_struct(brna, "CurvePoint", NULL);
+ RNA_def_struct_ui_text(srna, "Curve Point", "Curve curve control point");
+ RNA_def_struct_path_func(srna, "rna_CurvePoint_path");
- prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_TRANSLATION);
+ prop = RNA_def_property(srna, "position", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_array(prop, 3);
RNA_def_property_float_funcs(
- prop, "rna_HairPoint_location_get", "rna_HairPoint_location_set", NULL);
- RNA_def_property_ui_text(prop, "Location", "");
+ prop, "rna_CurvePoint_location_get", "rna_CurvePoint_location_set", NULL);
+ RNA_def_property_ui_text(prop, "Position", "");
RNA_def_property_update(prop, 0, "rna_Hair_update_data");
prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_float_funcs(prop, "rna_HairPoint_radius_get", "rna_HairPoint_radius_set", NULL);
+ RNA_def_property_float_funcs(
+ prop, "rna_CurvePoint_radius_get", "rna_CurvePoint_radius_set", NULL);
RNA_def_property_ui_text(prop, "Radius", "");
RNA_def_property_update(prop, 0, "rna_Hair_update_data");
prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_int_funcs(prop, "rna_HairPoint_index_get", NULL, NULL);
+ RNA_def_property_int_funcs(prop, "rna_CurvePoint_index_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Index", "Index of this points");
}
@@ -161,35 +188,37 @@ static void rna_def_hair_curve(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- srna = RNA_def_struct(brna, "HairCurve", NULL);
- RNA_def_struct_ui_text(srna, "Hair Curve", "Hair curve");
- RNA_def_struct_path_func(srna, "rna_HairCurve_path");
+ srna = RNA_def_struct(brna, "CurveSlice", NULL);
+ RNA_def_struct_ui_text(srna, "Curve Slice", "A single curve from a curves data-block");
+ RNA_def_struct_path_func(srna, "rna_CurveSlice_path");
prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "HairPoint");
+ RNA_def_property_struct_type(prop, "CurvePoint");
RNA_def_property_ui_text(prop, "Points", "Control points of the curve");
RNA_def_property_collection_funcs(prop,
- "rna_HairCurve_points_begin",
+ "rna_CurveSlice_points_begin",
"rna_iterator_array_next",
"rna_iterator_array_end",
"rna_iterator_array_get",
- "rna_HairCurve_points_length",
+ "rna_CurveSlice_points_length_get",
NULL,
NULL,
NULL);
- /* TODO: naming consistency, editable? */
prop = RNA_def_property(srna, "first_point_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "firstpoint");
- RNA_def_property_ui_text(prop, "First Point Index", "Index of the first loop of this polygon");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_int_funcs(prop, "rna_CurveSlice_first_point_index_get", NULL, NULL);
+ RNA_def_property_ui_text(
+ prop, "First Point Index", "The index of this curve's first control point");
- prop = RNA_def_property(srna, "num_points", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "numpoints");
- RNA_def_property_ui_text(prop, "Number of Points", "Number of loops used by this polygon");
+ prop = RNA_def_property(srna, "points_length", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_int_funcs(prop, "rna_CurveSlice_points_length_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Number of Points", "Number of control points in the curve");
prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_int_funcs(prop, "rna_HairCurve_index_get", NULL, NULL);
+ RNA_def_property_int_funcs(prop, "rna_CurveSlice_index_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Index", "Index of this curve");
}
@@ -202,20 +231,45 @@ static void rna_def_hair(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Hair", "Hair data-block for hair curves");
RNA_def_struct_ui_icon(srna, ICON_HAIR_DATA);
- /* geometry */
+ /* Point and Curve RNA API helpers. */
+
prop = RNA_def_property(srna, "curves", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "curves", "totcurve");
- RNA_def_property_struct_type(prop, "HairCurve");
+ RNA_def_property_collection_sdna(prop, NULL, "geometry.offsets", "geometry.curve_size");
+ RNA_def_property_struct_type(prop, "CurveSlice");
RNA_def_property_ui_text(prop, "Curves", "All hair curves");
/* TODO: better solution for (*co)[3] parsing issue. */
+
RNA_define_verify_sdna(0);
prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "co", "totpoint");
- RNA_def_property_struct_type(prop, "HairPoint");
+ RNA_def_property_collection_sdna(prop, NULL, "geometry.position", "geometry.point_size");
+ RNA_def_property_struct_type(prop, "CurvePoint");
RNA_def_property_ui_text(prop, "Points", "Control points of all hair curves");
RNA_define_verify_sdna(1);
+ /* Direct access to built-in attributes. */
+
+ RNA_define_verify_sdna(0);
+ prop = RNA_def_property(srna, "position_data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "geometry.position", "geometry.point_size");
+ RNA_def_property_struct_type(prop, "FloatVectorAttributeValue");
+ RNA_def_property_update(prop, 0, "rna_Hair_update_data");
+ RNA_define_verify_sdna(1);
+
+ prop = RNA_def_property(srna, "curve_offset_data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "geometry.offsets", NULL);
+ RNA_def_property_struct_type(prop, "IntAttributeValue");
+ RNA_def_property_collection_funcs(prop,
+ "rna_Hair_curve_offset_data_begin",
+ "rna_iterator_array_next",
+ "rna_iterator_array_end",
+ "rna_iterator_array_get",
+ "rna_Hair_curve_offset_data_length",
+ NULL,
+ NULL,
+ NULL);
+ RNA_def_property_update(prop, 0, "rna_Hair_update_data");
+
/* materials */
prop = RNA_def_property(srna, "materials", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "mat", "totcol");
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 0d86572357f..af13baad5a2 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -1107,7 +1107,7 @@ static void rna_def_image(BlenderRNA *brna)
prop, "Duration", "Duration (in frames) of the image (1 when not a video/sequence)");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- /* NOTE about pixels/channels/is_float:
+ /* NOTE: About pixels/channels/is_float:
* These properties describe how the image is stored internally (inside of ImBuf),
* not how it was saved to disk or how it'll be saved on disk.
*/
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index d4de20b5328..0e0391197ea 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -369,9 +369,10 @@ void rna_ViewLayer_active_aov_index_range(
PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax);
int rna_ViewLayer_active_aov_index_get(PointerRNA *ptr);
void rna_ViewLayer_active_aov_index_set(PointerRNA *ptr, int value);
-/** Set `r_rna_path` with the base viewlayer path.
+/**
+ * Set `r_rna_path` with the base view-layer path.
* `rna_path_buffer_size` should be at least `sizeof(ViewLayer.name) * 3`.
- * \return actual length of the generayted RNA path.
+ * \return actual length of the generated RNA path.
*/
size_t rna_ViewLayer_path_buffer_get(struct ViewLayer *view_layer,
char *r_rna_path,
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 38a447a9657..13c8444de1d 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -10524,7 +10524,7 @@ static void def_geo_object_info(StructRNA *srna)
RNA_def_property_enum_items(prop, rna_node_geometry_object_info_transform_space_items);
RNA_def_property_ui_text(
prop, "Transform Space", "The transformation of the vector and geometry outputs");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update_relations");
}
static void def_geo_legacy_points_to_volume(StructRNA *srna)
@@ -10608,7 +10608,7 @@ static void def_geo_collection_info(StructRNA *srna)
prop = RNA_def_property(srna, "transform_space", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_node_geometry_collection_info_transform_space_items);
RNA_def_property_ui_text(prop, "Transform Space", "The transformation of the geometry output");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update_relations");
}
static void def_geo_legacy_attribute_proximity(StructRNA *srna)
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index a098693459b..2bb341e00fb 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -3150,19 +3150,6 @@ static void rna_def_object(BlenderRNA *brna)
"Align to Vertex Normal is enabled)");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update");
- /* proxy */
- prop = RNA_def_property(srna, "proxy", PROP_POINTER, PROP_NONE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
- RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
- RNA_def_property_ui_text(prop, "Proxy", "Library object this proxy object controls");
-
- prop = RNA_def_property(srna, "proxy_collection", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "proxy_group");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
- RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
- RNA_def_property_ui_text(
- prop, "Proxy Collection", "Library collection duplicator object this proxy object controls");
-
/* materials */
prop = RNA_def_property(srna, "material_slots", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MaterialSlot");
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 76bfea00a79..7714e4d1e59 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -140,7 +140,7 @@ static char *rna_PoseBone_path(PointerRNA *ptr)
static bool rna_bone_group_poll(Object *ob, ReportList *reports)
{
- if ((ob->proxy != NULL) || (ob->proxy_group != NULL) || ID_IS_OVERRIDE_LIBRARY(ob)) {
+ if (ID_IS_OVERRIDE_LIBRARY(ob)) {
BKE_report(reports, RPT_ERROR, "Cannot edit bone groups for proxies or library overrides");
return false;
}
@@ -717,7 +717,7 @@ static int rna_PoseChannel_proxy_editable(PointerRNA *ptr, const char **r_info)
bArmature *arm = ob->data;
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
- if (ob->proxy && pchan->bone && (pchan->bone->layer & arm->layer_protected)) {
+ if (false && pchan->bone && (pchan->bone->layer & arm->layer_protected)) {
*r_info = "Can't edit property of a proxy on a protected layer";
return 0;
}
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 4379b4ebe1d..aef219c4236 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -6386,13 +6386,6 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
"Enable library overrides automatic resync detection and process on file load. Disable when "
"dealing with older .blend files that need manual Resync (Enforce) handling");
- prop = RNA_def_property(srna, "proxy_to_override_auto_conversion", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "no_proxy_to_override_conversion", 1);
- RNA_def_property_ui_text(
- prop,
- "Proxy to Override Auto Conversion",
- "Enable automatic conversion of proxies to library overrides on file load");
-
prop = RNA_def_property(srna, "use_new_point_cloud_type", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_new_point_cloud_type", 1);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index c64a47fc2ab..178a50c4d29 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -2175,7 +2175,8 @@ static void rna_def_event(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Mouse Previous Y Position", "The window relative vertical location of the mouse");
- prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_float_funcs(prop, "rna_Event_pressure_get", NULL, NULL);
RNA_def_property_ui_text(
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index bb933ba97a5..5065a23ee1b 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -183,10 +183,6 @@ if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
# To disable adaptive subdivision test in subsurf UI without cycles
if(WITH_CYCLES)
add_definitions(-DWITH_CYCLES)
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 828b8b79664..a86a667974e 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -296,7 +296,6 @@ ModifierTypeInfo modifierType_Armature = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ deformMatricesEM,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 56db68b163c..c2b1478c1b2 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -1037,7 +1037,6 @@ ModifierTypeInfo modifierType_Array = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index add95a0d248..984e85f58ef 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -446,7 +446,6 @@ ModifierTypeInfo modifierType_Bevel = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
/* requiredDataMask */ requiredDataMask,
diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc
index bb05ae3e1b3..7b084d608fb 100644
--- a/source/blender/modifiers/intern/MOD_boolean.cc
+++ b/source/blender/modifiers/intern/MOD_boolean.cc
@@ -641,7 +641,6 @@ ModifierTypeInfo modifierType_Boolean = {
/* deformVertsEM */ nullptr,
/* deformMatricesEM */ nullptr,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ nullptr,
/* modifyGeometrySet */ nullptr,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index 86f0df1418b..867c1e9b5bb 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -345,7 +345,6 @@ ModifierTypeInfo modifierType_Build = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index 715bc26e5d3..defc7df31dc 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -589,7 +589,6 @@ ModifierTypeInfo modifierType_Cast = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index 8aff29dc17d..4b8928009fe 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -308,7 +308,6 @@ ModifierTypeInfo modifierType_Cloth = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index 02e1f61b824..658a569627b 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -317,7 +317,6 @@ ModifierTypeInfo modifierType_Collision = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c
index dd62e354de8..d75c2a13587 100644
--- a/source/blender/modifiers/intern/MOD_correctivesmooth.c
+++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c
@@ -850,7 +850,6 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 20dbb299767..b01b70000b8 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -234,7 +234,6 @@ ModifierTypeInfo modifierType_Curve = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index 34bb93cbbbc..a289b9c918a 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -484,7 +484,6 @@ ModifierTypeInfo modifierType_DataTransfer = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index 975f80a04f8..ad5391d2b6c 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -298,7 +298,6 @@ ModifierTypeInfo modifierType_Decimate = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index c81e6cafa39..94cdcad3b6a 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -508,7 +508,6 @@ ModifierTypeInfo modifierType_Displace = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index a696ce216c7..676433b14b1 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -221,7 +221,6 @@ ModifierTypeInfo modifierType_DynamicPaint = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index 1039bcb2b3b..55707435e52 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -185,7 +185,6 @@ ModifierTypeInfo modifierType_EdgeSplit = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 68d6b4a3626..c788633f978 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -1255,7 +1255,6 @@ ModifierTypeInfo modifierType_Explode = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c
index a21eb603300..748633b78b3 100644
--- a/source/blender/modifiers/intern/MOD_fluid.c
+++ b/source/blender/modifiers/intern/MOD_fluid.c
@@ -273,7 +273,6 @@ ModifierTypeInfo modifierType_Fluid = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index 18ce37c5d85..b4c081906ba 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -572,7 +572,6 @@ ModifierTypeInfo modifierType_Hook = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index 6efeec1970f..090973f12c0 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -887,7 +887,6 @@ ModifierTypeInfo modifierType_LaplacianDeform = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index a36a8c386b4..8cc34d43d82 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -633,7 +633,6 @@ ModifierTypeInfo modifierType_LaplacianSmooth = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ init_data,
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index 29d1ecf6050..709b617d3ec 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -191,7 +191,6 @@ ModifierTypeInfo modifierType_Lattice = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc
index 0de8b26a1b7..097f7241205 100644
--- a/source/blender/modifiers/intern/MOD_mask.cc
+++ b/source/blender/modifiers/intern/MOD_mask.cc
@@ -837,7 +837,6 @@ ModifierTypeInfo modifierType_Mask = {
/* deformVertsEM */ nullptr,
/* deformMatricesEM */ nullptr,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ nullptr,
/* modifyGeometrySet */ nullptr,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc
index 910b52dea67..a8e1c91dd20 100644
--- a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc
+++ b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc
@@ -308,7 +308,6 @@ ModifierTypeInfo modifierType_MeshToVolume = {
/* deformVertsEM */ nullptr,
/* deformMatricesEM */ nullptr,
/* modifyMesh */ nullptr,
- /* modifyHair */ nullptr,
/* modifyGeometrySet */ modifyGeometrySet,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c
index 74f9887a973..48ff4f7d6af 100644
--- a/source/blender/modifiers/intern/MOD_meshcache.c
+++ b/source/blender/modifiers/intern/MOD_meshcache.c
@@ -446,7 +446,6 @@ ModifierTypeInfo modifierType_MeshCache = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index bfca5a39e8d..5c6bcb4ba24 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -642,7 +642,6 @@ ModifierTypeInfo modifierType_MeshDeform = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index b5dd0566215..8bde0cab3dc 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -456,7 +456,6 @@ ModifierTypeInfo modifierType_MeshSequenceCache = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 1bdc97f0a8b..721906a6a01 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -238,7 +238,6 @@ ModifierTypeInfo modifierType_Mirror = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index c3b34f3cd23..205839774d8 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -518,7 +518,6 @@ ModifierTypeInfo modifierType_Multires = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index 7e65774b86e..ca4bfbed5f5 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -141,56 +141,85 @@ static void initData(ModifierData *md)
MEMCPY_STRUCT_AFTER(nmd, DNA_struct_default_get(NodesModifierData), modifier);
}
-static void addIdsUsedBySocket(const ListBase *sockets, Set<ID *> &ids)
+static void add_used_ids_from_sockets(const ListBase &sockets, Set<ID *> &ids)
{
- LISTBASE_FOREACH (const bNodeSocket *, socket, sockets) {
- if (socket->type == SOCK_OBJECT) {
- Object *object = ((bNodeSocketValueObject *)socket->default_value)->value;
- if (object != nullptr) {
- ids.add(&object->id);
+ LISTBASE_FOREACH (const bNodeSocket *, socket, &sockets) {
+ switch (socket->type) {
+ case SOCK_OBJECT: {
+ if (Object *object = ((bNodeSocketValueObject *)socket->default_value)->value) {
+ ids.add(&object->id);
+ }
+ break;
}
- }
- else if (socket->type == SOCK_COLLECTION) {
- Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value;
- if (collection != nullptr) {
- ids.add(&collection->id);
+ case SOCK_COLLECTION: {
+ if (Collection *collection =
+ ((bNodeSocketValueCollection *)socket->default_value)->value) {
+ ids.add(&collection->id);
+ }
+ break;
}
- }
- else if (socket->type == SOCK_MATERIAL) {
- Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value;
- if (material != nullptr) {
- ids.add(&material->id);
+ case SOCK_MATERIAL: {
+ if (Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value) {
+ ids.add(&material->id);
+ }
+ break;
}
- }
- else if (socket->type == SOCK_TEXTURE) {
- Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value;
- if (texture != nullptr) {
- ids.add(&texture->id);
+ case SOCK_TEXTURE: {
+ if (Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value) {
+ ids.add(&texture->id);
+ }
+ break;
}
- }
- else if (socket->type == SOCK_IMAGE) {
- Image *image = ((bNodeSocketValueImage *)socket->default_value)->value;
- if (image != nullptr) {
- ids.add(&image->id);
+ case SOCK_IMAGE: {
+ if (Image *image = ((bNodeSocketValueImage *)socket->default_value)->value) {
+ ids.add(&image->id);
+ }
+ break;
}
}
}
}
-static void find_used_ids_from_nodes(const bNodeTree &tree, Set<ID *> &ids)
+/**
+ * \note We can only check properties here that cause the dependency graph to update relations when
+ * they are changed, otherwise there may be a missing relation after editing. So this could check
+ * more properties like whether the node is muted, but we would have to accept the cost of updating
+ * relations when those properties are changed.
+ */
+static bool node_needs_own_transform_relation(const bNode &node)
+{
+ if (node.type == GEO_NODE_COLLECTION_INFO) {
+ const NodeGeometryCollectionInfo &storage = *static_cast<const NodeGeometryCollectionInfo *>(
+ node.storage);
+ return storage.transform_space == GEO_NODE_TRANSFORM_SPACE_RELATIVE;
+ }
+
+ if (node.type == GEO_NODE_OBJECT_INFO) {
+ const NodeGeometryObjectInfo &storage = *static_cast<const NodeGeometryObjectInfo *>(
+ node.storage);
+ return storage.transform_space == GEO_NODE_TRANSFORM_SPACE_RELATIVE;
+ }
+
+ return false;
+}
+
+static void process_nodes_for_depsgraph(const bNodeTree &tree,
+ Set<ID *> &ids,
+ bool &needs_own_transform_relation)
{
Set<const bNodeTree *> handled_groups;
LISTBASE_FOREACH (const bNode *, node, &tree.nodes) {
- addIdsUsedBySocket(&node->inputs, ids);
- addIdsUsedBySocket(&node->outputs, ids);
+ add_used_ids_from_sockets(node->inputs, ids);
+ add_used_ids_from_sockets(node->outputs, ids);
if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
const bNodeTree *group = (bNodeTree *)node->id;
if (group != nullptr && handled_groups.add(group)) {
- find_used_ids_from_nodes(*group, ids);
+ process_nodes_for_depsgraph(*group, ids, needs_own_transform_relation);
}
}
+ needs_own_transform_relation |= node_needs_own_transform_relation(*node);
}
}
@@ -240,37 +269,43 @@ static void add_object_relation(const ModifierUpdateDepsgraphContext *ctx, Objec
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
- DEG_add_modifier_to_transform_relation(ctx->node, "Nodes Modifier");
- if (nmd->node_group != nullptr) {
- DEG_add_node_tree_output_relation(ctx->node, nmd->node_group, "Nodes Modifier");
-
- Set<ID *> used_ids;
- find_used_ids_from_settings(nmd->settings, used_ids);
- find_used_ids_from_nodes(*nmd->node_group, used_ids);
- for (ID *id : used_ids) {
- switch ((ID_Type)GS(id->name)) {
- case ID_OB: {
- Object *object = reinterpret_cast<Object *>(id);
- add_object_relation(ctx, *object);
- break;
- }
- case ID_GR: {
- Collection *collection = reinterpret_cast<Collection *>(id);
- add_collection_relation(ctx, *collection);
- break;
- }
- case ID_IM:
- case ID_TE: {
- DEG_add_generic_id_relation(ctx->node, id, "Nodes Modifier");
- }
- default: {
- /* Purposefully don't add relations for materials. While there are material sockets,
- * the pointers are only passed around as handles rather than dereferenced. */
- break;
- }
+ if (nmd->node_group == nullptr) {
+ return;
+ }
+
+ DEG_add_node_tree_output_relation(ctx->node, nmd->node_group, "Nodes Modifier");
+
+ bool needs_own_transform_relation = false;
+ Set<ID *> used_ids;
+ find_used_ids_from_settings(nmd->settings, used_ids);
+ process_nodes_for_depsgraph(*nmd->node_group, used_ids, needs_own_transform_relation);
+ for (ID *id : used_ids) {
+ switch ((ID_Type)GS(id->name)) {
+ case ID_OB: {
+ Object *object = reinterpret_cast<Object *>(id);
+ add_object_relation(ctx, *object);
+ break;
+ }
+ case ID_GR: {
+ Collection *collection = reinterpret_cast<Collection *>(id);
+ add_collection_relation(ctx, *collection);
+ break;
+ }
+ case ID_IM:
+ case ID_TE: {
+ DEG_add_generic_id_relation(ctx->node, id, "Nodes Modifier");
+ }
+ default: {
+ /* Purposefully don't add relations for materials. While there are material sockets,
+ * the pointers are only passed around as handles rather than dereferenced. */
+ break;
}
}
}
+
+ if (needs_own_transform_relation) {
+ DEG_add_modifier_to_transform_relation(ctx->node, "Nodes Modifier");
+ }
}
static bool check_tree_for_time_node(const bNodeTree &tree,
@@ -1683,7 +1718,6 @@ ModifierTypeInfo modifierType_Nodes = {
/* deformVertsEM */ nullptr,
/* deformMatricesEM */ nullptr,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ nullptr,
/* modifyGeometrySet */ modifyGeometrySet,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
index 5362d86a87f..f59af9074ce 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
@@ -1347,7 +1347,7 @@ class GeometryNodesEvaluator {
}
input_state.usage = ValueUsage::Unused;
- /* If the input is unused, it's value can be destructed now. */
+ /* If the input is unused, its value can be destructed now. */
this->destruct_input_value_if_exists(locked_node, socket);
if (input_state.was_ready_for_execution) {
diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c
index a01f63be791..cce3434f6e3 100644
--- a/source/blender/modifiers/intern/MOD_none.c
+++ b/source/blender/modifiers/intern/MOD_none.c
@@ -58,7 +58,6 @@ ModifierTypeInfo modifierType_None = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index 61099fedf46..8b58b575d24 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -336,8 +336,6 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
if (do_polynors_fix &&
polygons_check_flip(
mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), num_polys)) {
- /* XXX TODO: is this still needed? */
- // mesh->dirty |= DM_DIRTY_TESS_CDLAYERS;
/* We need to recompute vertex normals! */
BKE_mesh_normals_tag_dirty(mesh);
}
@@ -788,7 +786,6 @@ ModifierTypeInfo modifierType_NormalEdit = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index d821caf25a7..0c00f807df3 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -741,7 +741,6 @@ ModifierTypeInfo modifierType_Ocean = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 4fffa7c93f3..67a492d4154 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -677,7 +677,6 @@ ModifierTypeInfo modifierType_ParticleInstance = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index 2a4cc1c2747..6fb60fffcf4 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -334,7 +334,6 @@ ModifierTypeInfo modifierType_ParticleSystem = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c
index 937a73fddd9..67f83b17f3f 100644
--- a/source/blender/modifiers/intern/MOD_remesh.c
+++ b/source/blender/modifiers/intern/MOD_remesh.c
@@ -299,7 +299,6 @@ ModifierTypeInfo modifierType_Remesh = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index f5db3bced7a..33c62197dbd 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -27,6 +27,7 @@
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
+#include "BLI_bitmap.h"
#include "BLI_math.h"
#include "BLT_translation.h"
@@ -134,6 +135,8 @@ static Mesh *mesh_remove_doubles_on_axis(Mesh *result,
const float axis_offset[3],
const float merge_threshold)
{
+ BLI_bitmap *vert_tag = BLI_BITMAP_NEW(totvert, __func__);
+
const float merge_threshold_sq = square_f(merge_threshold);
const bool use_offset = axis_offset != NULL;
uint tot_doubles = 0;
@@ -150,13 +153,10 @@ static Mesh *mesh_remove_doubles_on_axis(Mesh *result,
}
const float dist_sq = len_squared_v3v3(axis_co, mvert_new[i].co);
if (dist_sq <= merge_threshold_sq) {
- mvert_new[i].flag |= ME_VERT_TMP_TAG;
+ BLI_BITMAP_ENABLE(vert_tag, i);
tot_doubles += 1;
copy_v3_v3(mvert_new[i].co, axis_co);
}
- else {
- mvert_new[i].flag &= ~ME_VERT_TMP_TAG & 0xFF;
- }
}
if (tot_doubles != 0) {
@@ -166,7 +166,7 @@ static Mesh *mesh_remove_doubles_on_axis(Mesh *result,
uint tot_doubles_left = tot_doubles;
for (uint i = 0; i < totvert; i += 1) {
- if (mvert_new[i].flag & ME_VERT_TMP_TAG) {
+ if (BLI_BITMAP_TEST(vert_tag, i)) {
int *doubles_map = &full_doubles_map[totvert + i];
for (uint step = 1; step < step_tot; step += 1) {
*doubles_map = (int)i;
@@ -184,6 +184,9 @@ static Mesh *mesh_remove_doubles_on_axis(Mesh *result,
MESH_MERGE_VERTS_DUMP_IF_MAPPED);
MEM_freeN(full_doubles_map);
}
+
+ MEM_freeN(vert_tag);
+
return result;
}
@@ -439,6 +442,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
mv_new = mvert_new;
mv_orig = mvert_orig;
+ BLI_bitmap *vert_tag = BLI_BITMAP_NEW(totvert, __func__);
+
/* Copy the first set of edges */
med_orig = medge_orig;
med_new = medge_new;
@@ -447,10 +452,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
med_new->v2 = med_orig->v2;
med_new->crease = med_orig->crease;
med_new->flag = med_orig->flag & ~ME_LOOSEEDGE;
- /* Tag mvert as not loose.
- * NOTE: ME_VERT_TMP_TAG is given to be cleared by BKE_mesh_new_nomain_from_template. */
- mvert_new[med_orig->v1].flag |= ME_VERT_TMP_TAG;
- mvert_new[med_orig->v2].flag |= ME_VERT_TMP_TAG;
+
+ /* Tag mvert as not loose. */
+ BLI_BITMAP_ENABLE(vert_tag, med_orig->v1);
+ BLI_BITMAP_ENABLE(vert_tag, med_orig->v1);
}
/* build polygon -> edge map */
@@ -910,7 +915,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
med_new->v1 = varray_stride + j;
med_new->v2 = med_new->v1 - totvert;
med_new->flag = ME_EDGEDRAW | ME_EDGERENDER;
- if ((mv_new_base->flag & ME_VERT_TMP_TAG) == 0) {
+ if (!BLI_BITMAP_TEST(vert_tag, j)) {
med_new->flag |= ME_LOOSEEDGE;
}
med_new++;
@@ -931,7 +936,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
med_new->v1 = i;
med_new->v2 = varray_stride + i;
med_new->flag = ME_EDGEDRAW | ME_EDGERENDER;
- if ((mvert_new[i].flag & ME_VERT_TMP_TAG) == 0) {
+ if (!BLI_BITMAP_TEST(vert_tag, i)) {
med_new->flag |= ME_LOOSEEDGE;
}
med_new++;
@@ -1119,6 +1124,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
}
#endif
+ MEM_freeN(vert_tag);
+
if (edge_poly_map) {
MEM_freeN(edge_poly_map);
}
@@ -1257,7 +1264,6 @@ ModifierTypeInfo modifierType_Screw = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index b517bc102f8..8c5299a965d 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -139,7 +139,6 @@ ModifierTypeInfo modifierType_ShapeKey = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ deformMatricesEM,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index a12724ec23c..4d10df91331 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -291,7 +291,6 @@ ModifierTypeInfo modifierType_Shrinkwrap = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 39ebc415021..25c3acb0c4f 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -596,7 +596,6 @@ ModifierTypeInfo modifierType_SimpleDeform = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 07ce819e91c..d1cb120132d 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -2101,7 +2101,6 @@ ModifierTypeInfo modifierType_Skin = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index 97027e2ecff..3228a72d958 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -284,7 +284,6 @@ ModifierTypeInfo modifierType_Smooth = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c
index 46e960e10d4..f0178a817dc 100644
--- a/source/blender/modifiers/intern/MOD_softbody.c
+++ b/source/blender/modifiers/intern/MOD_softbody.c
@@ -120,7 +120,6 @@ ModifierTypeInfo modifierType_Softbody = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 736dd08a713..09933fef7ff 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -274,7 +274,6 @@ ModifierTypeInfo modifierType_Solidify = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index a8c6687193b..65ad298cff1 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -500,7 +500,6 @@ ModifierTypeInfo modifierType_Subsurf = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index c8be2bd2829..a54af766b2f 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -245,7 +245,6 @@ ModifierTypeInfo modifierType_Surface = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index fd5a87571fc..70a05002a4f 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -1715,7 +1715,6 @@ ModifierTypeInfo modifierType_SurfaceDeform = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c
index b713df05b80..d4fcebb3216 100644
--- a/source/blender/modifiers/intern/MOD_triangulate.c
+++ b/source/blender/modifiers/intern/MOD_triangulate.c
@@ -170,7 +170,6 @@ ModifierTypeInfo modifierType_Triangulate = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 238952fde00..5721834c032 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -383,7 +383,6 @@ ModifierTypeInfo modifierType_UVProject = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index 3f161d339c2..552cf1d5d3b 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -233,9 +233,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
settings.use_threading = (numPolys > 1000);
BLI_task_parallel_range(0, numPolys, &data, uv_warp_compute, &settings);
- /* XXX TODO: is this still needed? */
- // me_eval->dirty |= DM_DIRTY_TESS_CDLAYERS;
-
mesh->runtime.is_original = false;
return mesh;
@@ -340,7 +337,6 @@ ModifierTypeInfo modifierType_UVWarp = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc
index af3a502162d..2b9ee97ea09 100644
--- a/source/blender/modifiers/intern/MOD_volume_displace.cc
+++ b/source/blender/modifiers/intern/MOD_volume_displace.cc
@@ -339,7 +339,6 @@ ModifierTypeInfo modifierType_VolumeDisplace = {
/* deformVertsEM */ nullptr,
/* deformMatricesEM */ nullptr,
/* modifyMesh */ nullptr,
- /* modifyHair */ nullptr,
/* modifyGeometrySet */ modifyGeometrySet,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc
index 72358844838..9557abf0a8a 100644
--- a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc
+++ b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc
@@ -221,7 +221,6 @@ ModifierTypeInfo modifierType_VolumeToMesh = {
/* deformVertsEM */ nullptr,
/* deformMatricesEM */ nullptr,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ nullptr,
/* modifyGeometrySet */ nullptr,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index 25e33b22bde..777ae4d9b10 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -539,7 +539,6 @@ ModifierTypeInfo modifierType_Warp = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index b7ab5dac388..5a56ec1d9e5 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -494,7 +494,6 @@ ModifierTypeInfo modifierType_Wave = {
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* modifyMesh */ NULL,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
index bfe389eb080..21e6ed46908 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.c
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -757,7 +757,6 @@ ModifierTypeInfo modifierType_WeightedNormal = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index a9d01c64ff1..6e4f8be8c50 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -428,7 +428,6 @@ ModifierTypeInfo modifierType_WeightVGEdit = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index b369b82ebb7..1b2608afa12 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -514,7 +514,6 @@ ModifierTypeInfo modifierType_WeightVGMix = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 7ee19e1c537..27242b32432 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -767,7 +767,6 @@ ModifierTypeInfo modifierType_WeightVGProximity = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_weld.cc b/source/blender/modifiers/intern/MOD_weld.cc
index 64871acabea..e9d98429ff2 100644
--- a/source/blender/modifiers/intern/MOD_weld.cc
+++ b/source/blender/modifiers/intern/MOD_weld.cc
@@ -218,7 +218,6 @@ ModifierTypeInfo modifierType_Weld = {
/* deformVertsEM */ nullptr,
/* deformMatricesEM */ nullptr,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ nullptr,
/* modifyGeometrySet */ nullptr,
/* initData */ initData,
diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c
index 706960182cf..72bc4336eff 100644
--- a/source/blender/modifiers/intern/MOD_wireframe.c
+++ b/source/blender/modifiers/intern/MOD_wireframe.c
@@ -194,7 +194,6 @@ ModifierTypeInfo modifierType_Wireframe = {
/* deformVertsEM */ NULL,
/* deformMatricesEM */ NULL,
/* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
/* modifyGeometrySet */ NULL,
/* initData */ initData,
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 402a71af27f..43fb90a52cd 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -133,10 +133,6 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_TBB)
list(APPEND INC_SYS
${TBB_INCLUDE_DIRS}
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index 82faccc2c2d..71acc738472 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -140,6 +140,8 @@ void register_node_type_cmp_pixelate(void);
void register_node_type_cmp_trackpos(void);
void register_node_type_cmp_planetrackdeform(void);
void register_node_type_cmp_cornerpin(void);
+void register_node_type_cmp_separate_xyz(void);
+void register_node_type_cmp_combine_xyz(void);
void node_cmp_rlayers_outputs(struct bNodeTree *ntree, struct bNode *node);
void node_cmp_rlayers_register_pass(struct bNodeTree *ntree,
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 8cbde6adcad..8fd71a978e3 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -230,6 +230,8 @@ DefNode(CompositorNode, CMP_NODE_ANTIALIASING, def_cmp_antialiasing, "ANTIAL
DefNode(CompositorNode, CMP_NODE_POSTERIZE, 0, "POSTERIZE", Posterize, "Posterize", "" )
DefNode(CompositorNode, CMP_NODE_CONVERT_COLOR_SPACE,def_cmp_convert_color_space, "CONVERT_COLORSPACE", ConvertColorSpace, "Color Space","" )
DefNode(CompositorNode, CMP_NODE_SCENE_TIME, 0, "SCENE_TIME", SceneTime, "Scene Time", "" )
+DefNode(CompositorNode, CMP_NODE_COMBINE_XYZ, 0, "COMBINE_XYZ", CombineXYZ, "Combine XYZ", "" )
+DefNode(CompositorNode, CMP_NODE_SEPARATE_XYZ, 0, "SEPARATE_XYZ", SeparateXYZ, "Separate XYZ", "" )
DefNode(TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode(TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
diff --git a/source/blender/nodes/composite/CMakeLists.txt b/source/blender/nodes/composite/CMakeLists.txt
index 8d2b2befd1a..8581ab7f82f 100644
--- a/source/blender/nodes/composite/CMakeLists.txt
+++ b/source/blender/nodes/composite/CMakeLists.txt
@@ -110,6 +110,7 @@ set(SRC
nodes/node_composite_sepcomb_rgba.cc
nodes/node_composite_sepcomb_ycca.cc
nodes/node_composite_sepcomb_yuva.cc
+ nodes/node_composite_sepcomb_xyz.cc
nodes/node_composite_setalpha.cc
nodes/node_composite_split_viewer.cc
nodes/node_composite_stabilize2d.cc
@@ -133,10 +134,6 @@ set(SRC
node_composite_util.hh
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_IMAGE_OPENEXR)
add_definitions(-DWITH_OPENEXR)
endif()
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcomb_xyz.cc b/source/blender/nodes/composite/nodes/node_composite_sepcomb_xyz.cc
new file mode 100644
index 00000000000..5dfcf5dca1e
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcomb_xyz.cc
@@ -0,0 +1,71 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup cmpnodes
+ */
+
+#include "node_composite_util.hh"
+
+/* **************** SEPARATE XYZ ******************** */
+namespace blender::nodes {
+
+static void cmp_node_separate_xyz_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Vector>("Vector").min(-10000.0f).max(10000.0f);
+ b.add_output<decl::Float>("X");
+ b.add_output<decl::Float>("Y");
+ b.add_output<decl::Float>("Z");
+}
+
+} // namespace blender::nodes
+
+void register_node_type_cmp_separate_xyz()
+{
+ static bNodeType ntype;
+
+ cmp_node_type_base(&ntype, CMP_NODE_SEPARATE_XYZ, "Separate XYZ", NODE_CLASS_CONVERTER);
+ ntype.declare = blender::nodes::cmp_node_separate_xyz_declare;
+
+ nodeRegisterType(&ntype);
+}
+
+/* **************** COMBINE XYZ ******************** */
+
+namespace blender::nodes {
+
+static void cmp_node_combine_xyz_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Float>("X").min(-10000.0f).max(10000.0f);
+ b.add_input<decl::Float>("Y").min(-10000.0f).max(10000.0f);
+ b.add_input<decl::Float>("Z").min(-10000.0f).max(10000.0f);
+ b.add_output<decl::Vector>("Vector");
+}
+
+} // namespace blender::nodes
+
+void register_node_type_cmp_combine_xyz()
+{
+ static bNodeType ntype;
+
+ cmp_node_type_base(&ntype, CMP_NODE_COMBINE_XYZ, "Combine XYZ", NODE_CLASS_CONVERTER);
+ ntype.declare = blender::nodes::cmp_node_combine_xyz_declare;
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/function/CMakeLists.txt b/source/blender/nodes/function/CMakeLists.txt
index 0c3c6a34995..6418c525776 100644
--- a/source/blender/nodes/function/CMakeLists.txt
+++ b/source/blender/nodes/function/CMakeLists.txt
@@ -63,10 +63,6 @@ set(LIB
bf_functions
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_nodes_function "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
if(WITH_UNITY_BUILD)
diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt
index b4add633b0c..2a8faf65a6d 100644
--- a/source/blender/nodes/geometry/CMakeLists.txt
+++ b/source/blender/nodes/geometry/CMakeLists.txt
@@ -239,10 +239,6 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_TBB)
list(APPEND INC_SYS
${TBB_INCLUDE_DIRS}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc
index e78c4d7bc35..ab1afeb39f4 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc
@@ -67,7 +67,7 @@ static Mesh *triangulate_mesh_selection(const Mesh &mesh,
BM_elem_flag_set(BM_face_at_index(bm, i_face), BM_ELEM_TAG, true);
}
- BM_mesh_triangulate(bm, quad_method, ngon_method, min_vertices, true, NULL, NULL, NULL);
+ BM_mesh_triangulate(bm, quad_method, ngon_method, min_vertices, true, nullptr, nullptr, nullptr);
Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, &cd_mask_extra, &mesh);
BM_mesh_free(bm);
BKE_mesh_normals_tag_dirty(result);
diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt
index c8eb0b8d570..598b0c81b51 100644
--- a/source/blender/nodes/shader/CMakeLists.txt
+++ b/source/blender/nodes/shader/CMakeLists.txt
@@ -158,10 +158,6 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
diff --git a/source/blender/nodes/texture/CMakeLists.txt b/source/blender/nodes/texture/CMakeLists.txt
index 053b17e4e57..e595343b7d2 100644
--- a/source/blender/nodes/texture/CMakeLists.txt
+++ b/source/blender/nodes/texture/CMakeLists.txt
@@ -82,8 +82,5 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
blender_add_lib(bf_nodes_texture "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c
index 2e684faf61b..11e3ad0bcf4 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.c
+++ b/source/blender/python/intern/bpy_rna_id_collection.c
@@ -94,7 +94,7 @@ static int foreach_libblock_id_user_map_callback(LibraryIDLinkCallbackData *cb_d
}
if (cb_flag & IDWALK_CB_LOOPBACK) {
- /* We skip loop-back pointers like Object.proxy_from or Key.from here,
+ /* We skip loop-back pointers like Key.from here,
* since it's some internal pointer which is not relevant info for py/API level. */
return IDWALK_RET_NOP;
}
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index a7c1b12982c..a49fc21d7ff 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -95,9 +95,5 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib_nolist(bf_render "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/render/RE_texture.h b/source/blender/render/RE_texture.h
index c6ccc547ff4..4d58d866e9f 100644
--- a/source/blender/render/RE_texture.h
+++ b/source/blender/render/RE_texture.h
@@ -103,7 +103,7 @@ void RE_point_density_fix_linking(void);
typedef struct TexResult {
float tin;
float trgba[4];
- /* Is acually a bool true->use alpha, false->set alpha to 1.0. */
+ /* Is actually a boolean: When true -> use alpha, false -> set alpha to 1.0. */
int talpha;
float *nor;
} TexResult;
diff --git a/source/blender/render/intern/multires_bake.c b/source/blender/render/intern/multires_bake.c
index 5cf328a3a73..9468e4c5b0f 100644
--- a/source/blender/render/intern/multires_bake.c
+++ b/source/blender/render/intern/multires_bake.c
@@ -33,11 +33,14 @@
#include "BLI_math.h"
#include "BLI_threads.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_ccg.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_tangent.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_subsurf.h"
@@ -488,9 +491,35 @@ static void do_multires_bake(MultiresBakeRender *bkr,
void *bake_data = NULL;
+ Mesh *temp_mesh = BKE_mesh_new_nomain(
+ dm->getNumVerts(dm), dm->getNumEdges(dm), 0, dm->getNumLoops(dm), dm->getNumPolys(dm));
+ memcpy(temp_mesh->mvert, dm->getVertArray(dm), temp_mesh->totvert * sizeof(*temp_mesh->mvert));
+ memcpy(temp_mesh->medge, dm->getEdgeArray(dm), temp_mesh->totedge * sizeof(*temp_mesh->medge));
+ memcpy(temp_mesh->mpoly, dm->getPolyArray(dm), temp_mesh->totpoly * sizeof(*temp_mesh->mpoly));
+ memcpy(temp_mesh->mloop, dm->getLoopArray(dm), temp_mesh->totloop * sizeof(*temp_mesh->mloop));
+ const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(temp_mesh);
+
if (require_tangent) {
if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) {
- DM_calc_loop_tangents(dm, true, NULL, 0);
+ BKE_mesh_calc_loop_tangent_ex(
+ dm->getVertArray(dm),
+ dm->getPolyArray(dm),
+ dm->getNumPolys(dm),
+ dm->getLoopArray(dm),
+ dm->getLoopTriArray(dm),
+ dm->getNumLoopTri(dm),
+ &dm->loopData,
+ true,
+ NULL,
+ 0,
+ vert_normals,
+ (const float(*)[3])CustomData_get_layer(&dm->polyData, CD_NORMAL),
+ (const float(*)[3])dm->getLoopDataArray(dm, CD_NORMAL),
+ (const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* may be nullptr */
+ /* result */
+ &dm->loopData,
+ dm->getNumLoops(dm),
+ &dm->tangent_mask);
}
pvtangent = DM_get_loop_data_layer(dm, CD_TANGENT);
@@ -524,6 +553,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
handle->data.mpoly = mpoly;
handle->data.mvert = mvert;
+ handle->data.vert_normals = vert_normals;
handle->data.mloopuv = mloopuv;
handle->data.mlooptri = mlooptri;
handle->data.mloop = mloop;
@@ -575,6 +605,8 @@ static void do_multires_bake(MultiresBakeRender *bkr,
MEM_freeN(handles);
+ BKE_id_free(NULL, temp_mesh);
+
BKE_image_release_ibuf(ima, ibuf, NULL);
}
}
diff --git a/source/blender/render/intern/texture_margin.cc b/source/blender/render/intern/texture_margin.cc
index 5a9d9db5367..7aff01242e3 100644
--- a/source/blender/render/intern/texture_margin.cc
+++ b/source/blender/render/intern/texture_margin.cc
@@ -48,16 +48,17 @@
namespace blender::render::texturemargin {
-/* The map class contains both a pixel map which maps out polygon indices for all UV-polygons and
+/**
+ * The map class contains both a pixel map which maps out polygon indices for all UV-polygons and
* adjacency tables.
*/
class TextureMarginMap {
static const int directions[8][2];
static const int distances[8];
- /* Maps UV-edges to their corresponding UV-edge. */
+ /** Maps UV-edges to their corresponding UV-edge. */
Vector<int> loop_adjacency_map_;
- /* Maps UV-edges to their corresponding polygon. */
+ /** Maps UV-edges to their corresponding polygon. */
Vector<int> loop_to_poly_map_;
int w_, h_;
@@ -122,7 +123,7 @@ class TextureMarginMap {
void rasterize_tri(float *v1, float *v2, float *v3, uint32_t value, char *mask)
{
/* NOTE: This is not thread safe, because the value to be written by the rasterizer is
- * a class member. If this is ever made multi-threaded each thread needs to get it's own. */
+ * a class member. If this is ever made multi-threaded each thread needs to get its own. */
value_to_store_ = value;
mask_ = mask;
zspan_scanconvert(
@@ -132,9 +133,7 @@ class TextureMarginMap {
static void zscan_store_pixel(
void *map, int x, int y, [[maybe_unused]] float u, [[maybe_unused]] float v)
{
- /* NOTE: Not thread safe, see comment above.
- *
- */
+ /* NOTE: Not thread safe, see comment above. */
TextureMarginMap *m = static_cast<TextureMarginMap *>(map);
m->set_pixel(x, y, m->value_to_store_);
if (m->mask_) {
@@ -153,7 +152,8 @@ class TextureMarginMap {
#define IsDijkstraPixel(dp) ((dp)&0x80000000)
#define DijkstraPixelIsUnset(dp) ((dp) == 0xFFFFFFFF)
- /* Use dijkstra's algorithm to 'grow' a border around the polygons marked in the map.
+ /**
+ * Use dijkstra's algorithm to 'grow' a border around the polygons marked in the map.
* For each pixel mark which direction is the shortest way to a polygon.
*/
void grow_dijkstra(int margin)
@@ -188,8 +188,10 @@ class TextureMarginMap {
}
}
- // std::make_heap(active_pixels.begin(), active_pixels.end(), cmp_dijkstrapixel_fun);
- // Not strictly needed because at this point it already is a heap.
+ /* Not strictly needed because at this point it already is a heap. */
+#if 0
+ std::make_heap(active_pixels.begin(), active_pixels.end(), cmp_dijkstrapixel_fun);
+#endif
while (active_pixels.size()) {
std::pop_heap(active_pixels.begin(), active_pixels.end(), cmp_dijkstrapixel_fun);
@@ -215,7 +217,8 @@ class TextureMarginMap {
}
}
- /* Walk over the map and for margin pixels follow the direction stored in the bottom 3
+ /**
+ * Walk over the map and for margin pixels follow the direction stored in the bottom 3
* bits back to the polygon.
* Then look up the pixel from the next polygon.
*/
@@ -324,10 +327,12 @@ class TextureMarginMap {
}
}
- /* Call lookup_pixel for the start_poly. If that fails, try the adjacent polygons as well.
- * Because the Dijkstra is not vey exact in determining which polygon is the closest, the
+ /**
+ * Call lookup_pixel for the start_poly. If that fails, try the adjacent polygons as well.
+ * Because the Dijkstra is not very exact in determining which polygon is the closest, the
* polygon we need can be the one next to the one the Dijkstra map provides. To prevent missing
- * pixels also check the neighbouring polygons. */
+ * pixels also check the neighboring polygons.
+ */
bool lookup_pixel_polygon_neighbourhood(
float x, float y, uint32_t *r_start_poly, float *r_destx, float *r_desty, int *r_other_poly)
{
@@ -344,8 +349,8 @@ class TextureMarginMap {
float mindist = -1.f;
- /* Loop over all adjacent polyons and determine which edge is closest.
- * This could be optimized by only inspecting neigbours which are on the edge of an island.
+ /* Loop over all adjacent polygons and determine which edge is closest.
+ * This could be optimized by only inspecting neighbors which are on the edge of an island.
* But it seems fast enough for now and that would add a lot of complexity. */
for (int i = 0; i < totloop; i++) {
int otherloop = loop_adjacency_map_[i + loopstart];
@@ -370,10 +375,12 @@ class TextureMarginMap {
return mindist >= 0.f;
}
- /* Find which edge of the src_poly is closest to x,y. Look up it's adjacent UV-edge and polygon.
+ /**
+ * Find which edge of the src_poly is closest to x,y. Look up its adjacent UV-edge and polygon.
* Then return the location of the equivalent pixel in the other polygon.
* Returns true if a new pixel location was found, false if it wasn't, which can happen if the
- * margin pixel is on a corner, or the UV-edge doesn't have an adjacent polygon. */
+ * margin pixel is on a corner, or the UV-edge doesn't have an adjacent polygon.
+ */
bool lookup_pixel(float x,
float y,
int src_poly,
@@ -463,7 +470,7 @@ class TextureMarginMap {
float2 other_edgepoint1 = uv_to_xy(mloopuv_[other_edge]);
float2 other_edgepoint2 = uv_to_xy(mloopuv_[other_edge2]);
- /* Calculate the vector from the order edges last point to it's first point. */
+ /* Calculate the vector from the order edges last point to its first point. */
float2 other_ab = other_edgepoint1 - other_edgepoint2;
float2 other_reflect_point = other_edgepoint2 + (found_t * other_ab);
float2 perpendicular_other_ab;
@@ -568,7 +575,9 @@ static void generate_margin(ImBuf *ibuf,
vec[a][1] = uv[1] * (float)ibuf->y - (0.5f + 0.002f);
}
- BLI_assert(lt->poly < 0x80000000); // NOTE: we need the top bit for the dijkstra distance map
+ /* NOTE: we need the top bit for the dijkstra distance map. */
+ BLI_assert(lt->poly < 0x80000000);
+
map.rasterize_tri(vec[0], vec[1], vec[2], lt->poly, draw_new_mask ? mask : nullptr);
}
diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c
index be29dcfcd0c..dd8966acfd8 100644
--- a/source/blender/sequencer/intern/strip_add.c
+++ b/source/blender/sequencer/intern/strip_add.c
@@ -297,7 +297,7 @@ static void seq_add_sound_av_sync(Main *bmain, Scene *scene, Sequence *seq, SeqL
const double av_stream_offset = sound_stream.start - load_data->r_video_stream_start;
const int frame_offset = av_stream_offset * FPS;
- /* Set subframe offset. */
+ /* Set sub-frame offset. */
seq->sound->offset_time = ((double)frame_offset / FPS) - av_stream_offset;
SEQ_transform_translate_sequence(scene, seq, frame_offset);
}
diff --git a/source/blender/shader_fx/CMakeLists.txt b/source/blender/shader_fx/CMakeLists.txt
index 0167591c3ba..ae78d9964e5 100644
--- a/source/blender/shader_fx/CMakeLists.txt
+++ b/source/blender/shader_fx/CMakeLists.txt
@@ -63,9 +63,5 @@ set(SRC
set(LIB
)
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
blender_add_lib(bf_shader_fx "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 03b2fb49085..37b233d85d2 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -135,10 +135,6 @@ if(WITH_CYCLES)
add_definitions(-DWITH_CYCLES)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_OPENCOLLADA)
add_definitions(-DWITH_COLLADA)
endif()
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index d1f790ce3e2..929b39715b9 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -1048,6 +1048,10 @@ typedef struct wmDragActiveDropState {
* it as needed. */
struct ARegion *region_from;
+ /** If `active_dropbox` is set, additional context provided by the active (i.e. hovered) button.
+ * Activated before context sensitive operations (polling, drawing, dropping). */
+ struct bContextStore *ui_context;
+
/** Text to show when a dropbox poll succeeds (so the dropbox itself is available) but the
* operator poll fails. Typically the message the operator set with
* CTX_wm_operator_poll_msg_set(). */
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
index 6f10e4f3f0d..2a93e279576 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
@@ -706,7 +706,7 @@ wmKeyMap *WM_gizmogroup_setup_keymap_generic_maybe_drag(const wmGizmoGroupType *
/**
* Variation of #WM_gizmogroup_keymap_common but with keymap items for selection
*
- * TODO(campbell): move to Python.
+ * TODO(@campbellbarton): move to Python.
*
* \param name: Typically #wmGizmoGroupType.name
* \param params: Typically #wmGizmoGroupType.gzmap_params
@@ -719,7 +719,7 @@ static wmKeyMap *WM_gizmogroup_keymap_template_select_ex(
wmKeyMap *km = WM_keymap_ensure(kc, name, params->spaceid, params->regionid);
const bool do_init = BLI_listbase_is_empty(&km->items);
- /* FIXME(campbell) */
+ /* FIXME(@campbellbarton): Currently hard coded. */
#if 0
const int select_mouse = (U.flag & USER_LMOUSESELECT) ? LEFTMOUSE : RIGHTMOUSE;
const int select_tweak = (U.flag & USER_LMOUSESELECT) ? EVT_TWEAK_L : EVT_TWEAK_R;
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index ab955a9e233..83e6e347ce7 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -572,7 +572,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
rcti rect;
/* Almost certainly overkill, but allow for many custom gizmos. */
- uint buffer[MAXPICKBUF];
+ GPUSelectResult buffer[MAXPICKELEMS];
short hits;
BLI_rcti_init_pt_radius(&rect, co, hotspot);
@@ -582,19 +582,19 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
* - #GPU_SELECT_ALL: Use it to check if there is anything at the cursor location
* (only ever runs once).
* - #GPU_SELECT_PICK_NEAREST: Use if there are more than 1 item at the cursor location,
- * select the best one.
+ * pick the nearest one.
* - #GPU_SELECT_PICK_ALL: Use for the same purpose as #GPU_SELECT_PICK_NEAREST
* when the selection depths need to re-ordered based on a bias.
* */
- const int gpu_select_mode = (use_depth_test ?
- (has_3d_select_bias ?
- /* Using select bias means the depths need to be
- * re-calculated based on the bias to pick the best. */
- GPU_SELECT_PICK_ALL :
- /* No bias, just pick the closest. */
- GPU_SELECT_PICK_NEAREST) :
- /* Fast-path (occlusion queries). */
- GPU_SELECT_ALL);
+ const eGPUSelectMode gpu_select_mode =
+ (use_depth_test ? (has_3d_select_bias ?
+ /* Using select bias means the depths need to be
+ * re-calculated based on the bias to pick the best. */
+ GPU_SELECT_PICK_ALL :
+ /* No bias, just pick the closest. */
+ GPU_SELECT_PICK_NEAREST) :
+ /* Fast-path (occlusion queries). */
+ GPU_SELECT_ALL);
/* When switching between modes and the mouse pointer is over a gizmo, the highlight test is
* performed before the viewport is fully initialized (region->draw_buffer = NULL).
@@ -657,14 +657,14 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
- uint *buf_iter = buffer;
+ GPUSelectResult *buf_iter = buffer;
float dot_best = FLT_MAX;
- for (int i = 0; i < hits; i++, buf_iter += 4) {
- BLI_assert(buf_iter[3] != -1);
- wmGizmo *gz = visible_gizmos[buf_iter[3] >> 8];
+ for (int i = 0; i < hits; i++, buf_iter++) {
+ BLI_assert(buf_iter->id != -1);
+ wmGizmo *gz = visible_gizmos[buf_iter->id >> 8];
float co_3d[3];
- co_screen[2] = int_as_float(buf_iter[1]);
+ co_screen[2] = int_as_float(buf_iter->depth);
GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d);
float select_bias = gz->select_bias;
if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
@@ -674,14 +674,14 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
const float dot_test = dot_v3v3(co_3d, co_direction) - select_bias;
if (dot_best > dot_test) {
dot_best = dot_test;
- hit_found = buf_iter[3];
+ hit_found = buf_iter->id;
}
}
}
else {
- const uint *hit_near = GPU_select_buffer_near(buffer, hits);
+ const GPUSelectResult *hit_near = GPU_select_buffer_near(buffer, hits);
if (hit_near) {
- hit_found = hit_near[3];
+ hit_found = hit_near->id;
}
}
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 96cb66b44ea..3bc77db45ca 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -226,6 +226,30 @@ void wm_drags_exit(wmWindowManager *wm, wmWindow *win)
}
}
+static bContextStore *wm_drop_ui_context_create(const bContext *C)
+{
+ uiBut *active_but = UI_region_active_but_get(CTX_wm_region(C));
+ if (!active_but) {
+ return NULL;
+ }
+
+ bContextStore *but_context = UI_but_context_get(active_but);
+ if (!but_context) {
+ return NULL;
+ }
+
+ return CTX_store_copy(but_context);
+}
+
+static void wm_drop_ui_context_free(bContextStore **context_store)
+{
+ if (!*context_store) {
+ return;
+ }
+ CTX_store_free(*context_store);
+ *context_store = NULL;
+}
+
void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy)
{
drag->imb = imb;
@@ -259,6 +283,7 @@ void WM_drag_free(wmDrag *drag)
if (drag->flags & WM_DRAG_FREE_DATA) {
WM_drag_data_free(drag->type, drag->poin);
}
+ wm_drop_ui_context_free(&drag->drop_state.ui_context);
if (drag->drop_state.free_disabled_info) {
MEM_SAFE_FREE(drag->drop_state.disabled_info);
}
@@ -317,6 +342,10 @@ static wmDropBox *dropbox_active(bContext *C,
}
const wmOperatorCallContext opcontext = wm_drop_operator_context_get(drop);
+ if (drag->drop_state.ui_context) {
+ CTX_store_set(C, drag->drop_state.ui_context);
+ }
+
if (WM_operator_poll_context(C, drop->ot, opcontext)) {
return drop;
}
@@ -367,6 +396,10 @@ static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *even
return;
}
+ /* Update UI context, before polling so polls can query this context. */
+ wm_drop_ui_context_free(&drag->drop_state.ui_context);
+ drag->drop_state.ui_context = wm_drop_ui_context_create(C);
+
wmDropBox *drop_prev = drag->drop_state.active_dropbox;
wmDropBox *drop = wm_dropbox_active(C, drag, event);
if (drop != drop_prev) {
@@ -381,11 +414,20 @@ static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *even
drag->drop_state.area_from = drop ? CTX_wm_area(C) : NULL;
drag->drop_state.region_from = drop ? CTX_wm_region(C) : NULL;
}
+
+ if (!drag->drop_state.active_dropbox) {
+ wm_drop_ui_context_free(&drag->drop_state.ui_context);
+ }
}
void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop)
{
const wmOperatorCallContext opcontext = wm_drop_operator_context_get(drop);
+
+ if (drag->drop_state.ui_context) {
+ CTX_store_set(C, drag->drop_state.ui_context);
+ }
+
/* Optionally copy drag information to operator properties. Don't call it if the
* operator fails anyway, it might do more than just set properties (e.g.
* typically import an asset). */
@@ -396,6 +438,11 @@ void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop)
wm_drags_exit(CTX_wm_manager(C), CTX_wm_window(C));
}
+void wm_drop_end(bContext *C, wmDrag *UNUSED(drag), wmDropBox *UNUSED(drop))
+{
+ CTX_store_set(C, NULL);
+}
+
void wm_drags_check_ops(bContext *C, const wmEvent *event)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -897,6 +944,7 @@ void wm_drags_draw(bContext *C, wmWindow *win)
if (drag->drop_state.active_dropbox) {
CTX_wm_area_set(C, drag->drop_state.area_from);
CTX_wm_region_set(C, drag->drop_state.region_from);
+ CTX_store_set(C, drag->drop_state.ui_context);
/* Drawing should be allowed to assume the context from handling and polling (that's why we
* restore it above). */
@@ -915,4 +963,5 @@ void wm_drags_draw(bContext *C, wmWindow *win)
GPU_blend(GPU_BLEND_NONE);
CTX_wm_area_set(C, NULL);
CTX_wm_region_set(C, NULL);
+ CTX_store_set(C, NULL);
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 0cc2db661ec..5210b315af6 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1081,7 +1081,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, const bool repeat, cons
}
}
- /* XXX(mont29) Disabled the repeat check to address part 2 of T31840.
+ /* XXX(@mont29): Disabled the repeat check to address part 2 of T31840.
* Carefully checked all calls to wm_operator_exec and WM_operator_repeat, don't see any reason
* why this was needed, but worth to note it in case something turns bad. */
if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED) /* && repeat == 0 */) {
@@ -3076,6 +3076,8 @@ static int wm_handlers_do_intern(bContext *C, wmWindow *win, wmEvent *event, Lis
event->customdata = NULL;
event->custom = 0;
+ wm_drop_end(C, drag, drop);
+
/* XXX fileread case. */
if (CTX_wm_window(C) == NULL) {
return action;
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 1478712c3cd..9b9aa37a251 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -874,18 +874,16 @@ static void file_read_reports_finalize(BlendFileReadReport *bf_reports)
duration_lib_override_recursive_resync_seconds);
}
- if (bf_reports->count.linked_proxies != 0 ||
- bf_reports->count.proxies_to_lib_overrides_success != 0 ||
+ if (bf_reports->count.proxies_to_lib_overrides_success != 0 ||
bf_reports->count.proxies_to_lib_overrides_failures != 0) {
- BKE_reportf(bf_reports->reports,
- RPT_WARNING,
- "Proxies are deprecated (%d proxies were automatically converted to library "
- "overrides, %d proxies could not be converted and %d linked proxies were kept "
- "untouched). If you need to keep proxies for the time being, please disable the "
- "`Proxy to Override Auto Conversion` in Experimental user preferences",
- bf_reports->count.proxies_to_lib_overrides_success,
- bf_reports->count.proxies_to_lib_overrides_failures,
- bf_reports->count.linked_proxies);
+ BKE_reportf(
+ bf_reports->reports,
+ RPT_WARNING,
+ "Proxies have been removed from Blender (%d proxies were automatically converted "
+ "to library overrides, %d proxies could not be converted and were cleared). "
+ "Please also consider re-saving any library .blend file with the newest Blender version.",
+ bf_reports->count.proxies_to_lib_overrides_success,
+ bf_reports->count.proxies_to_lib_overrides_failures);
}
if (bf_reports->count.sequence_strips_skipped != 0) {
@@ -2706,7 +2704,7 @@ static char *wm_open_mainfile_description(struct bContext *UNUSED(C),
BLI_stat_t stats;
if (BLI_stat(path, &stats) == -1) {
- return BLI_sprintfN("%s\n\n%s", path, N_("File Not Found"));
+ return BLI_sprintfN("%s\n\n%s", path, TIP_("File Not Found"));
}
/* Date. */
@@ -2716,7 +2714,7 @@ static char *wm_open_mainfile_description(struct bContext *UNUSED(C),
BLI_filelist_entry_datetime_to_string(
NULL, (int64_t)stats.st_mtime, false, time_st, date_st, &is_today, &is_yesterday);
if (is_today || is_yesterday) {
- BLI_strncpy(date_st, is_today ? N_("Today") : N_("Yesterday"), sizeof(date_st));
+ BLI_strncpy(date_st, is_today ? TIP_("Today") : TIP_("Yesterday"), sizeof(date_st));
}
/* Size. */
@@ -2724,7 +2722,7 @@ static char *wm_open_mainfile_description(struct bContext *UNUSED(C),
BLI_filelist_entry_size_to_string(NULL, (uint64_t)stats.st_size, false, size_str);
return BLI_sprintfN(
- "%s\n\n%s: %s %s\n%s: %s", path, N_("Modified"), date_st, time_st, N_("Size"), size_str);
+ "%s\n\n%s: %s %s\n%s: %s", path, TIP_("Modified"), date_st, time_st, TIP_("Size"), size_str);
}
/* currently fits in a pointer */
@@ -3171,8 +3169,8 @@ static char *wm_save_as_mainfile_get_description(bContext *UNUSED(C),
PointerRNA *ptr)
{
if (RNA_boolean_get(ptr, "copy")) {
- return BLI_strdup(
- "Save the current file in the desired location but do not make the saved file active");
+ return BLI_strdup(TIP_(
+ "Save the current file in the desired location but do not make the saved file active"));
}
return NULL;
}
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 6caac79c4d5..1d26c58bcf9 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -594,9 +594,7 @@ void WM_exit_ex(bContext *C, const bool do_python)
DRW_opengl_context_destroy();
}
-#ifdef WITH_INTERNATIONAL
BLT_lang_free();
-#endif
ANIM_keyingset_infos_exit();
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index a1854a8ed86..a7b5b9bddda 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1483,7 +1483,11 @@ static bool wm_window_timer(const bContext *C)
wt->delta = time - wt->ltime;
wt->duration += wt->delta;
wt->ltime = time;
- wt->ntime = wt->stime + wt->timestep * ceil(wt->duration / wt->timestep);
+
+ wt->ntime = wt->stime;
+ if (wt->timestep != 0.0f) {
+ wt->ntime += wt->timestep * ceil(wt->duration / wt->timestep);
+ }
if (wt->event_type == TIMERJOBS) {
wm_jobs_timer(wm, wt);
@@ -1596,6 +1600,7 @@ void WM_event_timer_sleep(wmWindowManager *wm,
wmTimer *WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type, double timestep)
{
wmTimer *wt = MEM_callocN(sizeof(wmTimer), "window timer");
+ BLI_assert(timestep >= 0.0f);
wt->event_type = event_type;
wt->ltime = PIL_check_seconds_timer();
@@ -1615,6 +1620,7 @@ wmTimer *WM_event_add_timer_notifier(wmWindowManager *wm,
double timestep)
{
wmTimer *wt = MEM_callocN(sizeof(wmTimer), "window timer");
+ BLI_assert(timestep >= 0.0f);
wt->event_type = TIMERNOTIFIER;
wt->ltime = PIL_check_seconds_timer();
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index 925be8ab183..252ff228bc1 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -199,6 +199,7 @@ void wm_dropbox_free(void);
*/
void wm_drags_exit(wmWindowManager *wm, wmWindow *win);
void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop);
+void wm_drop_end(bContext *C, wmDrag *drag, wmDropBox *drop);
/**
* Called in inner handler loop, region context.
*/
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index a6685e97c4f..6fcaad92661 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -60,7 +60,7 @@ enum {
/* ********** Start of Input devices. ********** */
- /* MOUSE : 0x000x, 0x001x */
+ /* MOUSE: 0x000x, 0x001x */
LEFTMOUSE = 0x0001,
MIDDLEMOUSE = 0x0002,
RIGHTMOUSE = 0x0003,
@@ -71,7 +71,7 @@ enum {
/* More mouse buttons - can't use 9 and 10 here (wheel) */
BUTTON6MOUSE = 0x0012,
BUTTON7MOUSE = 0x0013,
- /* Extra trackpad gestures */
+ /* Extra track-pad gestures. */
MOUSEPAN = 0x000e,
MOUSEZOOM = 0x000f,
MOUSEROTATE = 0x0010,
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 6f23fbe486a..b86b8999fd0 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -1082,6 +1082,13 @@ elseif(APPLE)
Blender.app/Contents/
)
+ if(WITH_BLENDER_THUMBNAILER)
+ install(
+ TARGETS blender-thumbnailer
+ DESTINATION Blender.app/Contents/MacOS/
+ )
+ endif()
+
if(WITH_OPENMP AND OPENMP_CUSTOM)
install(
FILES "${OpenMP_LIBRARY}"
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index 63dcdc0f925..04fdb380da2 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -293,6 +293,13 @@ add_blender_test(
--testdir "${TEST_SRC_DIR}/animation"
)
+add_blender_test(
+ bl_rigging_symmetrize
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_rigging_symmetrize.py
+ --
+ --testdir "${TEST_SRC_DIR}/animation"
+)
+
# ------------------------------------------------------------------------------
# IO TESTS
diff --git a/tests/python/bl_keymap_validate.py b/tests/python/bl_keymap_validate.py
index ebc35c1178c..705a026e441 100644
--- a/tests/python/bl_keymap_validate.py
+++ b/tests/python/bl_keymap_validate.py
@@ -162,7 +162,7 @@ def keymap_data_clean(keyconfig_data: typing.List, *, relaxed: bool) -> None:
item_prop.pop("properties")
# Needed so: `{"properties": ()}` matches `None` as there is no meaningful difference.
- # Wruting `None` makes the most sense when explicitly written, however generated properties
+ # Writing `None` makes the most sense when explicitly written, however generated properties
# might be empty and it's not worth adding checks in the generation logic to use `None`
# just to satisfy this check.
if not item_prop:
diff --git a/tests/python/bl_rigging_symmetrize.py b/tests/python/bl_rigging_symmetrize.py
new file mode 100644
index 00000000000..b47ace7f3f1
--- /dev/null
+++ b/tests/python/bl_rigging_symmetrize.py
@@ -0,0 +1,244 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+"""
+blender -b -noaudio --factory-startup --python tests/python/bl_rigging_symmetrize.py -- --testdir /path/to/lib/tests/animation
+"""
+
+import pathlib
+import sys
+import unittest
+
+import bpy
+
+
+def check_loc_rot_scale(self, bone, exp_bone):
+ # Check if posistions are the same
+ self.assertEqualVector(
+ bone.head, exp_bone.head, "Head position", bone.name)
+ self.assertEqualVector(
+ bone.tail, exp_bone.tail, "Tail position", bone.name)
+
+ # Scale
+ self.assertEqualVector(
+ bone.scale, exp_bone.scale, "Scale", bone.name)
+
+ # Rotation
+ rot_mode = exp_bone.rotation_mode
+ self.assertEqual(bone.rotation_mode, rot_mode, "Rotations mode does not match on bone %s" % (bone.name))
+
+ if rot_mode == 'QUATERNION':
+ self.assertEqualVector(
+ bone.rotation_quaternion, exp_bone.rotation_quaternion, "Quaternion rotation", bone.name)
+ elif rot_mode == 'AXIS_ANGLE':
+ self.assertEqualVector(
+ bone.axis_angle, exp_bone.axis_angle, "Axis Angle rotation", bone.name)
+ else:
+ # Euler rotation
+ self.assertEqualVector(
+ bone.rotation_euler, exp_bone.rotation_euler, "Euler rotation", bone.name)
+
+
+def check_parent(self, bone, exp_bone):
+ self.assertEqual(type(bone.parent), type(exp_bone.parent),
+ "Missmatching types in pose.bones[%s].parent" % (bone.name))
+ self.assertTrue(bone.parent is None or bone.parent.name == exp_bone.parent.name,
+ "Bone parent does not match on bone %s" % (bone.name))
+
+
+def check_bendy_bones(self, bone, exp_bone):
+ bone_variables = bone.bl_rna.properties.keys()
+
+ bendy_bone_variables = [
+ var for var in bone_variables if var.startswith("bbone_")]
+
+ for var in bendy_bone_variables:
+ value = getattr(bone, var)
+ exp_value = getattr(exp_bone, var)
+
+ self.assertEqual(type(value), type(exp_value),
+ "Missmatching types in pose.bones[%s].%s" % (bone.name, var))
+
+ if isinstance(value, str):
+ self.assertEqual(value, exp_value,
+ "Missmatching value in pose.bones[%s].%s" % (bone.name, var))
+ elif hasattr(value, "name"):
+ self.assertEqual(value.name, exp_value.name,
+ "Missmatching value in pose.bones[%s].%s" % (bone.name, var))
+ else:
+ self.assertAlmostEqual(value, exp_value,
+ "Missmatching value in pose.bones[%s].%s" % (bone.name, var))
+
+
+def check_ik(self, bone, exp_bone):
+ bone_variables = bone.bl_rna.properties.keys()
+ prefixes = ("ik_", "lock_ik", "use_ik")
+ ik_bone_variables = (
+ var for var in bone_variables
+ if var.startswith(prefixes)
+ )
+
+ for var in ik_bone_variables:
+ value = getattr(bone, var)
+ exp_value = getattr(exp_bone, var)
+ self.assertAlmostEqual(value, exp_value,
+ "Missmatching value in pose.bones[%s].%s" % (bone.name, var))
+
+
+def check_constraints(self, input_arm, expected_arm, bone, exp_bone):
+ const_len = len(bone.constraints)
+ expo_const_len = len(exp_bone.constraints)
+
+ self.assertEqual(const_len, expo_const_len,
+ "Constraints missmatch on bone %s" % (bone.name))
+
+ for exp_constraint in exp_bone.constraints:
+ const_name = exp_constraint.name
+ # Make sure that the constraint exists
+ self.assertTrue(const_name in bone.constraints,
+ "Bone %s is expected to contain constraint %s, but it does not." % (
+ bone.name, const_name))
+ constraint = bone.constraints[const_name]
+ const_variables = constraint.bl_rna.properties.keys()
+
+ for var in const_variables:
+
+ if var == "is_override_data":
+ # This variable is not used for local (non linked) data.
+ # For local object it is not initialized, so don't check this value.
+ continue
+
+ value = getattr(constraint, var)
+ exp_value = getattr(exp_constraint, var)
+
+ self.assertEqual(type(value), type(exp_value),
+ "Missmatching constraint value types in pose.bones[%s].constraints[%s].%s" % (
+ bone.name, const_name, var))
+
+ if isinstance(value, str):
+ self.assertEqual(value, exp_value,
+ "Missmatching constraint value in pose.bones[%s].constraints[%s].%s" % (
+ bone.name, const_name, var))
+ elif hasattr(value, "name"):
+ # Some constraints targets the armature itself, so the armature name should missmatch.
+ if value.name == input_arm.name and exp_value.name == expected_arm.name:
+ continue
+
+ self.assertEqual(value.name, exp_value.name,
+ "Missmatching constraint value in pose.bones[%s].constraints[%s].%s" % (
+ bone.name, const_name, var))
+
+ elif isinstance(value, bool):
+ self.assertEqual(value, exp_value,
+ "Missmatching constraint boolean in pose.bones[%s].constraints[%s].%s" % (
+ bone.name, const_name, var))
+ else:
+ self.assertAlmostEqual(value, exp_value,
+ "Missmatching constraint value in pose.bones[%s].constraints[%s].%s" % (
+ bone.name, const_name, var))
+
+
+class AbstractAnimationTest:
+ @classmethod
+ def setUpClass(cls):
+ cls.testdir = args.testdir
+
+ def setUp(self):
+ self.assertTrue(self.testdir.exists(),
+ 'Test dir %s should exist' % self.testdir)
+
+
+class ArmatureSymmetrizeTest(AbstractAnimationTest, unittest.TestCase):
+ def test_symmetrize_operator(self):
+ """Test that the symmetrize operator is working correctly."""
+ bpy.ops.wm.open_mainfile(filepath=str(
+ self.testdir / "symm_test.blend"))
+
+ # T81541 (D9214)
+ arm = bpy.data.objects['transform_const_rig']
+ expected_arm = bpy.data.objects['expected_transform_const_rig']
+ self.assertEqualSymmetrize(arm, expected_arm)
+
+ # T66751 (D6009)
+ arm = bpy.data.objects['dragon_rig']
+ expected_arm = bpy.data.objects['expected_dragon_rig']
+ self.assertEqualSymmetrize(arm, expected_arm)
+
+ def assertEqualSymmetrize(self, input_arm, expected_arm):
+
+ # Symmetrize our input armature
+ bpy.context.view_layer.objects.active = input_arm
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.armature.select_all(action='SELECT')
+ bpy.ops.armature.symmetrize()
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Make sure that the bone count is the same
+ bone_len = len(input_arm.pose.bones)
+ expected_bone_len = len(expected_arm.pose.bones)
+ self.assertEqual(bone_len, expected_bone_len,
+ "Expected bone count to match")
+
+ for exp_bone in expected_arm.pose.bones:
+ bone_name = exp_bone.name
+ # Make sure that the bone exists
+ self.assertTrue(bone_name in input_arm.pose.bones,
+ "Armature is expected to contain bone %s, but it does not." % (bone_name))
+ bone = input_arm.pose.bones[bone_name]
+
+ # Loc Rot Scale
+ check_loc_rot_scale(self, bone, exp_bone)
+
+ # Parent settings
+ check_parent(self, bone, exp_bone)
+
+ # Bendy Bones
+ check_bendy_bones(self, bone, exp_bone)
+
+ # IK
+ check_ik(self, bone, exp_bone)
+
+ # Constraints
+ check_constraints(self, input_arm, expected_arm, bone, exp_bone)
+
+ def assertEqualVector(self, vec1, vec2, check_str, bone_name) -> None:
+ for idx, value in enumerate(vec1):
+ self.assertAlmostEqual(
+ value, vec2[idx], 3, "%s does not match with expected value on bone %s" % (check_str, bone_name))
+
+
+def main():
+ global args
+ import argparse
+
+ if '--' in sys.argv:
+ argv = [sys.argv[0]] + sys.argv[sys.argv.index('--') + 1:]
+ else:
+ argv = sys.argv
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--testdir', required=True, type=pathlib.Path)
+ args, remaining = parser.parse_known_args(argv)
+
+ unittest.main(argv=remaining)
+
+
+if __name__ == "__main__":
+ main()