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:
authorHans Goudey <h.goudey@me.com>2020-06-05 18:34:10 +0300
committerHans Goudey <h.goudey@me.com>2020-06-05 18:34:10 +0300
commit76e9cdc90a43458ab0bb5d66883631f9dc5fe53b (patch)
treeaf531a8989c7bad0bc8d3020a5ef61ac0096c315 /source/blender
parent8a971c9d91fafaa77fcb320bfd1f25e7e905dce2 (diff)
parent9b099c86123fc828a194c59ce5b8bbf5a56f9cdb (diff)
Merge branch 'master' into modifier-panels-ui
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_anim_data.h3
-rw-r--r--source/blender/blenkernel/BKE_blender.h6
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h30
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h37
-rw-r--r--source/blender/blenkernel/BKE_camera.h2
-rw-r--r--source/blender/blenkernel/BKE_collection.h4
-rw-r--r--source/blender/blenkernel/BKE_curve.h3
-rw-r--r--source/blender/blenkernel/BKE_editmesh_cache.h5
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h72
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h4
-rw-r--r--source/blender/blenkernel/BKE_lib_query.h2
-rw-r--r--source/blender/blenkernel/BKE_light.h3
-rw-r--r--source/blender/blenkernel/BKE_main.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h23
-rw-r--r--source/blender/blenkernel/BKE_modifier.h12
-rw-r--r--source/blender/blenkernel/BKE_nla.h3
-rw-r--r--source/blender/blenkernel/BKE_paint.h2
-rw-r--r--source/blender/blenkernel/BKE_particle.h2
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h93
-rw-r--r--source/blender/blenkernel/BKE_screen.h16
-rw-r--r--source/blender/blenkernel/BKE_simulation.h6
-rw-r--r--source/blender/blenkernel/BKE_workspace.h10
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c56
-rw-r--r--source/blender/blenkernel/intern/action.c10
-rw-r--r--source/blender/blenkernel/intern/anim_data.c27
-rw-r--r--source/blender/blenkernel/intern/blender.c46
-rw-r--r--source/blender/blenkernel/intern/blendfile.c5
-rw-r--r--source/blender/blenkernel/intern/brush.c2
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c433
-rw-r--r--source/blender/blenkernel/intern/collection.c34
-rw-r--r--source/blender/blenkernel/intern/constraint.c8
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c2
-rw-r--r--source/blender/blenkernel/intern/curve.c49
-rw-r--r--source/blender/blenkernel/intern/customdata.c149
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c7
-rw-r--r--source/blender/blenkernel/intern/editmesh.c3
-rw-r--r--source/blender/blenkernel/intern/editmesh_cache.c44
-rw-r--r--source/blender/blenkernel/intern/fcurve.c130
-rw-r--r--source/blender/blenkernel/intern/gpencil.c24
-rw-r--r--source/blender/blenkernel/intern/ipo.c6
-rw-r--r--source/blender/blenkernel/intern/layer.c42
-rw-r--r--source/blender/blenkernel/intern/lib_id.c51
-rw-r--r--source/blender/blenkernel/intern/lib_override.c12
-rw-r--r--source/blender/blenkernel/intern/lib_query.c83
-rw-r--r--source/blender/blenkernel/intern/light.c7
-rw-r--r--source/blender/blenkernel/intern/mesh.c24
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c4
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c16
-rw-r--r--source/blender/blenkernel/intern/mesh_iterators.c272
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_runtime.c6
-rw-r--r--source/blender/blenkernel/intern/mesh_wrapper.c166
-rw-r--r--source/blender/blenkernel/intern/modifier.c39
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_smooth.c2
-rw-r--r--source/blender/blenkernel/intern/nla.c28
-rw-r--r--source/blender/blenkernel/intern/object.c7
-rw-r--r--source/blender/blenkernel/intern/particle.c4
-rw-r--r--source/blender/blenkernel/intern/particle_system.c4
-rw-r--r--source/blender/blenkernel/intern/pbvh.c786
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c437
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c1
-rw-r--r--source/blender/blenkernel/intern/scene.c9
-rw-r--r--source/blender/blenkernel/intern/seqcache.c13
-rw-r--r--source/blender/blenkernel/intern/seqprefetch.c67
-rw-r--r--source/blender/blenkernel/intern/sequencer.c4
-rw-r--r--source/blender/blenkernel/intern/simulation.cc7
-rw-r--r--source/blender/blenkernel/intern/studiolight.c4
-rw-r--r--source/blender/blenkernel/intern/unit.c111
-rw-r--r--source/blender/blenkernel/intern/workspace.c78
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c5
-rw-r--r--source/blender/blenlib/BLI_assert.h8
-rw-r--r--source/blender/blenlib/BLI_math_vector.h1
-rw-r--r--source/blender/blenlib/BLI_task.h76
-rw-r--r--source/blender/blenlib/CMakeLists.txt3
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c4
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c2
-rw-r--r--source/blender/blenlib/intern/math_color.c3
-rw-r--r--source/blender/blenlib/intern/math_geom.c28
-rw-r--r--source/blender/blenlib/intern/math_vector.c29
-rw-r--r--source/blender/blenlib/intern/storage.c56
-rw-r--r--source/blender/blenlib/intern/task_graph.cc166
-rw-r--r--source/blender/blenloader/BLO_read_write.h210
-rw-r--r--source/blender/blenloader/BLO_undofile.h26
-rw-r--r--source/blender/blenloader/CMakeLists.txt1
-rw-r--r--source/blender/blenloader/intern/readblenentry.c35
-rw-r--r--source/blender/blenloader/intern/readfile.c357
-rw-r--r--source/blender/blenloader/intern/readfile.h3
-rw-r--r--source/blender/blenloader/intern/undofile.c84
-rw-r--r--source/blender/blenloader/intern/versioning_250.c29
-rw-r--r--source/blender/blenloader/intern/versioning_280.c145
-rw-r--r--source/blender/blenloader/intern/versioning_290.c192
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c12
-rw-r--r--source/blender/blenloader/intern/writefile.c1435
-rw-r--r--source/blender/bmesh/CMakeLists.txt6
-rw-r--r--source/blender/bmesh/bmesh.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_convert.c (renamed from source/blender/bmesh/intern/bmesh_mesh_conv.c)4
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_convert.h (renamed from source/blender/bmesh/intern/bmesh_mesh_conv.h)0
-rw-r--r--source/blender/bmesh/intern/bmesh_query.c44
-rw-r--r--source/blender/bmesh/intern/bmesh_query.h10
-rw-r--r--source/blender/bmesh/operators/bmo_mesh_convert.c (renamed from source/blender/bmesh/operators/bmo_mesh_conv.c)0
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c57
-rw-r--r--source/blender/bmesh/tools/bmesh_path.c2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc13
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc23
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.cc2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.h1
-rw-r--r--source/blender/draw/CMakeLists.txt5
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c25
-rw-r--r--source/blender/draw/engines/basic/shaders/depth_frag.glsl (renamed from source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl)0
-rw-r--r--source/blender/draw/engines/basic/shaders/depth_vert.glsl (renamed from source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl)4
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c15
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c16
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c8
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c95
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c44
-rw-r--r--source/blender/draw/engines/eevee/eevee_lut_gen.c198
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c2352
-rw-r--r--source/blender/draw/engines/eevee/eevee_mist.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h170
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c16
-rw-r--r--source/blender/draw/engines/eevee/eevee_renderpasses.c48
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders.c488
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows.c44
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c137
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c33
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl8
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl27
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_frag.glsl21
-rw-r--r--source/blender/draw/engines/external/external_engine.c18
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_antialiasing.c5
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c9
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h2
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl12
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.c44
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_curve.c5
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_text.c3
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c14
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c36
-rw-r--r--source/blender/draw/engines/overlay/overlay_facing.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_gpencil.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_motion_path.c4
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_particle.c8
-rw-r--r--source/blender/draw/engines/overlay/overlay_pointcloud.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h7
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c23
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c13
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl16
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl11
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_vert.glsl7
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl11
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl1
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl24
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_antialiasing.c7
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c6
-rw-r--r--source/blender/draw/engines/workbench/workbench_opaque.c16
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.c33
-rw-r--r--source/blender/draw/engines/workbench/workbench_transparent.c12
-rw-r--r--source/blender/draw/intern/DRW_render.h32
-rw-r--r--source/blender/draw/intern/draw_cache.c6
-rw-r--r--source/blender/draw/intern/draw_cache_extract.h5
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.c686
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h5
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.c18
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.c11
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c53
-rw-r--r--source/blender/draw/intern/draw_common.h12
-rw-r--r--source/blender/draw/intern/draw_hair.c58
-rw-r--r--source/blender/draw/intern/draw_manager.c55
-rw-r--r--source/blender/draw/intern/draw_manager.h62
-rw-r--r--source/blender/draw/intern/draw_manager_data.c233
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c247
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c25
-rw-r--r--source/blender/draw/intern/draw_manager_texture.c4
-rw-r--r--source/blender/draw/intern/shaders/common_globals_lib.glsl1
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c4
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c6
-rw-r--r--source/blender/editors/animation/anim_draw.c61
-rw-r--r--source/blender/editors/animation/anim_filter.c2
-rw-r--r--source/blender/editors/animation/drivers.c17
-rw-r--r--source/blender/editors/animation/keyframing.c21
-rw-r--r--source/blender/editors/armature/armature_add.c4
-rw-r--r--source/blender/editors/armature/armature_select.c260
-rw-r--r--source/blender/editors/curve/editcurve.c16
-rw-r--r--source/blender/editors/curve/editcurve_add.c4
-rw-r--r--source/blender/editors/curve/editcurve_query.c13
-rw-r--r--source/blender/editors/curve/editcurve_select.c11
-rw-r--r--source/blender/editors/curve/editcurve_undo.c16
-rw-r--r--source/blender/editors/curve/editfont_undo.c2
-rw-r--r--source/blender/editors/gizmo_library/CMakeLists.txt1
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c560
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c46
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c43
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c13
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c79
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c54
-rw-r--r--source/blender/editors/gpencil/gpencil_uv.c154
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_paint.c43
-rw-r--r--source/blender/editors/include/ED_anim_api.h3
-rw-r--r--source/blender/editors/include/ED_armature.h8
-rw-r--r--source/blender/editors/include/ED_gizmo_library.h38
-rw-r--r--source/blender/editors/include/ED_gpencil.h6
-rw-r--r--source/blender/editors/include/ED_node.h5
-rw-r--r--source/blender/editors/include/ED_object.h38
-rw-r--r--source/blender/editors/include/ED_outliner.h1
-rw-r--r--source/blender/editors/include/ED_transform.h25
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h7
-rw-r--r--source/blender/editors/include/ED_uvedit.h17
-rw-r--r--source/blender/editors/include/ED_view3d.h4
-rw-r--r--source/blender/editors/include/UI_interface.h6
-rw-r--r--source/blender/editors/interface/CMakeLists.txt2
-rw-r--r--source/blender/editors/interface/interface_align.c6
-rw-r--r--source/blender/editors/interface/interface_anim.c2
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c34
-rw-r--r--source/blender/editors/interface/interface_handlers.c2
-rw-r--r--source/blender/editors/interface/interface_icons.c10
-rw-r--r--source/blender/editors/interface/interface_panel.c46
-rw-r--r--source/blender/editors/interface/interface_region_hud.c5
-rw-r--r--source/blender/editors/interface/interface_templates.c40
-rw-r--r--source/blender/editors/interface/view2d_draw.c2
-rw-r--r--source/blender/editors/interface/view2d_ops.c185
-rw-r--r--source/blender/editors/io/io_alembic.c2
-rw-r--r--source/blender/editors/mask/mask_draw.c2
-rw-r--r--source/blender/editors/mesh/editmesh_add.c113
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c1
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c23
-rw-r--r--source/blender/editors/mesh/editmesh_mask_extract.c2
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c3
-rw-r--r--source/blender/editors/object/object_add.c65
-rw-r--r--source/blender/editors/object/object_constraint.c37
-rw-r--r--source/blender/editors/object/object_edit.c85
-rw-r--r--source/blender/editors/object/object_modes.c94
-rw-r--r--source/blender/editors/object/object_modifier.c4
-rw-r--r--source/blender/editors/object/object_relations.c20
-rw-r--r--source/blender/editors/object/object_volume.c2
-rw-r--r--source/blender/editors/physics/particle_edit.c92
-rw-r--r--source/blender/editors/physics/particle_edit_undo.c2
-rw-r--r--source/blender/editors/physics/physics_fluid.c9
-rw-r--r--source/blender/editors/render/render_internal.c20
-rw-r--r--source/blender/editors/screen/glutil.c4
-rw-r--r--source/blender/editors/screen/screen_context.c4
-rw-r--r--source/blender/editors/screen/screen_edit.c103
-rw-r--r--source/blender/editors/screen/screen_geometry.c2
-rw-r--r--source/blender/editors/screen/screen_intern.h5
-rw-r--r--source/blender/editors/screen/screen_ops.c23
-rw-r--r--source/blender/editors/screen/workspace_edit.c14
-rw-r--r--source/blender/editors/screen/workspace_layout_edit.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c14
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c189
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h5
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c14
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c21
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c56
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c144
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_automasking.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c353
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.c29
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c43
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h26
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_pose.c301
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c3
-rw-r--r--source/blender/editors/space_action/action_edit.c4
-rw-r--r--source/blender/editors/space_api/spacetypes.c1
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c4
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c4
-rw-r--r--source/blender/editors/space_console/console_draw.c8
-rw-r--r--source/blender/editors/space_file/file_draw.c79
-rw-r--r--source/blender/editors/space_file/file_ops.c28
-rw-r--r--source/blender/editors/space_file/filelist.c96
-rw-r--r--source/blender/editors/space_file/fsmenu.c7
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c2
-rw-r--r--source/blender/editors/space_graph/graph_draw.c2
-rw-r--r--source/blender/editors/space_graph/graph_edit.c13
-rw-r--r--source/blender/editors/space_graph/graph_utils.c4
-rw-r--r--source/blender/editors/space_graph/space_graph.c2
-rw-r--r--source/blender/editors/space_image/image_draw.c6
-rw-r--r--source/blender/editors/space_image/image_ops.c5
-rw-r--r--source/blender/editors/space_image/image_undo.c2
-rw-r--r--source/blender/editors/space_info/info_stats.c2
-rw-r--r--source/blender/editors/space_info/textview.c2
-rw-r--r--source/blender/editors/space_info/textview.h2
-rw-r--r--source/blender/editors/space_nla/nla_draw.c2
-rw-r--r--source/blender/editors/space_nla/nla_edit.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c2
-rw-r--r--source/blender/editors/space_node/node_add.c2
-rw-r--r--source/blender/editors/space_node/node_edit.c10
-rw-r--r--source/blender/editors/space_node/node_select.c52
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c52
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c3
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c386
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h15
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c247
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c69
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c14
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c9
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c422
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h6
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c17
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_placement.c1153
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c109
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c20
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c26
-rw-r--r--source/blender/editors/transform/transform.c104
-rw-r--r--source/blender/editors/transform/transform.h111
-rw-r--r--source/blender/editors/transform/transform_constraints.c240
-rw-r--r--source/blender/editors/transform/transform_constraints.h5
-rw-r--r--source/blender/editors/transform/transform_convert.c19
-rw-r--r--source/blender/editors/transform/transform_convert_curve.c10
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c3
-rw-r--r--source/blender/editors/transform/transform_generics.c100
-rw-r--r--source/blender/editors/transform/transform_gizmo_2d.c4
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c103
-rw-r--r--source/blender/editors/transform/transform_mode_align.c4
-rw-r--r--source/blender/editors/transform/transform_mode_baketime.c4
-rw-r--r--source/blender/editors/transform/transform_mode_bbone_resize.c4
-rw-r--r--source/blender/editors/transform/transform_mode_bend.c4
-rw-r--r--source/blender/editors/transform/transform_mode_boneenvelope.c4
-rw-r--r--source/blender/editors/transform/transform_mode_boneroll.c4
-rw-r--r--source/blender/editors/transform/transform_mode_curveshrinkfatten.c4
-rw-r--r--source/blender/editors/transform/transform_mode_edge_bevelweight.c4
-rw-r--r--source/blender/editors/transform/transform_mode_edge_crease.c4
-rw-r--r--source/blender/editors/transform/transform_mode_edge_seq_slide.c4
-rw-r--r--source/blender/editors/transform/transform_mode_gpopacity.c4
-rw-r--r--source/blender/editors/transform/transform_mode_gpshrinkfatten.c4
-rw-r--r--source/blender/editors/transform/transform_mode_maskshrinkfatten.c8
-rw-r--r--source/blender/editors/transform/transform_mode_mirror.c8
-rw-r--r--source/blender/editors/transform/transform_mode_push_pull.c4
-rw-r--r--source/blender/editors/transform/transform_mode_resize.c4
-rw-r--r--source/blender/editors/transform/transform_mode_rotate.c4
-rw-r--r--source/blender/editors/transform/transform_mode_shear.c7
-rw-r--r--source/blender/editors/transform/transform_mode_shrink_fatten.c4
-rw-r--r--source/blender/editors/transform/transform_mode_skin_resize.c5
-rw-r--r--source/blender/editors/transform/transform_mode_tilt.c4
-rw-r--r--source/blender/editors/transform/transform_mode_tosphere.c4
-rw-r--r--source/blender/editors/transform/transform_mode_trackball.c4
-rw-r--r--source/blender/editors/transform/transform_mode_translate.c4
-rw-r--r--source/blender/editors/transform/transform_orientations.c209
-rw-r--r--source/blender/editors/transform/transform_snap.c123
-rw-r--r--source/blender/editors/transform/transform_snap_object.c353
-rw-r--r--source/blender/editors/undo/memfile_undo.c2
-rw-r--r--source/blender/editors/util/ed_util.c6
-rw-r--r--source/blender/editors/uvedit/uvedit_buttons.c21
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c18
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h11
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c247
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c206
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c5
-rw-r--r--source/blender/freestyle/intern/view_map/Silhouette.h8
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c5
-rw-r--r--source/blender/gpu/GPU_draw.h2
-rw-r--r--source/blender/gpu/GPU_material.h14
-rw-r--r--source/blender/gpu/GPU_shader.h8
-rw-r--r--source/blender/gpu/GPU_shader_interface.h57
-rw-r--r--source/blender/gpu/GPU_texture.h28
-rw-r--r--source/blender/gpu/GPU_vertex_format.h5
-rw-r--r--source/blender/gpu/intern/gpu_batch.c6
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c2
-rw-r--r--source/blender/gpu/intern/gpu_draw.c39
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c6
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c49
-rw-r--r--source/blender/gpu/intern/gpu_material.c8
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c44
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c30
-rw-r--r--source/blender/gpu/intern/gpu_shader.c64
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c486
-rw-r--r--source/blender/gpu/intern/gpu_texture.c355
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.c89
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl10
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl7
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl168
-rw-r--r--source/blender/io/alembic/intern/abc_customdata.cc13
-rw-r--r--source/blender/io/alembic/intern/abc_customdata.h10
-rw-r--r--source/blender/io/alembic/intern/abc_writer_archive.cc2
-rw-r--r--source/blender/io/alembic/intern/alembic_capi.cc3
-rw-r--r--source/blender/io/collada/AnimationImporter.cpp8
-rw-r--r--source/blender/io/collada/BCAnimationCurve.cpp4
-rw-r--r--source/blender/io/collada/BCAnimationSampler.cpp2
-rw-r--r--source/blender/io/collada/DocumentExporter.cpp13
-rw-r--r--source/blender/io/collada/ErrorHandler.h2
-rw-r--r--source/blender/io/usd/intern/abstract_hierarchy_iterator.cc2
-rw-r--r--source/blender/io/usd/intern/usd_capi.cc5
-rw-r--r--source/blender/io/usd/intern/usd_writer_mesh.cc4
-rw-r--r--source/blender/io/usd/intern/usd_writer_transform.cc2
-rw-r--r--source/blender/makesdna/DNA_ID.h2
-rw-r--r--source/blender/makesdna/DNA_brush_types.h9
-rw-r--r--source/blender/makesdna/DNA_curve_types.h4
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h8
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h29
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h4
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h6
-rw-r--r--source/blender/makesdna/DNA_scene_types.h2
-rw-r--r--source/blender/makesdna/DNA_space_types.h7
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h2
-rw-r--r--source/blender/makesdna/DNA_view3d_defaults.h4
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h17
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/RNA_define.h1
-rw-r--r--source/blender/makesrna/intern/makesrna.c41
-rw-r--r--source/blender/makesrna/intern/rna_access.c6
-rw-r--r--source/blender/makesrna/intern/rna_action.c6
-rw-r--r--source/blender/makesrna/intern/rna_animation.c8
-rw-r--r--source/blender/makesrna/intern/rna_armature.c19
-rw-r--r--source/blender/makesrna/intern/rna_brush.c16
-rw-r--r--source/blender/makesrna/intern/rna_camera.c16
-rw-r--r--source/blender/makesrna/intern/rna_collection.c10
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c160
-rw-r--r--source/blender/makesrna/intern/rna_define.c204
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c2
-rw-r--r--source/blender/makesrna/intern/rna_fluid.c5
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c2
-rw-r--r--source/blender/makesrna/intern/rna_internal.h9
-rw-r--r--source/blender/makesrna/intern/rna_light.c60
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c315
-rw-r--r--source/blender/makesrna/intern/rna_nla.c2
-rw-r--r--source/blender/makesrna/intern/rna_object.c4
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c3
-rw-r--r--source/blender/makesrna/intern/rna_render.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene.c4
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c11
-rw-r--r--source/blender/makesrna/intern/rna_space.c15
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c17
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c4
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo.c15
-rw-r--r--source/blender/makesrna/intern/rna_workspace.c2
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c17
-rw-r--r--source/blender/modifiers/intern/MOD_array.c1
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c12
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c1
-rw-r--r--source/blender/modifiers/intern/MOD_build.c1
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c19
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c16
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c17
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c10
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c12
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c16
-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.c10
-rw-r--r--source/blender/modifiers/intern/MOD_fluid.c1
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c12
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c19
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c17
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c16
-rw-r--r--source/blender/modifiers/intern/MOD_mask.cc9
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache.c1
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c16
-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_normal_edit.c14
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c4
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c1
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c24
-rw-r--r--source/blender/modifiers/intern/MOD_remesh.c2
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c1
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c16
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c17
-rw-r--r--source/blender/modifiers/intern/MOD_simulation.cc1
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c9
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c15
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c14
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c74
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c12
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c1
-rw-r--r--source/blender/modifiers/intern/MOD_ui_common.c186
-rw-r--r--source/blender/modifiers/intern/MOD_ui_common.h9
-rw-r--r--source/blender/modifiers/intern/MOD_util.c11
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c1
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c12
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c21
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c15
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c11
-rw-r--r--source/blender/modifiers/intern/MOD_weightvg_util.c41
-rw-r--r--source/blender/modifiers/intern/MOD_weightvg_util.h3
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c7
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c41
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c9
-rw-r--r--source/blender/modifiers/intern/MOD_weld.c25
-rw-r--r--source/blender/modifiers/intern/MOD_wireframe.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_material.c13
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c56
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c165
-rw-r--r--source/blender/python/gpu/gpu_py_offscreen.c10
-rw-r--r--source/blender/python/gpu/gpu_py_shader.c4
-rw-r--r--source/blender/python/intern/bpy.c5
-rw-r--r--source/blender/python/intern/bpy_app.c12
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c12
-rw-r--r--source/blender/python/intern/bpy_library.h6
-rw-r--r--source/blender/python/intern/bpy_library_load.c16
-rw-r--r--source/blender/python/intern/bpy_library_write.c19
-rw-r--r--source/blender/python/intern/bpy_rna.c31
-rw-r--r--source/blender/python/intern/bpy_rna_anim.c8
-rw-r--r--source/blender/python/intern/bpy_rna_callback.c8
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.c47
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.h4
-rw-r--r--source/blender/python/intern/bpy_rna_types_capi.c52
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h3
-rw-r--r--source/blender/render/intern/source/external_engine.c4
-rw-r--r--source/blender/render/intern/source/initrender.c2
-rw-r--r--source/blender/render/intern/source/pipeline.c30
-rw-r--r--source/blender/windowmanager/WM_api.h14
-rw-r--r--source/blender/windowmanager/WM_keymap.h2
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_types.h17
-rw-r--r--source/blender/windowmanager/intern/wm.c2
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c16
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c6
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c42
-rw-r--r--source/blender/windowmanager/intern/wm_files.c273
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c2
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c2
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c18
-rw-r--r--source/blender/windowmanager/intern/wm_splash_screen.c46
-rw-r--r--source/blender/windowmanager/intern/wm_window.c88
-rw-r--r--source/blender/windowmanager/wm_files.h2
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr.c7
541 files changed, 15496 insertions, 10203 deletions
diff --git a/source/blender/blenkernel/BKE_anim_data.h b/source/blender/blenkernel/BKE_anim_data.h
index 8809fadd55c..5aeaf4405f5 100644
--- a/source/blender/blenkernel/BKE_anim_data.h
+++ b/source/blender/blenkernel/BKE_anim_data.h
@@ -32,6 +32,7 @@ extern "C" {
struct AnimData;
struct ID;
+struct LibraryForeachIDData;
struct Main;
struct ReportList;
struct bAction;
@@ -58,6 +59,8 @@ void BKE_animdata_free(struct ID *id, const bool do_id_user);
/* Return true if the ID-block has non-empty AnimData. */
bool BKE_animdata_id_is_animated(const struct ID *id);
+void BKE_animdata_foreach_id(struct AnimData *adt, struct LibraryForeachIDData *data);
+
/* Copy AnimData */
struct AnimData *BKE_animdata_copy(struct Main *bmain, struct AnimData *adt, const int flag);
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 59c7a1dfd2b..3feba4b3a66 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -34,12 +34,6 @@ void BKE_blender_free(void);
void BKE_blender_globals_init(void);
void BKE_blender_globals_clear(void);
-void BKE_blender_version_string(char *version_str,
- size_t maxncpy,
- short version,
- short subversion,
- bool v_prefix,
- bool include_subversion);
void BKE_blender_userdef_data_swap(struct UserDef *userdef_dst, struct UserDef *userdef_src);
void BKE_blender_userdef_data_set(struct UserDef *userdef);
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 5510f3c3d2e..9d948dfd57b 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -30,22 +30,26 @@ extern "C" {
*
* \note Use #STRINGIFY() rather than defining with quotes.
*/
+
+/* Blender major and minor version. */
#define BLENDER_VERSION 290
-#define BLENDER_SUBVERSION 2
-/** Several breakages with 280, e.g. collections vs layers. */
-#define BLENDER_MINVERSION 280
-#define BLENDER_MINSUBVERSION 0
-
-/** Used by packaging tools. */
-/** Can be left blank, otherwise a,b,c... etc with no quotes. */
-#define BLENDER_VERSION_CHAR
-/** alpha/beta/rc/release, docs use this. */
+/* Blender patch version for bugfix releases. */
+#define BLENDER_VERSION_PATCH 0
+/** Blender release cycle stage: alpha/beta/rc/release. */
#define BLENDER_VERSION_CYCLE alpha
-/** Optionally set to 1,2,... for example to get alpha1 or rc2. */
-#define BLENDER_VERSION_CYCLE_NUMBER
-/** Defined in from blender.c */
-extern char versionstr[];
+/* Blender file format version. */
+#define BLENDER_FILE_VERSION BLENDER_VERSION
+#define BLENDER_FILE_SUBVERSION 4
+
+/* 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
+ * was written with too new a version. */
+#define BLENDER_FILE_MIN_VERSION 280
+#define BLENDER_FILE_MIN_SUBVERSION 0
+
+/** User readable version string. */
+const char *BKE_blender_version_string(void);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 458f1ab7a56..5d7e8fe743e 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -25,6 +25,7 @@
#include "BLI_bitmap.h"
#include "BLI_kdopbvh.h"
+#include "BLI_threads.h"
#ifdef __cplusplus
extern "C" {
@@ -39,7 +40,7 @@ struct MFace;
struct MVert;
struct Mesh;
-typedef struct LinkNode BVHCache;
+struct BVHCache;
/**
* Struct that stores basic information about a BVHTree built from a edit-mesh.
@@ -98,6 +99,9 @@ typedef enum BVHCacheType {
BVHTREE_FROM_EM_VERTS,
BVHTREE_FROM_EM_EDGES,
BVHTREE_FROM_EM_LOOPTRI,
+
+ /* Keep `BVHTREE_MAX_ITEM` as last item. */
+ BVHTREE_MAX_ITEM,
} BVHCacheType;
/**
@@ -122,7 +126,8 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -134,7 +139,8 @@ BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_editmesh_edges(
BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis);
@@ -147,7 +153,8 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -161,7 +168,8 @@ BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -175,7 +183,8 @@ BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_editmesh_looptri(
BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis);
@@ -188,7 +197,8 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -204,7 +214,8 @@ BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
struct Mesh *mesh,
@@ -215,7 +226,8 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const int tree_type,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
/**
* Frees data allocated by a call to bvhtree_from_mesh_*.
@@ -244,10 +256,9 @@ float bvhtree_sphereray_tri_intersection(const BVHTreeRay *ray,
/* Using local coordinates */
-bool bvhcache_find(const BVHCache *cache, BVHCacheType type, BVHTree **r_tree);
-bool bvhcache_has_tree(const BVHCache *cache, const BVHTree *tree);
-void bvhcache_insert(BVHCache **cache_p, BVHTree *tree, BVHCacheType type);
-void bvhcache_free(BVHCache **cache_p);
+bool bvhcache_has_tree(const struct BVHCache *bvh_cache, const BVHTree *tree);
+struct BVHCache *bvhcache_init(void);
+void bvhcache_free(struct BVHCache *bvh_cache);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index f93003dc423..812f5d520d7 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -22,7 +22,7 @@
/** \file
* \ingroup bke
- * \brief Camera datablock and utility functions.
+ * \brief Camera data-block and utility functions.
*/
#ifdef __cplusplus
extern "C" {
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index a314008f715..f4b56aa152f 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -50,6 +50,10 @@ typedef struct CollectionParent {
struct Collection *BKE_collection_add(struct Main *bmain,
struct Collection *parent,
const char *name);
+void BKE_collection_add_from_object(struct Main *bmain,
+ struct Scene *scene,
+ const struct Object *ob_src,
+ struct Collection *collection_dst);
void BKE_collection_free(struct Collection *collection);
bool BKE_collection_delete(struct Main *bmain, struct Collection *collection, bool hierarchy);
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index bf270f2c06f..40f73ccfe84 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -173,7 +173,8 @@ void BKE_nurbList_handles_recalculate(struct ListBase *editnurb,
const char flag);
void BKE_nurbList_handles_autocalc(ListBase *editnurb, int flag);
-void BKE_nurbList_flag_set(ListBase *editnurb, short flag);
+void BKE_nurbList_flag_set(ListBase *editnurb, short flag, bool set);
+bool BKE_nurbList_flag_set_from_flag(ListBase *editnurb, short from_flag, short flag);
void BKE_nurb_free(struct Nurb *nu);
struct Nurb *BKE_nurb_duplicate(const struct Nurb *nu);
diff --git a/source/blender/blenkernel/BKE_editmesh_cache.h b/source/blender/blenkernel/BKE_editmesh_cache.h
index c6a2541e0a7..6c812098b2e 100644
--- a/source/blender/blenkernel/BKE_editmesh_cache.h
+++ b/source/blender/blenkernel/BKE_editmesh_cache.h
@@ -33,6 +33,11 @@ void BKE_editmesh_cache_ensure_vert_normals(struct BMEditMesh *em, struct EditMe
void BKE_editmesh_cache_ensure_poly_centers(struct BMEditMesh *em, struct EditMeshData *emd);
+bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em,
+ struct EditMeshData *emd,
+ float min[3],
+ float max[3]);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 21a9b7b8b04..c3a597e29b9 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -37,6 +37,7 @@ struct FModifier;
struct AnimData;
struct BezTriple;
+struct LibraryForeachIDData;
struct PathResolvedRNA;
struct PointerRNA;
struct PropertyRNA;
@@ -178,17 +179,19 @@ int BKE_fcm_envelope_find_index(struct FCM_EnvelopeData *array,
#define BEZT_BINARYSEARCH_THRESH 0.01f /* was 0.00001, but giving errors */
/* -------- Data Management -------- */
+struct FCurve *BKE_fcurve_create(void);
+void BKE_fcurve_free(struct FCurve *fcu);
+struct FCurve *BKE_fcurve_copy(const struct FCurve *fcu);
-void free_fcurve(struct FCurve *fcu);
-struct FCurve *copy_fcurve(const struct FCurve *fcu);
+void BKE_fcurves_free(ListBase *list);
+void BKE_fcurves_copy(ListBase *dst, ListBase *src);
-void free_fcurves(ListBase *list);
-void copy_fcurves(ListBase *dst, ListBase *src);
+void BKE_fcurve_foreach_id(struct FCurve *fcu, struct LibraryForeachIDData *data);
/* find matching F-Curve in the given list of F-Curves */
-struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_index);
+struct FCurve *BKE_fcurve_find(ListBase *list, const char rna_path[], const int array_index);
-struct FCurve *iter_step_fcurve(struct FCurve *fcu_iter, const char rna_path[]);
+struct FCurve *BKE_fcurve_iter_step(struct FCurve *fcu_iter, const char rna_path[]);
/* high level function to get an fcurve from C without having the rna */
struct FCurve *id_data_find_fcurve(
@@ -196,31 +199,28 @@ struct FCurve *id_data_find_fcurve(
/* Get list of LinkData's containing pointers to the F-Curves which control the types of data
* indicated
- * e.g. numMatches = list_find_data_fcurves(matches, &act->curves, "pose.bones[", "MyFancyBone");
+ * e.g. numMatches = BKE_fcurves_filter(matches, &act->curves, "pose.bones[", "MyFancyBone");
*/
-int list_find_data_fcurves(ListBase *dst,
- ListBase *src,
- const char *dataPrefix,
- const char *dataName);
+int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName);
/* Find an f-curve based on an rna property. */
-struct FCurve *rna_get_fcurve(struct PointerRNA *ptr,
- struct PropertyRNA *prop,
- int rnaindex,
- struct AnimData **r_adt,
- struct bAction **r_action,
- bool *r_driven,
- bool *r_special);
+struct FCurve *BKE_fcurve_find_by_rna(struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ int rnaindex,
+ struct AnimData **r_adt,
+ struct bAction **r_action,
+ bool *r_driven,
+ bool *r_special);
/* Same as above, but takes a context data,
* temp hack needed for complex paths like texture ones. */
-struct FCurve *rna_get_fcurve_context_ui(struct bContext *C,
- struct PointerRNA *ptr,
- struct PropertyRNA *prop,
- int rnaindex,
- struct AnimData **r_animdata,
- struct bAction **r_action,
- bool *r_driven,
- bool *r_special);
+struct FCurve *BKE_fcurve_find_by_rna_context_ui(struct bContext *C,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ int rnaindex,
+ struct AnimData **r_animdata,
+ struct bAction **r_action,
+ bool *r_driven,
+ bool *r_special);
/* Binary search algorithm for finding where to 'insert' BezTriple with given frame number.
* Returns the index to insert at (data already at that index will be offset if replace is 0)
@@ -228,25 +228,25 @@ struct FCurve *rna_get_fcurve_context_ui(struct bContext *C,
int binarysearch_bezt_index(struct BezTriple array[], float frame, int arraylen, bool *r_replace);
/* get the time extents for F-Curve */
-bool calc_fcurve_range(
+bool BKE_fcurve_calc_range(
struct FCurve *fcu, float *min, float *max, const bool do_sel_only, const bool do_min_length);
/* get the bounding-box extents for F-Curve */
-bool calc_fcurve_bounds(struct FCurve *fcu,
- float *xmin,
- float *xmax,
- float *ymin,
- float *ymax,
- const bool do_sel_only,
- const bool include_handles);
+bool BKE_fcurve_calc_bounds(struct FCurve *fcu,
+ float *xmin,
+ float *xmax,
+ float *ymin,
+ float *ymax,
+ const bool do_sel_only,
+ const bool include_handles);
/* .............. */
/* Are keyframes on F-Curve of any use (to final result, and to show in editors)? */
-bool fcurve_are_keyframes_usable(struct FCurve *fcu);
+bool BKE_fcurve_are_keyframes_usable(struct FCurve *fcu);
/* Can keyframes be added to F-Curve? */
-bool fcurve_is_keyframable(struct FCurve *fcu);
+bool BKE_fcurve_is_keyframable(struct FCurve *fcu);
bool BKE_fcurve_is_protected(struct FCurve *fcu);
/* The curve is an infinite cycle via Cycles modifier */
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index faa331aa02d..85ba8175143 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -41,6 +41,7 @@ struct Object;
struct Scene;
struct SpaceImage;
struct ToolSettings;
+struct ViewLayer;
struct bDeformGroup;
struct bGPDframe;
struct bGPDlayer;
@@ -253,7 +254,8 @@ typedef void (*gpIterCb)(struct bGPDlayer *layer,
struct bGPDstroke *stroke,
void *thunk);
-void BKE_gpencil_visible_stroke_iter(struct Object *ob,
+void BKE_gpencil_visible_stroke_iter(struct ViewLayer *view_layer,
+ struct Object *ob,
gpIterCb layer_cb,
gpIterCb stroke_cb,
void *thunk,
diff --git a/source/blender/blenkernel/BKE_lib_query.h b/source/blender/blenkernel/BKE_lib_query.h
index fac1852eafe..c5a25e8e7af 100644
--- a/source/blender/blenkernel/BKE_lib_query.h
+++ b/source/blender/blenkernel/BKE_lib_query.h
@@ -94,6 +94,8 @@ enum {
typedef struct LibraryIDLinkCallbackData {
void *user_data;
+ /** Main database used to call `BKE_library_foreach_ID_link()`. */
+ struct Main *bmain;
/**
* 'Real' ID, the one that might be in bmain, only differs from self_id when the later is an
* embedded one.
diff --git a/source/blender/blenkernel/BKE_light.h b/source/blender/blenkernel/BKE_light.h
index 17f7a8596bf..ead27ec8002 100644
--- a/source/blender/blenkernel/BKE_light.h
+++ b/source/blender/blenkernel/BKE_light.h
@@ -31,6 +31,7 @@
extern "C" {
#endif
+struct Depsgraph;
struct Light;
struct Main;
@@ -38,6 +39,8 @@ struct Light *BKE_light_add(struct Main *bmain, const char *name) ATTR_WARN_UNUS
struct Light *BKE_light_copy(struct Main *bmain, const struct Light *la) ATTR_WARN_UNUSED_RESULT;
struct Light *BKE_light_localize(struct Light *la) ATTR_WARN_UNUSED_RESULT;
+void BKE_light_eval(struct Depsgraph *depsgraph, struct Light *la);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 29ec65166a9..516148728d2 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -87,7 +87,7 @@ enum {
typedef struct Main {
struct Main *next, *prev;
char name[1024]; /* 1024 = FILE_MAX */
- short versionfile, subversionfile; /* see BLENDER_VERSION, BLENDER_SUBVERSION */
+ short versionfile, subversionfile; /* see BLENDER_FILE_VERSION, BLENDER_FILE_SUBVERSION */
short minversionfile, minsubversionfile;
uint64_t build_commit_timestamp; /* commit's timestamp from buildinfo */
char build_hash[16]; /* hash from buildinfo */
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index f14b9a30d99..52d458c108d 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -85,12 +85,6 @@ struct Mesh *BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm,
const struct CustomData_MeshMasks *cd_mask_extra,
const struct Mesh *me_settings);
-struct Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap(
- struct BMEditMesh *em,
- const struct CustomData_MeshMasks *cd_mask_extra,
- float (*vertexCos)[3],
- const struct Mesh *me_settings);
-
int poly_find_loop_from_vert(const struct MPoly *poly, const struct MLoop *loopstart, uint vert);
int poly_get_adj_loops_from_vert(const struct MPoly *poly,
const struct MLoop *mloop,
@@ -673,6 +667,23 @@ void BKE_mesh_calc_edges_loose(struct Mesh *mesh);
void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select);
void BKE_mesh_calc_edges_tessface(struct Mesh *mesh);
+/* *** mesh_geomtype.c *** */
+struct Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(
+ struct BMEditMesh *em,
+ const struct CustomData_MeshMasks *cd_mask_extra,
+ float (*vertexCos)[3],
+ const struct Mesh *me_settings);
+struct Mesh *BKE_mesh_wrapper_from_editmesh(struct BMEditMesh *em,
+ const struct CustomData_MeshMasks *cd_mask_extra,
+ const struct Mesh *me_settings);
+void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me);
+bool BKE_mesh_wrapper_minmax(const struct Mesh *me, float min[3], float max[3]);
+void BKE_mesh_wrapper_normals_update(struct Mesh *me);
+
+/* In DerivedMesh.c */
+void BKE_mesh_wrapper_deferred_finalize(struct Mesh *me_eval,
+ const CustomData_MeshMasks *final_datamask);
+
/* **** Depsgraph evaluation **** */
void BKE_mesh_eval_geometry(struct Depsgraph *depsgraph, struct Mesh *mesh);
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 672ee8f9cd5..e4cf7d44f05 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -102,6 +102,9 @@ typedef enum {
/* For modifiers that use CD_PREVIEW_MCOL for preview. */
eModifierTypeFlag_UsesPreview = (1 << 9),
eModifierTypeFlag_AcceptsVertexCosOnly = (1 << 10),
+
+ /** Accepts #BMesh input (without conversion). */
+ eModifierTypeFlag_AcceptsBMesh = (1 << 11),
} ModifierTypeFlag;
/* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */
@@ -212,10 +215,10 @@ typedef struct ModifierTypeInfo {
/********************* Non-deform modifier functions *********************/
- /* For non-deform types: apply the modifier and return a mesh datablock.
+ /* For non-deform types: apply the modifier and return a mesh data-block.
*
* The mesh argument should always be non-NULL; the modifier should use the
- * passed in mesh datablock rather than object->data, as it contains the mesh
+ * passed in mesh data-block rather than object->data, as it contains the mesh
* with modifier applied up to this point.
*
* The modifier may modify and return the mesh argument, but must not free it
@@ -365,9 +368,6 @@ const ModifierTypeInfo *BKE_modifier_get_info(ModifierType type);
/* For modifier UI panels. */
void BKE_modifier_type_panel_id(ModifierType type, char *r_idname);
-/* For modifier UI panels. */
-void modifierType_panelId(ModifierType type, char *r_idname);
-
/* Modifier utility calls, do call through type pointer and return
* default values if pointer is optional.
*/
@@ -403,7 +403,7 @@ void BKE_modifiers_foreach_ID_link(struct Object *ob, IDWalkFunc walk, void *use
void BKE_modifiers_foreach_tex_link(struct Object *ob, TexWalkFunc walk, void *userData);
struct ModifierData *BKE_modifiers_findby_type(struct Object *ob, ModifierType type);
-struct ModifierData *BKE_modifiers_findny_name(struct Object *ob, const char *name);
+struct ModifierData *BKE_modifiers_findby_name(struct Object *ob, const char *name);
void BKE_modifiers_clear_errors(struct Object *ob);
int BKE_modifiers_get_cage_index(struct Scene *scene,
struct Object *ob,
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index e5a77bce0e6..2be8d657bf4 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -29,6 +29,7 @@ extern "C" {
#endif
struct AnimData;
+struct LibraryForeachIDData;
struct Main;
struct NlaStrip;
struct NlaTrack;
@@ -63,6 +64,8 @@ struct NlaStrip *BKE_nla_add_soundstrip(struct Main *bmain,
struct Scene *scene,
struct Speaker *spk);
+void BKE_nla_strip_foreach_id(struct NlaStrip *strip, struct LibraryForeachIDData *data);
+
/* ----------------------------- */
/* API */
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index a7ece2e3167..26ffd1bbfef 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -239,6 +239,7 @@ typedef struct SculptPoseIKChainSegment {
float initial_orig[3];
float initial_head[3];
float len;
+ float scale;
float rot[4];
float *weights;
@@ -252,6 +253,7 @@ typedef struct SculptPoseIKChainSegment {
typedef struct SculptPoseIKChain {
SculptPoseIKChainSegment *segments;
int tot_segments;
+ float grab_delta_offset[3];
} SculptPoseIKChain;
/* Cloth Brush */
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index ea81be05b03..00d010cd6d9 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -430,7 +430,7 @@ void psys_apply_child_modifiers(struct ParticleThreadContext *ctx,
const float parent_orco[3]);
void psys_sph_init(struct ParticleSimulationData *sim, struct SPHData *sphdata);
-void psys_sph_finalise(struct SPHData *sphdata);
+void psys_sph_finalize(struct SPHData *sphdata);
void psys_sph_density(struct BVHTree *tree, struct SPHData *data, float co[3], float vars[2]);
/* for anim.c */
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 2bf16e38716..8fb6f140822 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -82,8 +82,8 @@ typedef struct PBVHFrustumPlanes {
int num_planes;
} PBVHFrustumPlanes;
-void BKE_pbvh_set_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes);
-void BKE_pbvh_get_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes);
+void BKE_pbvh_set_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes);
+void BKE_pbvh_get_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes);
/* Callbacks */
@@ -98,7 +98,7 @@ typedef void (*BKE_pbvh_SearchNearestCallback)(PBVHNode *node, void *data, float
/* Building */
PBVH *BKE_pbvh_new(void);
-void BKE_pbvh_build_mesh(PBVH *bvh,
+void BKE_pbvh_build_mesh(PBVH *pbvh,
const struct Mesh *mesh,
const struct MPoly *mpoly,
const struct MLoop *mloop,
@@ -109,47 +109,47 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
struct CustomData *pdata,
const struct MLoopTri *looptri,
int looptri_num);
-void BKE_pbvh_build_grids(PBVH *bvh,
+void BKE_pbvh_build_grids(PBVH *pbvh,
struct CCGElem **grid_elems,
int totgrid,
struct CCGKey *key,
void **gridfaces,
struct DMFlagMat *flagmats,
unsigned int **grid_hidden);
-void BKE_pbvh_build_bmesh(PBVH *bvh,
+void BKE_pbvh_build_bmesh(PBVH *pbvh,
struct BMesh *bm,
bool smooth_shading,
struct BMLog *log,
const int cd_vert_node_offset,
const int cd_face_node_offset);
-void BKE_pbvh_free(PBVH *bvh);
+void BKE_pbvh_free(PBVH *pbvh);
/* Hierarchical Search in the BVH, two methods:
* - for each hit calling a callback
* - gather nodes in an array (easy to multithread) */
-void BKE_pbvh_search_callback(PBVH *bvh,
+void BKE_pbvh_search_callback(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
BKE_pbvh_HitCallback hcb,
void *hit_data);
void BKE_pbvh_search_gather(
- PBVH *bvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot);
+ PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot);
/* Raycast
* the hit callback is called for all leaf nodes intersecting the ray;
* it's up to the callback to find the primitive within the leaves that is
* hit first */
-void BKE_pbvh_raycast(PBVH *bvh,
+void BKE_pbvh_raycast(PBVH *pbvh,
BKE_pbvh_HitOccludedCallback cb,
void *data,
const float ray_start[3],
const float ray_normal[3],
bool original);
-bool BKE_pbvh_node_raycast(PBVH *bvh,
+bool BKE_pbvh_node_raycast(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
@@ -170,16 +170,16 @@ bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
/* for orthographic cameras, project the far away ray segment points to the root node so
* we can have better precision. */
void BKE_pbvh_raycast_project_ray_root(
- PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]);
+ PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]);
-void BKE_pbvh_find_nearest_to_ray(PBVH *bvh,
+void BKE_pbvh_find_nearest_to_ray(PBVH *pbvh,
BKE_pbvh_HitOccludedCallback cb,
void *data,
const float ray_start[3],
const float ray_normal[3],
bool original);
-bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
+bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
@@ -190,7 +190,7 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
/* Drawing */
-void BKE_pbvh_draw_cb(PBVH *bvh,
+void BKE_pbvh_draw_cb(PBVH *pbvh,
bool update_only_visible,
PBVHFrustumPlanes *update_frustum,
PBVHFrustumPlanes *draw_frustum,
@@ -198,7 +198,7 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
void *user_data);
void BKE_pbvh_draw_debug_cb(
- PBVH *bvh,
+ PBVH *pbvh,
void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag),
void *user_data);
@@ -209,26 +209,27 @@ typedef enum {
PBVH_BMESH,
} PBVHType;
-PBVHType BKE_pbvh_type(const PBVH *bvh);
-bool BKE_pbvh_has_faces(const PBVH *bvh);
+PBVHType BKE_pbvh_type(const PBVH *pbvh);
+bool BKE_pbvh_has_faces(const PBVH *pbvh);
/* Get the PBVH root's bounding box */
-void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]);
+void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3]);
/* multires hidden data, only valid for type == PBVH_GRIDS */
-unsigned int **BKE_pbvh_grid_hidden(const PBVH *bvh);
+unsigned int **BKE_pbvh_grid_hidden(const PBVH *pbvh);
int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
int *grid_indices,
int totgrid,
int gridsize);
-void BKE_pbvh_sync_face_sets_to_grids(PBVH *bvh);
+void BKE_pbvh_sync_face_sets_to_grids(PBVH *pbvh);
/* multires level, only valid for type == PBVH_GRIDS */
const struct CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh);
struct CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh);
+BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh);
int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh);
/* Only valid for type == PBVH_BMESH */
@@ -239,7 +240,7 @@ typedef enum {
PBVH_Subdivide = 1,
PBVH_Collapse = 2,
} PBVHTopologyUpdateMode;
-bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
+bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
PBVHTopologyUpdateMode mode,
const float center[3],
const float view_normal[3],
@@ -262,15 +263,15 @@ bool BKE_pbvh_node_fully_masked_get(PBVHNode *node);
void BKE_pbvh_node_fully_unmasked_set(PBVHNode *node, int fully_masked);
bool BKE_pbvh_node_fully_unmasked_get(PBVHNode *node);
-void BKE_pbvh_node_get_grids(PBVH *bvh,
+void BKE_pbvh_node_get_grids(PBVH *pbvh,
PBVHNode *node,
int **grid_indices,
int *totgrid,
int *maxgrid,
int *gridsize,
struct CCGElem ***grid_elems);
-void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *r_uniquevert, int *r_totvert);
-void BKE_pbvh_node_get_verts(PBVH *bvh,
+void BKE_pbvh_node_num_verts(PBVH *pbvh, PBVHNode *node, int *r_uniquevert, int *r_totvert);
+void BKE_pbvh_node_get_verts(PBVH *pbvh,
PBVHNode *node,
const int **r_vert_indices,
struct MVert **r_verts);
@@ -289,27 +290,27 @@ struct GSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
struct GSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
void BKE_pbvh_bmesh_node_save_orig(struct BMesh *bm, PBVHNode *node);
-void BKE_pbvh_bmesh_after_stroke(PBVH *bvh);
+void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh);
/* Update Bounding Box/Redraw and clear flags */
-void BKE_pbvh_update_bounds(PBVH *bvh, int flags);
-void BKE_pbvh_update_vertex_data(PBVH *bvh, int flags);
-void BKE_pbvh_update_visibility(PBVH *bvh);
-void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg);
-void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]);
-void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface);
-void BKE_pbvh_grids_update(PBVH *bvh,
+void BKE_pbvh_update_bounds(PBVH *pbvh, int flags);
+void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flags);
+void BKE_pbvh_update_visibility(PBVH *pbvh);
+void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg);
+void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3]);
+void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface);
+void BKE_pbvh_grids_update(PBVH *pbvh,
struct CCGElem **grid_elems,
void **gridfaces,
struct DMFlagMat *flagmats,
unsigned int **grid_hidden);
-void BKE_pbvh_subdiv_cgg_set(PBVH *bvh, struct SubdivCCG *subdiv_ccg);
-void BKE_pbvh_face_sets_set(PBVH *bvh, int *face_sets);
+void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, struct SubdivCCG *subdiv_ccg);
+void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets);
-void BKE_pbvh_face_sets_color_set(PBVH *bvh, int seed, int color_default);
+void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default);
-void BKE_pbvh_respect_hide_set(PBVH *bvh, bool respect_hide);
+void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide);
/* vertex deformer */
float (*BKE_pbvh_vert_coords_alloc(struct PBVH *pbvh))[3];
@@ -370,10 +371,10 @@ typedef struct PBVHVertexIter {
bool visible;
} PBVHVertexIter;
-void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mode);
+void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode);
-#define BKE_pbvh_vertex_iter_begin(bvh, node, vi, mode) \
- pbvh_vertex_iter_init(bvh, node, &vi, mode); \
+#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode) \
+ pbvh_vertex_iter_init(pbvh, node, &vi, mode); \
\
for (vi.i = 0, vi.g = 0; vi.g < vi.totgrid; vi.g++) { \
if (vi.grids) { \
@@ -446,30 +447,30 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo
void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count);
void BKE_pbvh_node_free_proxies(PBVHNode *node);
-PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node);
+PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node);
void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***nodes, int *totnode);
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
int (**r_orco_tris)[3],
int *r_orco_tris_num,
float (**r_orco_coords)[3]);
-bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node);
+bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node);
// void BKE_pbvh_node_BB_reset(PBVHNode *node);
// void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
-bool pbvh_has_mask(PBVH *bvh);
-void pbvh_show_mask_set(PBVH *bvh, bool show_mask);
+bool pbvh_has_mask(PBVH *pbvh);
+void pbvh_show_mask_set(PBVH *pbvh, bool show_mask);
-bool pbvh_has_face_sets(PBVH *bvh);
-void pbvh_show_face_sets_set(PBVH *bvh, bool show_face_sets);
+bool pbvh_has_face_sets(PBVH *pbvh);
+void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets);
/* Parallelization */
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings,
bool use_threading,
int totnode);
-struct MVert *BKE_pbvh_get_verts(const PBVH *bvh);
+struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 8794558b81f..fc7146b8cf4 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -34,6 +34,7 @@ extern "C" {
struct ARegion;
struct Header;
struct ID;
+struct LibraryForeachIDData;
struct ListBase;
struct Menu;
struct Panel;
@@ -48,7 +49,6 @@ struct WorkSpace;
struct bContext;
struct bContextDataResult;
struct bScreen;
-struct LibraryForeachIDData;
struct uiLayout;
struct uiList;
struct wmGizmoMap;
@@ -234,17 +234,17 @@ typedef struct PanelType {
/** Reorder function, called when drag and drop finishes. */
void (*reorder)(struct bContext *C, struct Panel *pa, int new_index);
/**
- * Get the panel and subpanel's expansion state from the expansion flag in the corresponding data
- * item. Called on draw updates.
- * \note Subpanels are indexed in depth first order, the visualorder you would see if all panels
- * were expanded.
+ * Get the panel and sub-panel's expansion state from the expansion flag in the corresponding
+ * data item. Called on draw updates.
+ * \note Sub-panels are indexed in depth first order,
+ * the visual order you would see if all panels were expanded.
*/
short (*get_list_data_expand_flag)(const struct bContext *C, struct Panel *pa);
/**
- * Set the expansion bitfield from the closed / open state of this panel and its subpanels.
+ * Set the expansion bit-field from the closed / open state of this panel and its sub-panels.
* Called when the expansion state of the panel changes with user input.
- * \note Subpanels are indexed in depth first order, the visual order you would see if all panels
- * were expanded.
+ * \note Sub-panels are indexed in depth first order,
+ * the visual order you would see if all panels were expanded.
*/
void (*set_list_data_expand_flag)(const struct bContext *C, struct Panel *pa, short expand_flag);
diff --git a/source/blender/blenkernel/BKE_simulation.h b/source/blender/blenkernel/BKE_simulation.h
index d1cf782e9e5..ff6aaa5e30e 100644
--- a/source/blender/blenkernel/BKE_simulation.h
+++ b/source/blender/blenkernel/BKE_simulation.h
@@ -21,13 +21,15 @@
extern "C" {
#endif
+struct Depsgraph;
struct Main;
struct Simulation;
-struct Depsgraph;
void *BKE_simulation_add(struct Main *bmain, const char *name);
-void BKE_simulation_data_update(struct Depsgraph *depsgraph, struct Scene *scene);
+void BKE_simulation_data_update(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Simulation *simulation);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h
index 8582996108a..8a6afd8a753 100644
--- a/source/blender/blenkernel/BKE_workspace.h
+++ b/source/blender/blenkernel/BKE_workspace.h
@@ -84,6 +84,7 @@ void BKE_workspace_active_set(struct WorkSpaceInstanceHook *hook,
struct WorkSpaceLayout *BKE_workspace_active_layout_get(const struct WorkSpaceInstanceHook *hook)
GETTER_ATTRS;
void BKE_workspace_active_layout_set(struct WorkSpaceInstanceHook *hook,
+ struct WorkSpace *workspace,
struct WorkSpaceLayout *layout) SETTER_ATTRS;
struct bScreen *BKE_workspace_active_screen_get(const struct WorkSpaceInstanceHook *hook)
GETTER_ATTRS;
@@ -91,21 +92,14 @@ void BKE_workspace_active_screen_set(struct WorkSpaceInstanceHook *hook,
struct WorkSpace *workspace,
struct bScreen *screen) SETTER_ATTRS;
-struct ListBase *BKE_workspace_layouts_get(struct WorkSpace *workspace) GETTER_ATTRS;
-
const char *BKE_workspace_layout_name_get(const struct WorkSpaceLayout *layout) GETTER_ATTRS;
void BKE_workspace_layout_name_set(struct WorkSpace *workspace,
struct WorkSpaceLayout *layout,
const char *new_name) ATTR_NONNULL();
struct bScreen *BKE_workspace_layout_screen_get(const struct WorkSpaceLayout *layout) GETTER_ATTRS;
-void BKE_workspace_layout_screen_set(struct WorkSpaceLayout *layout,
- struct bScreen *screen) SETTER_ATTRS;
-struct WorkSpaceLayout *BKE_workspace_hook_layout_for_workspace_get(
+struct WorkSpaceLayout *BKE_workspace_active_layout_for_workspace_get(
const struct WorkSpaceInstanceHook *hook, const struct WorkSpace *workspace) GETTER_ATTRS;
-void BKE_workspace_hook_layout_for_workspace_set(struct WorkSpaceInstanceHook *hook,
- struct WorkSpace *workspace,
- struct WorkSpaceLayout *layout) ATTR_NONNULL();
bool BKE_workspace_owner_id_check(const struct WorkSpace *workspace, const char *owner_id)
ATTR_NONNULL();
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 220bafa2187..817fe849eab 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -168,6 +168,7 @@ set(SRC
intern/mesh_runtime.c
intern/mesh_tangent.c
intern/mesh_validate.c
+ intern/mesh_wrapper.c
intern/modifier.c
intern/movieclip.c
intern/multires.c
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index b3893d8600f..8f820a873fe 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -90,6 +90,8 @@
static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER;
static void mesh_init_origspace(Mesh *mesh);
+static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
+ const CustomData_MeshMasks *final_datamask);
/* -------------------------------------------------------------------- */
@@ -861,6 +863,16 @@ static void mesh_calc_finalize(const Mesh *mesh_input, Mesh *mesh_eval)
mesh_eval->edit_mesh = mesh_input->edit_mesh;
}
+void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval,
+ const CustomData_MeshMasks *cd_mask_finalize)
+{
+ if (me_eval->runtime.wrapper_type_finalize & (1 << ME_WRAPPER_TYPE_BMESH)) {
+ editbmesh_calc_modifier_final_normals(me_eval, cd_mask_finalize);
+ me_eval->runtime.wrapper_type_finalize &= ~(1 << ME_WRAPPER_TYPE_BMESH);
+ }
+ BLI_assert(me_eval->runtime.wrapper_type_finalize == 0);
+}
+
static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob,
@@ -1391,11 +1403,16 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, bool has_prev
return true;
}
-static void editbmesh_calc_modifier_final_normals(const Mesh *mesh_input,
- const CustomData_MeshMasks *final_datamask,
- Mesh *mesh_final)
+static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
+ const CustomData_MeshMasks *final_datamask)
{
- const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
+ if (mesh_final->runtime.wrapper_type != ME_WRAPPER_TYPE_MDATA) {
+ /* Generated at draw time. */
+ mesh_final->runtime.wrapper_type_finalize = (1 << mesh_final->runtime.wrapper_type);
+ return;
+ }
+
+ const bool do_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 ||
(final_datamask->lmask & CD_MASK_NORMAL) != 0);
/* Some modifiers may need this info from their target (other) object,
* simpler to generate it here as well. */
@@ -1501,7 +1518,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
/* Evaluate modifiers up to certain index to get the mesh cage. */
int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1);
if (r_cage && cageIndex == -1) {
- mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(
+ mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords(
em_input, &final_datamask, NULL, mesh_input);
}
@@ -1574,12 +1591,9 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
}
}
else {
- mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, NULL, mesh_input);
- ASSERT_IS_VALID_MESH(mesh_final);
-
- if (deformed_verts) {
- BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
- }
+ mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords(
+ em_input, NULL, deformed_verts, mesh_input);
+ deformed_verts = NULL;
}
/* create an orco derivedmesh in parallel */
@@ -1657,7 +1671,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
BKE_mesh_runtime_ensure_edit_data(me_orig);
me_orig->runtime.edit_data->vertexCos = MEM_dupallocN(deformed_verts);
}
- mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(
+ mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords(
em_input,
&final_datamask,
deformed_verts ? MEM_dupallocN(deformed_verts) : NULL,
@@ -1689,7 +1703,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
}
else {
/* this is just a copy of the editmesh, no need to calc normals */
- mesh_final = BKE_mesh_from_editmesh_with_coords_thin_wrap(
+ mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords(
em_input, &final_datamask, deformed_verts, mesh_input);
deformed_verts = NULL;
}
@@ -1700,6 +1714,9 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
/* Add orco coordinates to final and deformed mesh if requested. */
if (final_datamask.vmask & CD_MASK_ORCO) {
+ /* FIXME(Campbell): avoid the need to convert to mesh data just to add an orco layer. */
+ BKE_mesh_wrapper_ensure_mdata(mesh_final);
+
add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO);
}
@@ -1707,10 +1724,15 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
BKE_id_free(NULL, mesh_orco);
}
+ /* Ensure normals calculation below is correct. */
+ BLI_assert((mesh_input->flag & ME_AUTOSMOOTH) == (mesh_final->flag & ME_AUTOSMOOTH));
+ BLI_assert(mesh_input->smoothresh == mesh_final->smoothresh);
+ BLI_assert(mesh_input->smoothresh == mesh_cage->smoothresh);
+
/* Compute normals. */
- editbmesh_calc_modifier_final_normals(mesh_input, &final_datamask, mesh_final);
+ editbmesh_calc_modifier_final_normals(mesh_final, &final_datamask);
if (mesh_cage && (mesh_cage != mesh_final)) {
- editbmesh_calc_modifier_final_normals(mesh_input, &final_datamask, mesh_cage);
+ editbmesh_calc_modifier_final_normals(mesh_cage, &final_datamask);
}
/* Return final mesh. */
@@ -1798,9 +1820,7 @@ static void mesh_build_data(struct Depsgraph *depsgraph,
}
}
- if (mesh_eval != NULL) {
- mesh_runtime_check_normals_valid(mesh_eval);
- }
+ mesh_runtime_check_normals_valid(mesh_eval);
mesh_build_extra_data(depsgraph, ob, mesh_eval);
}
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index bd39ffc65e7..c776f0d077d 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -116,7 +116,7 @@ static void action_copy_data(Main *UNUSED(bmain),
/* XXX TODO pass subdata flag?
* But surprisingly does not seem to be doing any ID refcounting... */
- fcurve_dst = copy_fcurve(fcurve_src);
+ fcurve_dst = BKE_fcurve_copy(fcurve_src);
BLI_addtail(&action_dst->curves, fcurve_dst);
@@ -146,7 +146,7 @@ static void action_free_data(struct ID *id)
/* No animdata here. */
/* Free F-Curves. */
- free_fcurves(&action->curves);
+ BKE_fcurves_free(&action->curves);
/* Free groups. */
BLI_freelistN(&action->groups);
@@ -159,6 +159,10 @@ static void action_foreach_id(ID *id, LibraryForeachIDData *data)
{
bAction *act = (bAction *)id;
+ LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
+ BKE_fcurve_foreach_id(fcu, data);
+ }
+
LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) {
BKE_LIB_FOREACHID_PROCESS(data, marker->camera, IDWALK_CB_NOP);
}
@@ -1306,7 +1310,7 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_
* single-keyframe curves will increase the overall length by
* a phantom frame (T50354)
*/
- calc_fcurve_range(fcu, &nmin, &nmax, false, false);
+ BKE_fcurve_calc_range(fcu, &nmin, &nmax, false, false);
/* compare to the running tally */
min = min_ff(min, nmin);
diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c
index 02b7763a9b4..9ab4e5c028d 100644
--- a/source/blender/blenkernel/intern/anim_data.c
+++ b/source/blender/blenkernel/intern/anim_data.c
@@ -32,6 +32,7 @@
#include "BKE_fcurve_driver.h"
#include "BKE_global.h"
#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_node.h"
@@ -255,7 +256,7 @@ void BKE_animdata_free(ID *id, const bool do_id_user)
BKE_nla_tracks_free(&adt->nla_tracks, do_id_user);
/* free drivers - stored as a list of F-Curves */
- free_fcurves(&adt->drivers);
+ BKE_fcurves_free(&adt->drivers);
/* free driver array cache */
MEM_SAFE_FREE(adt->driver_array);
@@ -289,6 +290,24 @@ bool BKE_animdata_id_is_animated(const struct ID *id)
!BLI_listbase_is_empty(&adt->overrides);
}
+/** Callback used by lib_query to walk over all ID usages (mimics `foreach_id` callback of
+ * `IDTypeInfo` structure). */
+void BKE_animdata_foreach_id(AnimData *adt, LibraryForeachIDData *data)
+{
+ LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
+ BKE_fcurve_foreach_id(fcu, data);
+ }
+
+ BKE_LIB_FOREACHID_PROCESS(data, adt->action, IDWALK_CB_USER);
+ BKE_LIB_FOREACHID_PROCESS(data, adt->tmpact, IDWALK_CB_USER);
+
+ LISTBASE_FOREACH (NlaTrack *, nla_track, &adt->nla_tracks) {
+ LISTBASE_FOREACH (NlaStrip *, nla_strip, &nla_track->strips) {
+ BKE_nla_strip_foreach_id(nla_strip, data);
+ }
+ }
+}
+
/* Copying -------------------------------------------- */
/**
@@ -326,7 +345,7 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag)
BKE_nla_tracks_copy(bmain, &dadt->nla_tracks, &adt->nla_tracks, flag);
/* duplicate drivers (F-Curves) */
- copy_fcurves(&dadt->drivers, &adt->drivers);
+ BKE_fcurves_copy(&dadt->drivers, &adt->drivers);
dadt->driver_array = NULL;
/* don't copy overrides */
@@ -428,7 +447,7 @@ void BKE_animdata_merge_copy(
if (src->drivers.first) {
ListBase drivers = {NULL, NULL};
- copy_fcurves(&drivers, &src->drivers);
+ BKE_fcurves_copy(&drivers, &src->drivers);
/* Fix up all driver targets using the old target id
* - This assumes that the src ID is being merged into the dst ID
@@ -1082,7 +1101,7 @@ static bool fcurves_path_remove_fix(const char *prefix, ListBase *curves)
if (fcu->rna_path) {
if (STRPREFIX(fcu->rna_path, prefix)) {
BLI_remlink(curves, fcu);
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
any_removed = true;
}
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index b3a4de02451..e8aa13a8beb 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -66,7 +66,7 @@
Global G;
UserDef U;
-char versionstr[48] = "";
+static char blender_version_string[48] = "";
/* ********** free ********** */
@@ -102,26 +102,43 @@ void BKE_blender_free(void)
free_nodesystem();
}
-void BKE_blender_version_string(char *version_str,
- size_t maxncpy,
- short version,
- short subversion,
- bool v_prefix,
- bool include_subversion)
+static void blender_version_init(void)
{
- const char *prefix = v_prefix ? "v" : "";
-
- if (include_subversion && subversion > 0) {
- BLI_snprintf(
- version_str, maxncpy, "%s%d.%02d.%d", prefix, version / 100, version % 100, subversion);
+ const char *version_cycle = "";
+ if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) {
+ version_cycle = " Alpha";
+ }
+ else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "beta")) {
+ version_cycle = " Beta";
+ }
+ else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "rc")) {
+ version_cycle = " Release Candidate";
+ }
+ else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) {
+ version_cycle = "";
}
else {
- BLI_snprintf(version_str, maxncpy, "%s%d.%02d", prefix, version / 100, version % 100);
+ BLI_assert(!"Invalid Blender version cycle");
}
+
+ BLI_snprintf(blender_version_string,
+ ARRAY_SIZE(blender_version_string),
+ "%d.%02d.%d%s",
+ BLENDER_VERSION / 100,
+ BLENDER_VERSION % 100,
+ BLENDER_VERSION_PATCH,
+ version_cycle);
+}
+
+const char *BKE_blender_version_string(void)
+{
+ return blender_version_string;
}
void BKE_blender_globals_init(void)
{
+ blender_version_init();
+
memset(&G, 0, sizeof(Global));
U.savetime = 1;
@@ -130,9 +147,6 @@ void BKE_blender_globals_init(void)
strcpy(G.ima, "//");
- BKE_blender_version_string(
- versionstr, sizeof(versionstr), BLENDER_VERSION, BLENDER_SUBVERSION, true, true);
-
#ifndef WITH_PYTHON_SECURITY /* default */
G.f |= G_FLAG_SCRIPT_AUTOEXEC;
#else
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 13dcc7b06f6..ef474022f19 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -415,8 +415,9 @@ static void setup_app_blend_file_data(bContext *C,
static int handle_subversion_warning(Main *main, ReportList *reports)
{
- if (main->minversionfile > BLENDER_VERSION ||
- (main->minversionfile == BLENDER_VERSION && main->minsubversionfile > BLENDER_SUBVERSION)) {
+ if (main->minversionfile > BLENDER_FILE_VERSION ||
+ (main->minversionfile == BLENDER_FILE_VERSION &&
+ main->minsubversionfile > BLENDER_FILE_SUBVERSION)) {
BKE_reportf(reports,
RPT_ERROR,
"File written by newer Blender binary (%d.%d), expect loss of data!",
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 133917e441c..3241518cae5 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -520,6 +520,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
Material *ma = BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2);
if (ma == NULL) {
ma = BKE_gpencil_material_add(bmain, "Dots Stroke");
+ ma->gp_style->mode = GP_MATERIAL_MODE_DOT;
}
brush->gpencil_settings->material = ma;
/* Pin the matterial to the brush. */
@@ -744,6 +745,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
Material *ma = BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2);
if (ma == NULL) {
ma = BKE_gpencil_material_add(bmain, "Dots Stroke");
+ ma->gp_style->mode = GP_MATERIAL_MODE_DOT;
}
brush->gpencil_settings->material = ma;
/* Pin the matterial to the brush. */
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index cd90ebc2eed..93794eb9709 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -41,8 +41,126 @@
#include "MEM_guardedalloc.h"
-static ThreadRWMutex cache_rwlock = BLI_RWLOCK_INITIALIZER;
+/* -------------------------------------------------------------------- */
+/** \name BVHCache
+ * \{ */
+
+typedef struct BVHCacheItem {
+ bool is_filled;
+ BVHTree *tree;
+} BVHCacheItem;
+
+typedef struct BVHCache {
+ BVHCacheItem items[BVHTREE_MAX_ITEM];
+ ThreadMutex mutex;
+} BVHCache;
+
+/**
+ * Queries a bvhcache for the cache bvhtree of the request type
+ *
+ * When the `r_locked` is filled and the tree could not be found the caches mutex will be
+ * locked. This mutex can be unlocked by calling `bvhcache_unlock`.
+ *
+ * When `r_locked` is used the `mesh_eval_mutex` must contain the `Mesh_Runtime.eval_mutex`.
+ */
+static bool bvhcache_find(BVHCache **bvh_cache_p,
+ BVHCacheType type,
+ BVHTree **r_tree,
+ bool *r_locked,
+ ThreadMutex *mesh_eval_mutex)
+{
+ bool do_lock = r_locked;
+ if (r_locked) {
+ *r_locked = false;
+ }
+ if (*bvh_cache_p == NULL) {
+ if (!do_lock) {
+ /* Cache does not exist and no lock is requested. */
+ return false;
+ }
+ /* Lazy initialization of the bvh_cache using the `mesh_eval_mutex`. */
+ BLI_mutex_lock(mesh_eval_mutex);
+ if (*bvh_cache_p == NULL) {
+ *bvh_cache_p = bvhcache_init();
+ }
+ BLI_mutex_unlock(mesh_eval_mutex);
+ }
+ BVHCache *bvh_cache = *bvh_cache_p;
+ if (bvh_cache->items[type].is_filled) {
+ *r_tree = bvh_cache->items[type].tree;
+ return true;
+ }
+ if (do_lock) {
+ BLI_mutex_lock(&bvh_cache->mutex);
+ bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, NULL, NULL);
+ if (in_cache) {
+ BLI_mutex_unlock(&bvh_cache->mutex);
+ return in_cache;
+ }
+ *r_locked = true;
+ }
+ return false;
+}
+
+static void bvhcache_unlock(BVHCache *bvh_cache, bool lock_started)
+{
+ if (lock_started) {
+ BLI_mutex_unlock(&bvh_cache->mutex);
+ }
+}
+
+bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree)
+{
+ if (bvh_cache == NULL) {
+ return false;
+ }
+
+ for (BVHCacheType i = 0; i < BVHTREE_MAX_ITEM; i++) {
+ if (bvh_cache->items[i].tree == tree) {
+ return true;
+ }
+ }
+ return false;
+}
+
+BVHCache *bvhcache_init(void)
+{
+ BVHCache *cache = MEM_callocN(sizeof(BVHCache), __func__);
+ BLI_mutex_init(&cache->mutex);
+ return cache;
+}
+/**
+ * Inserts a BVHTree of the given type under the cache
+ * After that the caller no longer needs to worry when to free the BVHTree
+ * as that will be done when the cache is freed.
+ *
+ * A call to this assumes that there was no previous cached tree of the given type
+ * \warning The #BVHTree can be NULL.
+ */
+static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType type)
+{
+ BVHCacheItem *item = &bvh_cache->items[type];
+ BLI_assert(!item->is_filled);
+ item->tree = tree;
+ item->is_filled = true;
+}
+
+/**
+ * frees a bvhcache
+ */
+void bvhcache_free(BVHCache *bvh_cache)
+{
+ for (BVHCacheType index = 0; index < BVHTREE_MAX_ITEM; index++) {
+ BVHCacheItem *item = &bvh_cache->items[index];
+ BLI_bvhtree_free(item->tree);
+ item->tree = NULL;
+ }
+ BLI_mutex_end(&bvh_cache->mutex);
+ MEM_freeN(bvh_cache);
+}
+
+/** \} */
/* -------------------------------------------------------------------- */
/** \name Local Callbacks
* \{ */
@@ -518,29 +636,26 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ if (bvh_cache_p) {
+ bool lock_started = false;
+ data->cached = bvhcache_find(
+ bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, mesh_eval_mutex);
if (data->cached == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree);
- if (data->cached == false) {
- tree = bvhtree_from_editmesh_verts_create_tree(
- epsilon, tree_type, axis, em, verts_mask, verts_num_active);
-
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- data->cached = true;
- }
- BLI_rw_mutex_unlock(&cache_rwlock);
+ tree = bvhtree_from_editmesh_verts_create_tree(
+ epsilon, tree_type, axis, em, verts_mask, verts_num_active);
+
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(*bvh_cache_p, tree, bvh_cache_type);
+ data->cached = true;
}
+ bvhcache_unlock(*bvh_cache_p, lock_started);
}
else {
tree = bvhtree_from_editmesh_verts_create_tree(
@@ -553,7 +668,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
data->em = em;
data->nearest_callback = NULL;
data->raycast_callback = editmesh_verts_spherecast;
- data->cached = bvh_cache != NULL;
+ data->cached = bvh_cache_p != NULL;
}
return tree;
@@ -562,7 +677,8 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
BVHTree *bvhtree_from_editmesh_verts(
BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
{
- return bvhtree_from_editmesh_verts_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL);
+ return bvhtree_from_editmesh_verts_ex(
+ data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
}
/**
@@ -582,32 +698,26 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
bool in_cache = false;
+ bool lock_started = false;
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
- if (in_cache == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- if (in_cache) {
- BLI_rw_mutex_unlock(&cache_rwlock);
- }
- }
+ if (bvh_cache_p) {
+ in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
if (in_cache == false) {
tree = bvhtree_from_mesh_verts_create_tree(
epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active);
- if (bvh_cache) {
+ if (bvh_cache_p) {
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
+ BVHCache *bvh_cache = *bvh_cache_p;
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ bvhcache_unlock(bvh_cache, lock_started);
in_cache = true;
}
}
@@ -735,29 +845,26 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
-
+ if (bvh_cache_p) {
+ bool lock_started = false;
+ data->cached = bvhcache_find(
+ bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, mesh_eval_mutex);
+ BVHCache *bvh_cache = *bvh_cache_p;
if (data->cached == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree);
- if (data->cached == false) {
- tree = bvhtree_from_editmesh_edges_create_tree(
- epsilon, tree_type, axis, em, edges_mask, edges_num_active);
-
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- data->cached = true;
- }
- BLI_rw_mutex_unlock(&cache_rwlock);
+ tree = bvhtree_from_editmesh_edges_create_tree(
+ epsilon, tree_type, axis, em, edges_mask, edges_num_active);
+
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(bvh_cache, tree, bvh_cache_type);
+ data->cached = true;
}
+ bvhcache_unlock(bvh_cache, lock_started);
}
else {
tree = bvhtree_from_editmesh_edges_create_tree(
@@ -770,7 +877,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
data->em = em;
data->nearest_callback = NULL; /* TODO */
data->raycast_callback = NULL; /* TODO */
- data->cached = bvh_cache != NULL;
+ data->cached = bvh_cache_p != NULL;
}
return tree;
@@ -779,7 +886,8 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
BVHTree *bvhtree_from_editmesh_edges(
BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
{
- return bvhtree_from_editmesh_edges_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL);
+ return bvhtree_from_editmesh_edges_ex(
+ data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
}
/**
@@ -802,32 +910,26 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
bool in_cache = false;
+ bool lock_started = false;
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
- if (in_cache == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- if (in_cache) {
- BLI_rw_mutex_unlock(&cache_rwlock);
- }
- }
+ if (bvh_cache_p) {
+ in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
if (in_cache == false) {
tree = bvhtree_from_mesh_edges_create_tree(
vert, edge, edges_num, edges_mask, edges_num_active, epsilon, tree_type, axis);
- if (bvh_cache) {
+ if (bvh_cache_p) {
+ BVHCache *bvh_cache = *bvh_cache_p;
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ bvhcache_unlock(bvh_cache, lock_started);
in_cache = true;
}
}
@@ -937,32 +1039,26 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
bool in_cache = false;
+ bool lock_started = false;
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
- if (in_cache == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- if (in_cache) {
- BLI_rw_mutex_unlock(&cache_rwlock);
- }
- }
+ if (bvh_cache_p) {
+ in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
if (in_cache == false) {
tree = bvhtree_from_mesh_faces_create_tree(
epsilon, tree_type, axis, vert, face, numFaces, faces_mask, faces_num_active);
- if (bvh_cache) {
+ if (bvh_cache_p) {
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
+ BVHCache *bvh_cache = *bvh_cache_p;
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ bvhcache_unlock(bvh_cache, lock_started);
in_cache = true;
}
}
@@ -1113,29 +1209,28 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
/* BMESH specific check that we have tessfaces,
* we _could_ tessellate here but rather not - campbell */
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- bool in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ if (bvh_cache_p) {
+ bool lock_started = false;
+ bool in_cache = bvhcache_find(
+ bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
+ BVHCache *bvh_cache = *bvh_cache_p;
+
if (in_cache == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- if (in_cache == false) {
- tree = bvhtree_from_editmesh_looptri_create_tree(
- epsilon, tree_type, axis, em, looptri_mask, looptri_num_active);
-
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- }
- BLI_rw_mutex_unlock(&cache_rwlock);
+ tree = bvhtree_from_editmesh_looptri_create_tree(
+ epsilon, tree_type, axis, em, looptri_mask, looptri_num_active);
+
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(bvh_cache, tree, bvh_cache_type);
}
+ bvhcache_unlock(bvh_cache, lock_started);
}
else {
tree = bvhtree_from_editmesh_looptri_create_tree(
@@ -1147,7 +1242,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
data->nearest_callback = editmesh_looptri_nearest_point;
data->raycast_callback = editmesh_looptri_spherecast;
data->em = em;
- data->cached = bvh_cache != NULL;
+ data->cached = bvh_cache_p != NULL;
}
return tree;
}
@@ -1155,7 +1250,8 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
BVHTree *bvhtree_from_editmesh_looptri(
BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
{
- return bvhtree_from_editmesh_looptri_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL);
+ return bvhtree_from_editmesh_looptri_ex(
+ data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
}
/**
@@ -1177,21 +1273,14 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
bool in_cache = false;
+ bool lock_started = false;
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
- if (in_cache == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- if (in_cache) {
- BLI_rw_mutex_unlock(&cache_rwlock);
- }
- }
+ if (bvh_cache_p) {
+ in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
if (in_cache == false) {
@@ -1206,9 +1295,10 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
looptri_mask,
looptri_num_active);
- if (bvh_cache) {
+ if (bvh_cache_p) {
+ BVHCache *bvh_cache = *bvh_cache_p;
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ bvhcache_unlock(bvh_cache, lock_started);
in_cache = true;
}
}
@@ -1315,11 +1405,10 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
const int tree_type)
{
BVHTree *tree = NULL;
- BVHCache **bvh_cache = &mesh->runtime.bvh_cache;
+ BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime.bvh_cache;
+ ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- bool is_cached = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ bool is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL);
if (is_cached && tree == NULL) {
memset(data, 0, sizeof(*data));
@@ -1351,7 +1440,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
tree_type,
6,
bvh_cache_type,
- bvh_cache);
+ bvh_cache_p,
+ mesh_eval_mutex);
if (loose_verts_mask != NULL) {
MEM_freeN(loose_verts_mask);
@@ -1386,7 +1476,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
tree_type,
6,
bvh_cache_type,
- bvh_cache);
+ bvh_cache_p,
+ mesh_eval_mutex);
if (loose_edges_mask != NULL) {
MEM_freeN(loose_edges_mask);
@@ -1416,7 +1507,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
tree_type,
6,
bvh_cache_type,
- bvh_cache);
+ bvh_cache_p,
+ mesh_eval_mutex);
}
else {
/* Setup BVHTreeFromMesh */
@@ -1452,7 +1544,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
tree_type,
6,
bvh_cache_type,
- bvh_cache);
+ bvh_cache_p,
+ mesh_eval_mutex);
}
else {
/* Setup BVHTreeFromMesh */
@@ -1464,6 +1557,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
case BVHTREE_FROM_EM_VERTS:
case BVHTREE_FROM_EM_EDGES:
case BVHTREE_FROM_EM_LOOPTRI:
+ case BVHTREE_MAX_ITEM:
BLI_assert(false);
break;
}
@@ -1493,17 +1587,16 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const int tree_type,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
BVHTree *tree = NULL;
bool is_cached = false;
memset(data, 0, sizeof(*data));
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- is_cached = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ if (bvh_cache_p) {
+ is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL);
if (is_cached && tree == NULL) {
return tree;
@@ -1517,7 +1610,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
case BVHTREE_FROM_EM_VERTS:
if (is_cached == false) {
tree = bvhtree_from_editmesh_verts_ex(
- data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache);
+ data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
}
else {
data->nearest_callback = NULL;
@@ -1528,7 +1621,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
case BVHTREE_FROM_EM_EDGES:
if (is_cached == false) {
tree = bvhtree_from_editmesh_edges_ex(
- data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache);
+ data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
}
else {
/* Setup BVHTreeFromMesh */
@@ -1540,7 +1633,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
case BVHTREE_FROM_EM_LOOPTRI:
if (is_cached == false) {
tree = bvhtree_from_editmesh_looptri_ex(
- data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache);
+ data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
}
else {
/* Setup BVHTreeFromMesh */
@@ -1555,6 +1648,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
case BVHTREE_FROM_LOOPTRI_NO_HIDDEN:
case BVHTREE_FROM_LOOSEVERTS:
case BVHTREE_FROM_LOOSEEDGES:
+ case BVHTREE_MAX_ITEM:
BLI_assert(false);
break;
}
@@ -1615,82 +1709,3 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
memset(data, 0, sizeof(*data));
}
-
-/* -------------------------------------------------------------------- */
-/** \name BVHCache
- * \{ */
-
-typedef struct BVHCacheItem {
- BVHCacheType type;
- BVHTree *tree;
-
-} BVHCacheItem;
-
-/**
- * Queries a bvhcache for the cache bvhtree of the request type
- */
-bool bvhcache_find(const BVHCache *cache, BVHCacheType type, BVHTree **r_tree)
-{
- while (cache) {
- const BVHCacheItem *item = cache->link;
- if (item->type == type) {
- *r_tree = item->tree;
- return true;
- }
- cache = cache->next;
- }
- return false;
-}
-
-bool bvhcache_has_tree(const BVHCache *cache, const BVHTree *tree)
-{
- while (cache) {
- const BVHCacheItem *item = cache->link;
- if (item->tree == tree) {
- return true;
- }
- cache = cache->next;
- }
- return false;
-}
-
-/**
- * Inserts a BVHTree of the given type under the cache
- * After that the caller no longer needs to worry when to free the BVHTree
- * as that will be done when the cache is freed.
- *
- * A call to this assumes that there was no previous cached tree of the given type
- * \warning The #BVHTree can be NULL.
- */
-void bvhcache_insert(BVHCache **cache_p, BVHTree *tree, BVHCacheType type)
-{
- BVHCacheItem *item = NULL;
-
- BLI_assert(bvhcache_find(*cache_p, type, &(BVHTree *){0}) == false);
-
- item = MEM_mallocN(sizeof(BVHCacheItem), "BVHCacheItem");
-
- item->type = type;
- item->tree = tree;
-
- BLI_linklist_prepend(cache_p, item);
-}
-
-/**
- * frees a bvhcache
- */
-static void bvhcacheitem_free(void *_item)
-{
- BVHCacheItem *item = (BVHCacheItem *)_item;
-
- BLI_bvhtree_free(item->tree);
- MEM_freeN(item);
-}
-
-void bvhcache_free(BVHCache **cache_p)
-{
- BLI_linklist_free(*cache_p, (LinkNodeFreeFP)bvhcacheitem_free);
- *cache_p = NULL;
-}
-
-/** \} */
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index c1d77fd5f9e..e8e3e61ced4 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -210,6 +210,34 @@ Collection *BKE_collection_add(Main *bmain, Collection *collection_parent, const
return collection;
}
+/**
+ * Add \a collection_dst to all scene collections that reference object \a ob_src is in.
+ * Used to replace an instance object with a collection (library override operator).
+ *
+ * Logic is very similar to #BKE_collection_object_add_from().
+ */
+void BKE_collection_add_from_object(Main *bmain,
+ Scene *scene,
+ const Object *ob_src,
+ Collection *collection_dst)
+{
+ bool is_instantiated = false;
+
+ FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
+ if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, ob_src)) {
+ collection_child_add(collection, collection_dst, 0, true);
+ is_instantiated = true;
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END;
+
+ if (!is_instantiated) {
+ collection_child_add(scene->master_collection, collection_dst, 0, true);
+ }
+
+ BKE_main_collection_sync(bmain);
+}
+
/*********************** Free and Delete Collection ****************************/
/** Free (or release) any data used by this collection (does not free the collection itself). */
@@ -758,8 +786,10 @@ bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
}
/**
- * Add object to all scene collections that reference object is in
- * (used to copy objects).
+ * Add \a ob_dst to all scene collections that reference object \a ob_src is in.
+ * Used for copying objects.
+ *
+ * Logic is very similar to #BKE_collection_add_from_object()
*/
void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
{
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index a96747f82c4..44ac59432e7 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -951,6 +951,10 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
/* If requested, compute the inverse matrix from the computed parent matrix. */
if (data->flag & CHILDOF_SET_INVERSE) {
invert_m4_m4(data->invmat, parmat);
+ if (cob->pchan != NULL) {
+ mul_m4_series(data->invmat, data->invmat, cob->ob->obmat);
+ }
+
copy_m4_m4(inverse_matrix, data->invmat);
data->flag &= ~CHILDOF_SET_INVERSE;
@@ -4691,7 +4695,7 @@ static void followtrack_evaluate_using_3d_position_object(FollowTrackContext *co
MovieTrackingTrack *track = context->track;
MovieTrackingObject *tracking_object = context->tracking_object;
- /* Matrix of the object which is being solved prior to this contraint. */
+ /* Matrix of the object which is being solved prior to this constraint. */
float obmat[4][4];
copy_m4_m4(obmat, cob->matrix);
@@ -4716,7 +4720,7 @@ static void followtrack_evaluate_using_3d_position_camera(FollowTrackContext *co
Object *camera_object = context->camera_object;
MovieTrackingTrack *track = context->track;
- /* Matrix of the object which is being solved prior to this contraint. */
+ /* Matrix of the object which is being solved prior to this constraint. */
float obmat[4][4];
copy_m4_m4(obmat, cob->matrix);
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index f4acbdca772..6c8438e478e 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -293,7 +293,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra
cd_mask_extra = datamasks->mask;
BLI_linklist_free((LinkNode *)datamasks, NULL);
- me = BKE_mesh_from_editmesh_with_coords_thin_wrap(em, &cd_mask_extra, NULL, me_input);
+ me = BKE_mesh_wrapper_from_editmesh_with_coords(em, &cd_mask_extra, NULL, me_input);
deformedVerts = editbmesh_vert_coords_alloc(em, &numVerts);
defmats = MEM_mallocN(sizeof(*defmats) * numVerts, "defmats");
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 0798bc95797..e67cf8573f3 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -4485,7 +4485,7 @@ void BKE_nurbList_handles_recalculate(ListBase *editnurb, const bool calc_length
}
}
-void BKE_nurbList_flag_set(ListBase *editnurb, short flag)
+void BKE_nurbList_flag_set(ListBase *editnurb, short flag, bool set)
{
Nurb *nu;
BezTriple *bezt;
@@ -4497,7 +4497,16 @@ void BKE_nurbList_flag_set(ListBase *editnurb, short flag)
a = nu->pntsu;
bezt = nu->bezt;
while (a--) {
- bezt->f1 = bezt->f2 = bezt->f3 = flag;
+ if (set) {
+ bezt->f1 |= flag;
+ bezt->f2 |= flag;
+ bezt->f3 |= flag;
+ }
+ else {
+ bezt->f1 &= ~flag;
+ bezt->f2 &= ~flag;
+ bezt->f3 &= ~flag;
+ }
bezt++;
}
}
@@ -4505,13 +4514,47 @@ void BKE_nurbList_flag_set(ListBase *editnurb, short flag)
a = nu->pntsu * nu->pntsv;
bp = nu->bp;
while (a--) {
- bp->f1 = flag;
+ SET_FLAG_FROM_TEST(bp->f1, set, flag);
bp++;
}
}
}
}
+/**
+ * Set \a flag for every point that already has \a from_flag set.
+ */
+bool BKE_nurbList_flag_set_from_flag(ListBase *editnurb, short from_flag, short flag)
+{
+ bool changed = false;
+
+ for (Nurb *nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ for (int i = 0; i < nu->pntsu; i++) {
+ BezTriple *bezt = &nu->bezt[i];
+ int old_f1 = bezt->f1, old_f2 = bezt->f2, old_f3 = bezt->f3;
+
+ SET_FLAG_FROM_TEST(bezt->f1, bezt->f1 & from_flag, flag);
+ SET_FLAG_FROM_TEST(bezt->f2, bezt->f2 & from_flag, flag);
+ SET_FLAG_FROM_TEST(bezt->f3, bezt->f3 & from_flag, flag);
+
+ changed |= (old_f1 != bezt->f1) || (old_f2 != bezt->f2) || (old_f3 != bezt->f3);
+ }
+ }
+ else {
+ for (int i = 0; i < nu->pntsu * nu->pntsv; i++) {
+ BPoint *bp = &nu->bp[i];
+ int old_f1 = bp->f1;
+
+ SET_FLAG_FROM_TEST(bp->f1, bp->f1 & from_flag, flag);
+ changed |= (old_f1 != bp->f1);
+ }
+ }
+ }
+
+ return changed;
+}
+
void BKE_nurb_direction_switch(Nurb *nu)
{
BezTriple *bezt1, *bezt2;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index a022f3f5d14..b0007c2a598 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -1339,6 +1339,132 @@ static void layerDefault_fmap(void *data, int count)
}
}
+static void layerCopyValue_propcol(const void *source,
+ void *dest,
+ const int mixmode,
+ const float mixfactor)
+{
+ const MPropCol *m1 = source;
+ MPropCol *m2 = dest;
+ float tmp_col[4];
+
+ if (ELEM(mixmode,
+ CDT_MIX_NOMIX,
+ CDT_MIX_REPLACE_ABOVE_THRESHOLD,
+ CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
+ /* Modes that do a full copy or nothing. */
+ if (ELEM(mixmode, CDT_MIX_REPLACE_ABOVE_THRESHOLD, CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
+ /* TODO: Check for a real valid way to get 'factor' value of our dest color? */
+ const float f = (m2->col[0] + m2->col[1] + m2->col[2]) / 3.0f;
+ if (mixmode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && f < mixfactor) {
+ return; /* Do Nothing! */
+ }
+ else if (mixmode == CDT_MIX_REPLACE_BELOW_THRESHOLD && f > mixfactor) {
+ return; /* Do Nothing! */
+ }
+ }
+ copy_v3_v3(m2->col, m1->col);
+ }
+ else { /* Modes that support 'real' mix factor. */
+ if (mixmode == CDT_MIX_MIX) {
+ blend_color_mix_float(tmp_col, m2->col, m1->col);
+ }
+ else if (mixmode == CDT_MIX_ADD) {
+ blend_color_add_float(tmp_col, m2->col, m1->col);
+ }
+ else if (mixmode == CDT_MIX_SUB) {
+ blend_color_sub_float(tmp_col, m2->col, m1->col);
+ }
+ else if (mixmode == CDT_MIX_MUL) {
+ blend_color_mul_float(tmp_col, m2->col, m1->col);
+ }
+ else {
+ memcpy(tmp_col, m1->col, sizeof(tmp_col));
+ }
+ blend_color_interpolate_float(m2->col, m2->col, tmp_col, mixfactor);
+
+ copy_v3_v3(m2->col, m1->col);
+ }
+ m2->col[3] = m1->col[3];
+}
+
+static bool layerEqual_propcol(const void *data1, const void *data2)
+{
+ const MPropCol *m1 = data1, *m2 = data2;
+ float tot = 0;
+
+ for (int i = 0; i < 4; i++) {
+ float c = (m1->col[i] - m2->col[i]);
+ tot += c * c;
+ }
+
+ return tot < 0.001f;
+}
+
+static void layerMultiply_propcol(void *data, float fac)
+{
+ MPropCol *m = data;
+ mul_v4_fl(m->col, fac);
+}
+
+static void layerAdd_propcol(void *data1, const void *data2)
+{
+ MPropCol *m = data1;
+ const MPropCol *m2 = data2;
+ add_v4_v4(m->col, m2->col);
+}
+
+static void layerDoMinMax_propcol(const void *data, void *vmin, void *vmax)
+{
+ const MPropCol *m = data;
+ MPropCol *min = vmin, *max = vmax;
+ minmax_v4v4_v4(min->col, max->col, m->col);
+}
+
+static void layerInitMinMax_propcol(void *vmin, void *vmax)
+{
+ MPropCol *min = vmin, *max = vmax;
+
+ copy_v4_fl(min->col, FLT_MAX);
+ copy_v4_fl(max->col, FLT_MIN);
+}
+
+static void layerDefault_propcol(void *data, int count)
+{
+ /* Default to white, full alpha. */
+ MPropCol default_propcol = {{1.0f, 1.0f, 1.0f, 1.0f}};
+ MPropCol *pcol = (MPropCol *)data;
+ int i;
+ for (i = 0; i < count; i++) {
+ copy_v4_v4(pcol[i].col, default_propcol.col);
+ }
+}
+
+static void layerInterp_propcol(
+ const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
+{
+ MPropCol *mc = dest;
+ float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ const float *sub_weight = sub_weights;
+ for (int i = 0; i < count; i++) {
+ float weight = weights ? weights[i] : 1.0f;
+ const MPropCol *src = sources[i];
+ if (sub_weights) {
+ madd_v4_v4fl(col, src->col, (*sub_weight) * weight);
+ sub_weight++;
+ }
+ else {
+ madd_v4_v4fl(col, src->col, weight);
+ }
+ }
+ copy_v4_v4(mc->col, col);
+}
+
+static int layerMaxNum_propcol(void)
+{
+ return MAX_MCOL;
+}
+
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */
{sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
@@ -1654,7 +1780,27 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(HairCurve), "HairCurve", 1, NULL, NULL, NULL, NULL, NULL, NULL},
/* 46: CD_HAIR_MAPPING */
{sizeof(HairMapping), "HairMapping", 1, NULL, NULL, NULL, NULL, NULL, NULL},
-};
+ /* 47: CD_PROP_COL */
+ {sizeof(MPropCol),
+ "MPropCol",
+ 1,
+ N_("Col"),
+ NULL,
+ NULL,
+ layerInterp_propcol,
+ NULL,
+ layerDefault_propcol,
+ NULL,
+ layerEqual_propcol,
+ layerMultiply_propcol,
+ layerInitMinMax_propcol,
+ layerAdd_propcol,
+ layerDoMinMax_propcol,
+ layerCopyValue_propcol,
+ NULL,
+ NULL,
+ NULL,
+ layerMaxNum_propcol}};
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* 0-4 */ "CDMVert",
@@ -1706,6 +1852,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDHairCurve",
"CDHairMapping",
"CDPoint",
+ "CDPropCol",
};
const CustomData_MeshMasks CD_MASK_BAREMESH = {
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index f3cc17f46f6..dae8a59fe43 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -2704,15 +2704,16 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
}
}
+ const int final_tri_index = tempPoints[final_index].tri_index;
/* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */
- if (tempPoints[final_index].tri_index != target_tri) {
+ if (final_tri_index != target_tri && final_tri_index != -1) {
/* Check if it's close enough to likely touch the intended triangle. Any triangle
* becomes thinner than a pixel at its vertices, so robustness requires some margin. */
const float final_pt[2] = {((final_index % w) + 0.5f) / w, ((final_index / w) + 0.5f) / h};
const float threshold = square_f(0.7f) / (w * h);
- if (dist_squared_to_looptri_uv_edges(
- mlooptri, mloopuv, tempPoints[final_index].tri_index, final_pt) > threshold) {
+ if (dist_squared_to_looptri_uv_edges(mlooptri, mloopuv, final_tri_index, final_pt) >
+ threshold) {
continue;
}
}
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index 5aaae74e670..c4160d6d253 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -32,6 +32,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_iterators.h"
@@ -266,7 +267,7 @@ BoundBox *BKE_editmesh_cage_boundbox_get(BMEditMesh *em)
float min[3], max[3];
INIT_MINMAX(min, max);
if (em->mesh_eval_cage) {
- BKE_mesh_minmax(em->mesh_eval_cage, min, max);
+ BKE_mesh_wrapper_minmax(em->mesh_eval_cage, min, max);
}
em->bb_cage = MEM_callocN(sizeof(BoundBox), "BMEditMesh.bb_cage");
diff --git a/source/blender/blenkernel/intern/editmesh_cache.c b/source/blender/blenkernel/intern/editmesh_cache.c
index 8d3f1e84bcd..5017a48d14e 100644
--- a/source/blender/blenkernel/intern/editmesh_cache.c
+++ b/source/blender/blenkernel/intern/editmesh_cache.c
@@ -22,11 +22,17 @@
#include "MEM_guardedalloc.h"
+#include "BLI_math_vector.h"
+
#include "DNA_mesh_types.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h" /* own include */
+/* -------------------------------------------------------------------- */
+/** \name Ensure Data (derived from coords)
+ * \{ */
+
void BKE_editmesh_cache_ensure_poly_normals(BMEditMesh *em, EditMeshData *emd)
{
if (!(emd->vertexCos && (emd->polyNos == NULL))) {
@@ -112,3 +118,41 @@ void BKE_editmesh_cache_ensure_poly_centers(BMEditMesh *em, EditMeshData *emd)
emd->polyCos = (const float(*)[3])polyCos;
}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Calculate Min/Max
+ * \{ */
+
+bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em,
+ struct EditMeshData *emd,
+ float min[3],
+ float max[3])
+{
+ BMesh *bm = em->bm;
+ BMVert *eve;
+ BMIter iter;
+ int i;
+
+ if (bm->totvert) {
+ if (emd->vertexCos) {
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ minmax_v3v3_v3(min, max, emd->vertexCos[i]);
+ }
+ }
+ else {
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(min, max, eve->co);
+ }
+ }
+ return true;
+ }
+ else {
+ zero_v3(min);
+ zero_v3(max);
+ return false;
+ }
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 5d2207b5b80..d4754615c7f 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -31,6 +31,7 @@
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
+#include "DNA_text_types.h"
#include "BLI_blenlib.h"
#include "BLI_easing.h"
@@ -43,6 +44,8 @@
#include "BKE_fcurve.h"
#include "BKE_fcurve_driver.h"
#include "BKE_global.h"
+#include "BKE_idprop.h"
+#include "BKE_lib_query.h"
#include "BKE_nla.h"
#include "RNA_access.h"
@@ -55,11 +58,15 @@
static CLG_LogRef LOG = {"bke.fcurve"};
/* ************************** Data-Level Functions ************************* */
-
+FCurve *BKE_fcurve_create(void)
+{
+ FCurve *fcu = MEM_callocN(sizeof(FCurve), __func__);
+ return fcu;
+}
/* ---------------------- Freeing --------------------------- */
/* Frees the F-Curve itself too, so make sure BLI_remlink is called before calling this... */
-void free_fcurve(FCurve *fcu)
+void BKE_fcurve_free(FCurve *fcu)
{
if (fcu == NULL) {
return;
@@ -81,7 +88,7 @@ void free_fcurve(FCurve *fcu)
}
/* Frees a list of F-Curves */
-void free_fcurves(ListBase *list)
+void BKE_fcurves_free(ListBase *list)
{
FCurve *fcu, *fcn;
@@ -96,7 +103,7 @@ void free_fcurves(ListBase *list)
*/
for (fcu = list->first; fcu; fcu = fcn) {
fcn = fcu->next;
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
}
/* clear pointers just in case */
@@ -106,7 +113,7 @@ void free_fcurves(ListBase *list)
/* ---------------------- Copy --------------------------- */
/* duplicate an F-Curve */
-FCurve *copy_fcurve(const FCurve *fcu)
+FCurve *BKE_fcurve_copy(const FCurve *fcu)
{
FCurve *fcu_d;
@@ -139,7 +146,7 @@ FCurve *copy_fcurve(const FCurve *fcu)
}
/* duplicate a list of F-Curves */
-void copy_fcurves(ListBase *dst, ListBase *src)
+void BKE_fcurves_copy(ListBase *dst, ListBase *src)
{
FCurve *dfcu, *sfcu;
@@ -153,11 +160,43 @@ void copy_fcurves(ListBase *dst, ListBase *src)
/* copy one-by-one */
for (sfcu = src->first; sfcu; sfcu = sfcu->next) {
- dfcu = copy_fcurve(sfcu);
+ dfcu = BKE_fcurve_copy(sfcu);
BLI_addtail(dst, dfcu);
}
}
+/** Callback used by lib_query to walk over all ID usages (mimics `foreach_id` callback of
+ * `IDTypeInfo` structure). */
+void BKE_fcurve_foreach_id(FCurve *fcu, LibraryForeachIDData *data)
+{
+ ChannelDriver *driver = fcu->driver;
+
+ if (driver != NULL) {
+ LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
+ /* only used targets */
+ DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
+ BKE_LIB_FOREACHID_PROCESS_ID(data, dtar->id, IDWALK_CB_NOP);
+ }
+ DRIVER_TARGETS_LOOPER_END;
+ }
+ }
+
+ LISTBASE_FOREACH (FModifier *, fcm, &fcu->modifiers) {
+ switch (fcm->type) {
+ case FMODIFIER_TYPE_PYTHON: {
+ FMod_Python *fcm_py = (FMod_Python *)fcm->data;
+ BKE_LIB_FOREACHID_PROCESS(data, fcm_py->script, IDWALK_CB_NOP);
+
+ IDP_foreach_property(fcm_py->prop,
+ IDP_TYPE_FILTER_ID,
+ BKE_lib_query_idpropertiesForeachIDLink_callback,
+ data);
+ break;
+ }
+ }
+ }
+}
+
/* ----------------- Finding F-Curves -------------------------- */
/* high level function to get an fcurve from C without having the rna */
@@ -195,12 +234,12 @@ FCurve *id_data_find_fcurve(
/* animation takes priority over drivers */
if (adt->action && adt->action->curves.first) {
- fcu = list_find_fcurve(&adt->action->curves, path, index);
+ fcu = BKE_fcurve_find(&adt->action->curves, path, index);
}
/* if not animated, check if driven */
if (fcu == NULL && adt->drivers.first) {
- fcu = list_find_fcurve(&adt->drivers, path, index);
+ fcu = BKE_fcurve_find(&adt->drivers, path, index);
if (fcu && r_driven) {
*r_driven = true;
}
@@ -214,7 +253,7 @@ FCurve *id_data_find_fcurve(
/* Find the F-Curve affecting the given RNA-access path + index,
* in the list of F-Curves provided. */
-FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_index)
+FCurve *BKE_fcurve_find(ListBase *list, const char rna_path[], const int array_index)
{
FCurve *fcu;
@@ -239,7 +278,7 @@ FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_
}
/* quick way to loop over all fcurves of a given 'path' */
-FCurve *iter_step_fcurve(FCurve *fcu_iter, const char rna_path[])
+FCurve *BKE_fcurve_iter_step(FCurve *fcu_iter, const char rna_path[])
{
FCurve *fcu;
@@ -272,10 +311,7 @@ FCurve *iter_step_fcurve(FCurve *fcu_iter, const char rna_path[])
* - dataPrefix: i.e. 'pose.bones[' or 'nodes['
* - dataName: name of entity within "" immediately following the prefix
*/
-int list_find_data_fcurves(ListBase *dst,
- ListBase *src,
- const char *dataPrefix,
- const char *dataName)
+int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName)
{
FCurve *fcu;
int matches = 0;
@@ -317,26 +353,26 @@ int list_find_data_fcurves(ListBase *dst,
return matches;
}
-FCurve *rna_get_fcurve(PointerRNA *ptr,
- PropertyRNA *prop,
- int rnaindex,
- AnimData **r_adt,
- bAction **r_action,
- bool *r_driven,
- bool *r_special)
+FCurve *BKE_fcurve_find_by_rna(PointerRNA *ptr,
+ PropertyRNA *prop,
+ int rnaindex,
+ AnimData **r_adt,
+ bAction **r_action,
+ bool *r_driven,
+ bool *r_special)
{
- return rna_get_fcurve_context_ui(
+ return BKE_fcurve_find_by_rna_context_ui(
NULL, ptr, prop, rnaindex, r_adt, r_action, r_driven, r_special);
}
-FCurve *rna_get_fcurve_context_ui(bContext *C,
- PointerRNA *ptr,
- PropertyRNA *prop,
- int rnaindex,
- AnimData **r_animdata,
- bAction **r_action,
- bool *r_driven,
- bool *r_special)
+FCurve *BKE_fcurve_find_by_rna_context_ui(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int rnaindex,
+ AnimData **r_animdata,
+ bAction **r_action,
+ bool *r_driven,
+ bool *r_special)
{
FCurve *fcu = NULL;
PointerRNA tptr = *ptr;
@@ -361,7 +397,7 @@ FCurve *rna_get_fcurve_context_ui(bContext *C,
*r_special = true;
/* The F-Curve either exists or it doesn't here... */
- fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), rnaindex);
+ fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), rnaindex);
return fcu;
}
@@ -397,7 +433,7 @@ FCurve *rna_get_fcurve_context_ui(bContext *C,
// XXX: the logic here is duplicated with a function up above
/* animation takes priority over drivers */
if (adt->action && adt->action->curves.first) {
- fcu = list_find_fcurve(&adt->action->curves, path, rnaindex);
+ fcu = BKE_fcurve_find(&adt->action->curves, path, rnaindex);
if (fcu && r_action) {
*r_action = adt->action;
@@ -406,7 +442,7 @@ FCurve *rna_get_fcurve_context_ui(bContext *C,
/* if not animated, check if driven */
if (!fcu && (adt->drivers.first)) {
- fcu = list_find_fcurve(&adt->drivers, path, rnaindex);
+ fcu = BKE_fcurve_find(&adt->drivers, path, rnaindex);
if (fcu) {
if (r_animdata) {
@@ -596,13 +632,13 @@ static short get_fcurve_end_keyframes(FCurve *fcu,
}
/* Calculate the extents of F-Curve's data */
-bool calc_fcurve_bounds(FCurve *fcu,
- float *xmin,
- float *xmax,
- float *ymin,
- float *ymax,
- const bool do_sel_only,
- const bool include_handles)
+bool BKE_fcurve_calc_bounds(FCurve *fcu,
+ float *xmin,
+ float *xmax,
+ float *ymin,
+ float *ymax,
+ const bool do_sel_only,
+ const bool include_handles)
{
float xminv = 999999999.0f, xmaxv = -999999999.0f;
float yminv = 999999999.0f, ymaxv = -999999999.0f;
@@ -726,7 +762,7 @@ bool calc_fcurve_bounds(FCurve *fcu,
}
/* Calculate the extents of F-Curve's keyframes */
-bool calc_fcurve_range(
+bool BKE_fcurve_calc_range(
FCurve *fcu, float *start, float *end, const bool do_sel_only, const bool do_min_length)
{
float min = 999999999.0f, max = -999999999.0f;
@@ -779,7 +815,7 @@ bool calc_fcurve_range(
* Usability of keyframes refers to whether they should be displayed,
* and also whether they will have any influence on the final result.
*/
-bool fcurve_are_keyframes_usable(FCurve *fcu)
+bool BKE_fcurve_are_keyframes_usable(FCurve *fcu)
{
/* F-Curve must exist */
if (fcu == NULL) {
@@ -847,10 +883,10 @@ bool BKE_fcurve_is_protected(FCurve *fcu)
/* Can keyframes be added to F-Curve?
* Keyframes can only be added if they are already visible
*/
-bool fcurve_is_keyframable(FCurve *fcu)
+bool BKE_fcurve_is_keyframable(FCurve *fcu)
{
/* F-Curve's keyframes must be "usable" (i.e. visible + have an effect on final result) */
- if (fcurve_are_keyframes_usable(fcu) == 0) {
+ if (BKE_fcurve_are_keyframes_usable(fcu) == 0) {
return false;
}
@@ -1447,8 +1483,8 @@ static float fcurve_eval_keyframes_extrapolate(
return endpoint_bezt->vec[1][1] - (fac * dx);
}
- /* Use the gradient of the second handle (later) of neighbour to calculate the gradient and thus
- * the value of the curve at evaltime */
+ /* Use the gradient of the second handle (later) of neighbor to calculate the gradient and thus
+ * the value of the curve at evaluation time. */
int handle = direction_to_neighbor > 0 ? 0 : 2;
float dx = endpoint_bezt->vec[1][0] - evaltime;
float fac = endpoint_bezt->vec[1][0] - endpoint_bezt->vec[handle][0];
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 4311e425abf..122cc656bc2 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -839,12 +839,7 @@ bool BKE_gpencil_layer_is_editable(const bGPDlayer *gpl)
/* Layer must be: Visible + Editable */
if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0) {
- /* Opacity must be sufficiently high that it is still "visible"
- * Otherwise, it's not really "visible" to the user, so no point editing...
- */
- if (gpl->opacity > GPENCIL_ALPHA_OPACITY_THRESH) {
- return true;
- }
+ return true;
}
/* Something failed */
@@ -1855,8 +1850,13 @@ bool BKE_gpencil_from_image(SpaceImage *sima, bGPDframe *gpf, const float size,
*
* \{ */
-void BKE_gpencil_visible_stroke_iter(
- Object *ob, gpIterCb layer_cb, gpIterCb stroke_cb, void *thunk, bool do_onion, int cfra)
+void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer,
+ Object *ob,
+ gpIterCb layer_cb,
+ gpIterCb stroke_cb,
+ void *thunk,
+ bool do_onion,
+ int cfra)
{
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
@@ -1878,6 +1878,14 @@ void BKE_gpencil_visible_stroke_iter(
continue;
}
+ /* Hide the layer if it's defined a view layer filter. This is used to
+ * generate renders, putting only selected GP layers for each View Layer.
+ * This is used only in final render and never in Viewport. */
+ if ((view_layer != NULL) && (gpl->viewlayername[0] != '\0') &&
+ (!STREQ(view_layer->name, gpl->viewlayername))) {
+ continue;
+ }
+
if (is_multiedit) {
sta_gpf = end_gpf = NULL;
/* Check the whole range and tag the editable frames. */
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 780c3c2f14a..7bf9cb2d0a1 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1341,7 +1341,7 @@ static void icu_to_fcurves(ID *id,
int totbits;
/* allocate memory for a new F-Curve */
- fcu = MEM_callocN(sizeof(FCurve), "FCurve");
+ fcu = BKE_fcurve_create();
/* convert driver */
if (icu->driver) {
@@ -1420,7 +1420,7 @@ static void icu_to_fcurves(ID *id,
/* make a copy of existing base-data if not the last curve */
if (b < (totbits - 1)) {
- fcurve = copy_fcurve(fcu);
+ fcurve = BKE_fcurve_copy(fcu);
}
else {
fcurve = fcu;
@@ -2396,7 +2396,7 @@ void do_versions_ipos_to_animato(Main *bmain)
}
/* free unused drivers from actions + ipos */
- free_fcurves(&drivers);
+ BKE_fcurves_free(&drivers);
if (G.debug & G_DEBUG) {
printf("INFO: Animato convert done\n");
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 0eaf7cf2f41..f03bf60817f 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -694,14 +694,14 @@ int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection
* in at least one layer collection. That list is also synchronized here, and
* stores state like selection. */
-static short layer_collection_sync(ViewLayer *view_layer,
- const ListBase *lb_scene,
- ListBase *lb_layer,
- ListBase *new_object_bases,
- short parent_exclude,
- short parent_restrict,
- short parent_layer_restrict,
- unsigned short parent_local_collections_bits)
+static void layer_collection_sync(ViewLayer *view_layer,
+ const ListBase *lb_scene,
+ ListBase *lb_layer,
+ ListBase *new_object_bases,
+ short parent_exclude,
+ short parent_restrict,
+ short parent_layer_restrict,
+ unsigned short parent_local_collections_bits)
{
/* TODO: support recovery after removal of intermediate collections, reordering, ..
* For local edits we can make editing operating do the appropriate thing, but for
@@ -732,7 +732,6 @@ static short layer_collection_sync(ViewLayer *view_layer,
/* Add layer collections for any new scene collections, and ensure order is the same. */
ListBase new_lb_layer = {NULL, NULL};
- short runtime_flag = 0;
LISTBASE_FOREACH (const CollectionChild *, child, lb_scene) {
Collection *collection = child->collection;
@@ -763,23 +762,20 @@ static short layer_collection_sync(ViewLayer *view_layer,
}
/* Sync child collections. */
- short child_runtime_flag = layer_collection_sync(view_layer,
- &collection->children,
- &lc->layer_collections,
- new_object_bases,
- lc->flag,
- child_restrict,
- child_layer_restrict,
- local_collections_bits);
+ layer_collection_sync(view_layer,
+ &collection->children,
+ &lc->layer_collections,
+ new_object_bases,
+ lc->flag,
+ child_restrict,
+ child_layer_restrict,
+ local_collections_bits);
/* Layer collection exclude is not inherited. */
+ lc->runtime_flag = 0;
if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
- lc->runtime_flag = 0;
continue;
}
- else {
- lc->runtime_flag = child_runtime_flag;
- }
/* We separate restrict viewport and visible view layer because a layer collection can be
* hidden in the view layer yet (locally) visible in a viewport (if it is not restricted).*/
@@ -846,15 +842,11 @@ static short layer_collection_sync(ViewLayer *view_layer,
lc->runtime_flag |= LAYER_COLLECTION_HAS_OBJECTS;
}
-
- runtime_flag |= lc->runtime_flag;
}
/* Replace layer collection list with new one. */
*lb_layer = new_lb_layer;
BLI_assert(BLI_listbase_count(lb_scene) == BLI_listbase_count(lb_layer));
-
- return runtime_flag;
}
/**
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 9ef5c549235..19462c62496 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -128,8 +128,6 @@ static void lib_id_library_local_paths(Main *bmain, Library *lib, ID *id)
*/
static void lib_id_clear_library_data_ex(Main *bmain, ID *id)
{
- bNodeTree *ntree = NULL;
- Key *key = NULL;
const bool id_in_mainlist = (id->tag & LIB_TAG_NO_MAIN) == 0 &&
(id->flag & LIB_EMBEDDED_DATA) == 0;
@@ -146,14 +144,11 @@ static void lib_id_clear_library_data_ex(Main *bmain, ID *id)
}
}
- /* Internal bNodeTree blocks inside data-blocks also stores id->lib,
- * make sure this stays in sync. */
- if ((ntree = ntreeFromID(id))) {
- lib_id_clear_library_data_ex(bmain, &ntree->id);
- }
-
- /* Same goes for shapekeys. */
- if ((key = BKE_key_from_id(id))) {
+ /* Internal shape key blocks inside data-blocks also stores id->lib,
+ * make sure this stays in sync (note that we do not need any explicit handling for real EMBEDDED
+ * IDs here, this is down automatically in `lib_id_expand_local_cb()`. */
+ Key *key = BKE_key_from_id(id);
+ if (key != NULL) {
lib_id_clear_library_data_ex(bmain, &key->id);
}
}
@@ -310,10 +305,23 @@ void BKE_id_clear_newpoin(ID *id)
static int lib_id_expand_local_cb(LibraryIDLinkCallbackData *cb_data)
{
+ Main *bmain = cb_data->bmain;
ID *id_self = cb_data->id_self;
ID **id_pointer = cb_data->id_pointer;
int const cb_flag = cb_data->cb_flag;
+
+ if (cb_flag & IDWALK_CB_LOOPBACK) {
+ /* We should never have anything to do with loopback pointers here. */
+ return IDWALK_RET_NOP;
+ }
+
if (cb_flag & IDWALK_CB_EMBEDDED) {
+ /* Embedded data-blocks need to be made fully local as well. */
+ if (*id_pointer != NULL) {
+ BLI_assert(*id_pointer != id_self);
+
+ lib_id_clear_library_data_ex(bmain, *id_pointer);
+ }
return IDWALK_RET_NOP;
}
@@ -335,7 +343,7 @@ static int lib_id_expand_local_cb(LibraryIDLinkCallbackData *cb_data)
*/
void BKE_lib_id_expand_local(Main *bmain, ID *id)
{
- BKE_library_foreach_ID_link(bmain, id, lib_id_expand_local_cb, NULL, IDWALK_READONLY);
+ BKE_library_foreach_ID_link(bmain, id, lib_id_expand_local_cb, bmain, IDWALK_READONLY);
}
/**
@@ -393,6 +401,13 @@ void BKE_lib_id_make_local_generic(Main *bmain, ID *id, const int flags)
if (ntree && ntree_new) {
ID_NEW_SET(ntree, ntree_new);
}
+ if (GS(id->name) == ID_SCE) {
+ Collection *master_collection = ((Scene *)id)->master_collection,
+ *master_collection_new = ((Scene *)id_new)->master_collection;
+ if (master_collection && master_collection_new) {
+ ID_NEW_SET(master_collection, master_collection_new);
+ }
+ }
if (!lib_local) {
BKE_libblock_remap(bmain, id, id_new, ID_REMAP_SKIP_INDIRECT_USAGE);
@@ -1676,20 +1691,6 @@ static void library_make_local_copying_check(ID *id,
/* Our oh-so-beloved 'from' pointers... Those should always be ignored here, since the actual
* relation we want to check is in the other way around. */
if (entry->usage_flag & IDWALK_CB_LOOPBACK) {
-#ifndef NDEBUG
- /* Some debug checks to ensure we explicitly are aware of all 'loop-back' cases, since those
- * may not always be manageable in the same way... */
- switch (GS(par_id->name)) {
- case ID_OB:
- BLI_assert(((Object *)par_id)->proxy_from == (Object *)id);
- break;
- case ID_KE:
- BLI_assert(((Key *)par_id)->from == id);
- break;
- default:
- BLI_assert(0);
- }
-#endif
continue;
}
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 795390f1940..9426d229e01 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -46,6 +46,11 @@
#include "RNA_types.h"
#define OVERRIDE_AUTO_CHECK_DELAY 0.2 /* 200ms between auto-override checks. */
+//#define DEBUG_OVERRIDE_TIMEIT
+
+#ifdef DEBUG_OVERRIDE_TIMEIT
+# include "PIL_time_utildefines.h"
+#endif
static void lib_override_library_property_copy(IDOverrideLibraryProperty *op_dst,
IDOverrideLibraryProperty *op_src);
@@ -1027,7 +1032,7 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain,
ID *storage_id;
#ifdef DEBUG_OVERRIDE_TIMEIT
- TIMEIT_START_AVERAGED(BKE_override_operations_store_start);
+ TIMEIT_START_AVERAGED(BKE_lib_override_library_operations_store_start);
#endif
/* XXX TODO We may also want a specialized handling of things here too, to avoid copying heavy
@@ -1055,12 +1060,13 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain,
local->override_library->storage = storage_id;
#ifdef DEBUG_OVERRIDE_TIMEIT
- TIMEIT_END_AVERAGED(BKE_override_operations_store_start);
+ TIMEIT_END_AVERAGED(BKE_lib_override_library_operations_store_start);
#endif
return storage_id;
}
-/** Restore given ID modified by \a BKE_override_operations_store_start, to its original state. */
+/** Restore given ID modified by \a BKE_lib_override_library_operations_store_start, to its
+ * original state. */
void BKE_lib_override_library_operations_store_end(
OverrideLibraryStorage *UNUSED(override_storage), ID *local)
{
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c
index 015fa235a06..00a42b12e07 100644
--- a/source/blender/blenkernel/intern/lib_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -24,41 +24,6 @@
#include <stdlib.h>
#include "DNA_anim_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_collection_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_hair_types.h"
-#include "DNA_key_types.h"
-#include "DNA_lattice_types.h"
-#include "DNA_light_types.h"
-#include "DNA_lightprobe_types.h"
-#include "DNA_linestyle_types.h"
-#include "DNA_mask_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meta_types.h"
-#include "DNA_movieclip_types.h"
-#include "DNA_node_types.h"
-#include "DNA_object_force_types.h"
-#include "DNA_outliner_types.h"
-#include "DNA_pointcloud_types.h"
-#include "DNA_rigidbody_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_sequence_types.h"
-#include "DNA_simulation_types.h"
-#include "DNA_sound_types.h"
-#include "DNA_space_types.h"
-#include "DNA_speaker_types.h"
-#include "DNA_text_types.h"
-#include "DNA_vfont_types.h"
-#include "DNA_volume_types.h"
-#include "DNA_windowmanager_types.h"
-#include "DNA_workspace_types.h"
-#include "DNA_world_types.h"
#include "BLI_ghash.h"
#include "BLI_linklist_stack.h"
@@ -66,24 +31,12 @@
#include "BLI_utildefines.h"
#include "BKE_anim_data.h"
-#include "BKE_collection.h"
-#include "BKE_constraint.h"
-#include "BKE_fcurve_driver.h"
-#include "BKE_gpencil_modifier.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_main.h"
-#include "BKE_modifier.h"
#include "BKE_node.h"
-#include "BKE_particle.h"
-#include "BKE_rigidbody.h"
-#include "BKE_screen.h"
-#include "BKE_sequencer.h"
-#include "BKE_shader_fx.h"
-#include "BKE_texture.h"
-#include "BKE_workspace.h"
/* status */
enum {
@@ -122,6 +75,7 @@ bool BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int
ID *old_id = *id_pp;
const int callback_return = data->callback(&(struct LibraryIDLinkCallbackData){
.user_data = data->user_data,
+ .bmain = data->bmain,
.id_owner = data->owner_id,
.id_self = data->self_id,
.id_pointer = id_pp,
@@ -182,39 +136,6 @@ void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void
BKE_LIB_FOREACHID_PROCESS_ID(data, id_prop->data.pointer, IDWALK_CB_USER);
}
-static void library_foreach_nla_strip(LibraryForeachIDData *data, NlaStrip *strip)
-{
- BKE_LIB_FOREACHID_PROCESS(data, strip->act, IDWALK_CB_USER);
-
- LISTBASE_FOREACH (NlaStrip *, substrip, &strip->strips) {
- library_foreach_nla_strip(data, substrip);
- }
-}
-
-static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *adt)
-{
- LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
- ChannelDriver *driver = fcu->driver;
-
- LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
- /* only used targets */
- DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
- BKE_LIB_FOREACHID_PROCESS_ID(data, dtar->id, IDWALK_CB_NOP);
- }
- DRIVER_TARGETS_LOOPER_END;
- }
- }
-
- BKE_LIB_FOREACHID_PROCESS(data, adt->action, IDWALK_CB_USER);
- BKE_LIB_FOREACHID_PROCESS(data, adt->tmpact, IDWALK_CB_USER);
-
- LISTBASE_FOREACH (NlaTrack *, nla_track, &adt->nla_tracks) {
- LISTBASE_FOREACH (NlaStrip *, nla_strip, &nla_track->strips) {
- library_foreach_nla_strip(data, nla_strip);
- }
- }
-}
-
bool BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp)
{
/* Needed e.g. for callbacks handling relationships... This call shall be absolutely readonly. */
@@ -341,7 +262,7 @@ static void library_foreach_ID_link(Main *bmain,
AnimData *adt = BKE_animdata_from_id(id);
if (adt) {
- library_foreach_animationData(&data, adt);
+ BKE_animdata_foreach_id(adt, &data);
}
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c
index 9dc338ce580..aa1005c663f 100644
--- a/source/blender/blenkernel/intern/light.c
+++ b/source/blender/blenkernel/intern/light.c
@@ -48,6 +48,8 @@
#include "BLT_translation.h"
+#include "DEG_depsgraph.h"
+
static void light_init_data(ID *id)
{
Light *la = (Light *)id;
@@ -178,3 +180,8 @@ Light *BKE_light_localize(Light *la)
return lan;
}
+
+void BKE_light_eval(struct Depsgraph *depsgraph, Light *la)
+{
+ DEG_debug_print_eval(depsgraph, __func__, la->id.name, la);
+}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index aeef287bb87..0d20d25f84c 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -866,26 +866,6 @@ Mesh *BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm,
return mesh;
}
-/**
- * TODO(campbell): support mesh with only an edit-mesh which is lazy initialized.
- */
-Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap(BMEditMesh *em,
- const CustomData_MeshMasks *cd_mask_extra,
- float (*vertexCos)[3],
- const Mesh *me_settings)
-{
- Mesh *me = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, cd_mask_extra, me_settings);
- /* Use editmesh directly where possible. */
- me->runtime.is_original = true;
- if (vertexCos) {
- /* We will own this array in the future. */
- BKE_mesh_vert_coords_apply(me, vertexCos);
- MEM_freeN(vertexCos);
- me->runtime.is_original = false;
- }
- return me;
-}
-
BoundBox *BKE_mesh_boundbox_get(Object *ob)
{
/* This is Object-level data access,
@@ -895,7 +875,7 @@ BoundBox *BKE_mesh_boundbox_get(Object *ob)
float min[3], max[3];
INIT_MINMAX(min, max);
- if (!BKE_mesh_minmax(me, min, max)) {
+ if (!BKE_mesh_wrapper_minmax(me, min, max)) {
min[0] = min[1] = min[2] = -1.0f;
max[0] = max[1] = max[2] = 1.0f;
}
@@ -916,7 +896,7 @@ void BKE_mesh_texspace_calc(Mesh *me)
float min[3], max[3];
INIT_MINMAX(min, max);
- if (!BKE_mesh_minmax(me, min, max)) {
+ if (!BKE_mesh_wrapper_minmax(me, min, max)) {
min[0] = min[1] = min[2] = -1.0f;
max[0] = max[1] = max[2] = 1.0f;
}
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index 655c70bcf61..f2c84028570 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -1076,6 +1076,10 @@ static Mesh *mesh_new_from_mball_object(Object *object)
static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh)
{
+ /* While we could copy this into the new mesh,
+ * add the data to 'mesh' so future calls to this function don't need to re-convert the data. */
+ BKE_mesh_wrapper_ensure_mdata(mesh);
+
Mesh *mesh_result = NULL;
BKE_id_copy_ex(NULL,
&mesh->id,
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index f0d19f01aab..433db26ded8 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -46,6 +46,7 @@
#include "BLI_utildefines.h"
#include "BKE_customdata.h"
+#include "BKE_editmesh_cache.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_multires.h"
@@ -396,6 +397,21 @@ void BKE_mesh_ensure_normals(Mesh *mesh)
*/
void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
{
+ switch ((eMeshWrapperType)mesh->runtime.wrapper_type) {
+ case ME_WRAPPER_TYPE_MDATA:
+ /* Run code below. */
+ break;
+ case ME_WRAPPER_TYPE_BMESH: {
+ struct BMEditMesh *em = mesh->edit_mesh;
+ EditMeshData *emd = mesh->runtime.edit_data;
+ if (emd->vertexCos) {
+ BKE_editmesh_cache_ensure_vert_normals(em, emd);
+ BKE_editmesh_cache_ensure_poly_normals(em, emd);
+ }
+ return;
+ }
+ }
+
float(*poly_nors)[3] = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
const bool do_vert_normals = (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) != 0;
const bool do_poly_normals = (mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL || poly_nors == NULL);
diff --git a/source/blender/blenkernel/intern/mesh_iterators.c b/source/blender/blenkernel/intern/mesh_iterators.c
index f2ed9456b11..5ecf5ae316d 100644
--- a/source/blender/blenkernel/intern/mesh_iterators.c
+++ b/source/blender/blenkernel/intern/mesh_iterators.c
@@ -24,6 +24,8 @@
#include "DNA_meshdata_types.h"
#include "BKE_customdata.h"
+#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
#include "BKE_mesh.h"
#include "BKE_mesh_iterators.h"
@@ -42,23 +44,53 @@ void BKE_mesh_foreach_mapped_vert(Mesh *mesh,
void *userData,
MeshForeachFlag flag)
{
- const MVert *mv = mesh->mvert;
- const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
-
- if (index) {
- for (int i = 0; i < mesh->totvert; i++, mv++) {
- const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
- const int orig = *index++;
- if (orig == ORIGINDEX_NONE) {
- continue;
+ if (mesh->edit_mesh != NULL) {
+ BMEditMesh *em = mesh->edit_mesh;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMVert *eve;
+ int i;
+ if (mesh->runtime.edit_data->vertexCos != NULL) {
+ const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
+ const float(*vertexNos)[3];
+ if (flag & MESH_FOREACH_USE_NORMAL) {
+ BKE_editmesh_cache_ensure_vert_normals(em, mesh->runtime.edit_data);
+ vertexNos = mesh->runtime.edit_data->vertexNos;
+ }
+ else {
+ vertexNos = NULL;
+ }
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vertexNos[i] : NULL;
+ func(userData, i, vertexCos[i], no, NULL);
+ }
+ }
+ else {
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? eve->no : NULL;
+ func(userData, i, eve->co, no, NULL);
}
- func(userData, orig, mv->co, NULL, no);
}
}
else {
- for (int i = 0; i < mesh->totvert; i++, mv++) {
- const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
- func(userData, i, mv->co, NULL, no);
+ const MVert *mv = mesh->mvert;
+ const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
+
+ if (index) {
+ for (int i = 0; i < mesh->totvert; i++, mv++) {
+ const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
+ const int orig = *index++;
+ if (orig == ORIGINDEX_NONE) {
+ continue;
+ }
+ func(userData, orig, mv->co, NULL, no);
+ }
+ }
+ else {
+ for (int i = 0; i < mesh->totvert; i++, mv++) {
+ const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
+ func(userData, i, mv->co, NULL, no);
+ }
}
}
}
@@ -69,22 +101,47 @@ void BKE_mesh_foreach_mapped_edge(
void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
void *userData)
{
- const MVert *mv = mesh->mvert;
- const MEdge *med = mesh->medge;
- const int *index = CustomData_get_layer(&mesh->edata, CD_ORIGINDEX);
+ if (mesh->edit_mesh != NULL) {
+ BMEditMesh *em = mesh->edit_mesh;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMEdge *eed;
+ int i;
+ if (mesh->runtime.edit_data->vertexCos != NULL) {
+ const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
- if (index) {
- for (int i = 0; i < mesh->totedge; i++, med++) {
- const int orig = *index++;
- if (orig == ORIGINDEX_NONE) {
- continue;
+ BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
+ func(userData,
+ i,
+ vertexCos[BM_elem_index_get(eed->v1)],
+ vertexCos[BM_elem_index_get(eed->v2)]);
+ }
+ }
+ else {
+ BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
+ func(userData, i, eed->v1->co, eed->v2->co);
}
- func(userData, orig, mv[med->v1].co, mv[med->v2].co);
}
}
else {
- for (int i = 0; i < mesh->totedge; i++, med++) {
- func(userData, i, mv[med->v1].co, mv[med->v2].co);
+ const MVert *mv = mesh->mvert;
+ const MEdge *med = mesh->medge;
+ const int *index = CustomData_get_layer(&mesh->edata, CD_ORIGINDEX);
+
+ if (index) {
+ for (int i = 0; i < mesh->totedge; i++, med++) {
+ const int orig = *index++;
+ if (orig == ORIGINDEX_NONE) {
+ continue;
+ }
+ func(userData, orig, mv[med->v1].co, mv[med->v2].co);
+ }
+ }
+ else {
+ for (int i = 0; i < mesh->totedge; i++, med++) {
+ func(userData, i, mv[med->v1].co, mv[med->v2].co);
+ }
}
}
}
@@ -99,40 +156,72 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
void *userData,
MeshForeachFlag flag)
{
+
/* We can't use dm->getLoopDataLayout(dm) here,
* we want to always access dm->loopData, EditDerivedBMesh would
* return loop data from bmesh itself. */
- const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
- CustomData_get_layer(&mesh->ldata, CD_NORMAL) :
- NULL;
+ if (mesh->edit_mesh != NULL) {
+ BMEditMesh *em = mesh->edit_mesh;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMFace *efa;
- const MVert *mv = mesh->mvert;
- const MLoop *ml = mesh->mloop;
- const MPoly *mp = mesh->mpoly;
- const int *v_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
- const int *f_index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
- int p_idx, i;
-
- if (v_index || f_index) {
- for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
- for (i = 0; i < mp->totloop; i++, ml++) {
- const int v_idx = v_index ? v_index[ml->v] : ml->v;
- const int f_idx = f_index ? f_index[p_idx] : p_idx;
+ const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
+
+ /* XXX: investigate using EditMesh data. */
+ const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
+ CustomData_get_layer(&mesh->ldata, CD_NORMAL) :
+ NULL;
+
+ int f_idx;
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, f_idx) {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ const BMVert *eve = l_iter->v;
+ const int v_idx = BM_elem_index_get(eve);
const float *no = lnors ? *lnors++ : NULL;
- if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
- continue;
- }
- func(userData, v_idx, f_idx, mv[ml->v].co, no);
- }
+ func(userData, v_idx, f_idx, vertexCos ? vertexCos[v_idx] : eve->co, no);
+ } while ((l_iter = l_iter->next) != l_first);
}
}
else {
- for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
- for (i = 0; i < mp->totloop; i++, ml++) {
- const int v_idx = ml->v;
- const int f_idx = p_idx;
- const float *no = lnors ? *lnors++ : NULL;
- func(userData, v_idx, f_idx, mv[ml->v].co, no);
+ const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
+ CustomData_get_layer(&mesh->ldata, CD_NORMAL) :
+ NULL;
+
+ const MVert *mv = mesh->mvert;
+ const MLoop *ml = mesh->mloop;
+ const MPoly *mp = mesh->mpoly;
+ const int *v_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
+ const int *f_index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
+ int p_idx, i;
+
+ if (v_index || f_index) {
+ for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
+ for (i = 0; i < mp->totloop; i++, ml++) {
+ const int v_idx = v_index ? v_index[ml->v] : ml->v;
+ const int f_idx = f_index ? f_index[p_idx] : p_idx;
+ const float *no = lnors ? *lnors++ : NULL;
+ if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
+ continue;
+ }
+ func(userData, v_idx, f_idx, mv[ml->v].co, no);
+ }
+ }
+ }
+ else {
+ for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
+ for (i = 0; i < mp->totloop; i++, ml++) {
+ const int v_idx = ml->v;
+ const int f_idx = p_idx;
+ const float *no = lnors ? *lnors++ : NULL;
+ func(userData, v_idx, f_idx, mv[ml->v].co, no);
+ }
}
}
}
@@ -145,37 +234,72 @@ void BKE_mesh_foreach_mapped_face_center(
void *userData,
MeshForeachFlag flag)
{
- const MVert *mvert = mesh->mvert;
- const MPoly *mp = mesh->mpoly;
- const MLoop *ml;
- float _no_buf[3];
- float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
- const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
+ if (mesh->edit_mesh != NULL) {
+ BMEditMesh *em = mesh->edit_mesh;
+ BMesh *bm = em->bm;
+ const float(*polyCos)[3];
+ const float(*polyNos)[3];
+ BMFace *efa;
+ BMIter iter;
+ int i;
- if (index) {
- for (int i = 0; i < mesh->totpoly; i++, mp++) {
- const int orig = *index++;
- if (orig == ORIGINDEX_NONE) {
- continue;
+ BKE_editmesh_cache_ensure_poly_centers(em, mesh->runtime.edit_data);
+ polyCos = mesh->runtime.edit_data->polyCos; /* always set */
+
+ if (flag & MESH_FOREACH_USE_NORMAL) {
+ BKE_editmesh_cache_ensure_poly_normals(em, mesh->runtime.edit_data);
+ polyNos = mesh->runtime.edit_data->polyNos; /* maybe NULL */
+ }
+ else {
+ polyNos = NULL;
+ }
+
+ if (polyNos) {
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
+ const float *no = polyNos[i];
+ func(userData, i, polyCos[i], no);
}
- float cent[3];
- ml = &mesh->mloop[mp->loopstart];
- BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
- if (flag & MESH_FOREACH_USE_NORMAL) {
- BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
+ }
+ else {
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
+ const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? efa->no : NULL;
+ func(userData, i, polyCos[i], no);
}
- func(userData, orig, cent, no);
}
}
else {
- for (int i = 0; i < mesh->totpoly; i++, mp++) {
- float cent[3];
- ml = &mesh->mloop[mp->loopstart];
- BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
- if (flag & MESH_FOREACH_USE_NORMAL) {
- BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
+ const MVert *mvert = mesh->mvert;
+ const MPoly *mp = mesh->mpoly;
+ const MLoop *ml;
+ float _no_buf[3];
+ float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
+ const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
+
+ if (index) {
+ for (int i = 0; i < mesh->totpoly; i++, mp++) {
+ const int orig = *index++;
+ if (orig == ORIGINDEX_NONE) {
+ continue;
+ }
+ float cent[3];
+ ml = &mesh->mloop[mp->loopstart];
+ BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
+ if (flag & MESH_FOREACH_USE_NORMAL) {
+ BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
+ }
+ func(userData, orig, cent, no);
+ }
+ }
+ else {
+ for (int i = 0; i < mesh->totpoly; i++, mp++) {
+ float cent[3];
+ ml = &mesh->mloop[mp->loopstart];
+ BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
+ if (flag & MESH_FOREACH_USE_NORMAL) {
+ BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
+ }
+ func(userData, i, cent, no);
}
- func(userData, i, cent, no);
}
}
}
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index d09205b5744..404d6a581ae 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -1555,6 +1555,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
2,
6,
0,
+ NULL,
NULL);
}
@@ -1598,6 +1599,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
2,
6,
0,
+ NULL,
NULL);
}
diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c
index aa3586d1e3d..8bce577897b 100644
--- a/source/blender/blenkernel/intern/mesh_runtime.c
+++ b/source/blender/blenkernel/intern/mesh_runtime.c
@@ -53,6 +53,7 @@ void BKE_mesh_runtime_reset(Mesh *mesh)
memset(&mesh->runtime, 0, sizeof(mesh->runtime));
mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex");
BLI_mutex_init(mesh->runtime.eval_mutex);
+ mesh->runtime.bvh_cache = NULL;
}
/* Clear all pointers which we don't want to be shared on copying the datablock.
@@ -227,7 +228,10 @@ bool BKE_mesh_runtime_clear_edit_data(Mesh *mesh)
void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
{
- bvhcache_free(&mesh->runtime.bvh_cache);
+ if (mesh->runtime.bvh_cache) {
+ bvhcache_free(mesh->runtime.bvh_cache);
+ mesh->runtime.bvh_cache = NULL;
+ }
MEM_SAFE_FREE(mesh->runtime.looptris.array);
/* TODO(sergey): Does this really belong here? */
if (mesh->runtime.subdiv_ccg != NULL) {
diff --git a/source/blender/blenkernel/intern/mesh_wrapper.c b/source/blender/blenkernel/intern/mesh_wrapper.c
new file mode 100644
index 00000000000..f073feffedc
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_wrapper.c
@@ -0,0 +1,166 @@
+/*
+ * 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 bke
+ *
+ * The primary purpose of this API is to avoid unnecessary mesh conversion for the final
+ * output of a modified mesh.
+ *
+ * This API handles the case when the modifier stack outputs a mesh which does not have
+ * #Mesh data (#MPoly, #MLoop, #MEdge, #MVert).
+ * Currently this is used so the resulting mesh can have #BMEditMesh data,
+ * postponing the converting until it's needed or avoiding conversion entirely
+ * which can be an expensive operation.
+ * Once converted, the meshes type changes to #ME_WRAPPER_TYPE_MDATA,
+ * although the edit mesh is not cleared.
+ *
+ * This API exposes functions that abstract over the different kinds of internal data,
+ * as well as supporting converting the mesh into regular mesh.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_defaults.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_edgehash.h"
+#include "BLI_ghash.h"
+#include "BLI_hash.h"
+#include "BLI_linklist.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_animsys.h"
+#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
+#include "BKE_global.h"
+#include "BKE_idtype.h"
+#include "BKE_key.h"
+#include "BKE_lib_id.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_modifier.h"
+#include "BKE_multires.h"
+#include "BKE_object.h"
+
+#include "PIL_time.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
+ const CustomData_MeshMasks *cd_mask_extra,
+ float (*vertexCos)[3],
+ const Mesh *me_settings)
+{
+ Mesh *me = BKE_id_new_nomain(ID_ME, NULL);
+ BKE_mesh_copy_settings(me, me_settings);
+ BKE_mesh_runtime_ensure_edit_data(me);
+
+ me->runtime.wrapper_type = ME_WRAPPER_TYPE_BMESH;
+ if (cd_mask_extra) {
+ me->runtime.cd_mask_extra = *cd_mask_extra;
+ }
+
+ /* Use edit-mesh directly where possible. */
+ me->runtime.is_original = true;
+ me->edit_mesh = MEM_dupallocN(em);
+
+/* Make sure, we crash if these are ever used. */
+#ifdef DEBUG
+ me->totvert = INT_MAX;
+ me->totedge = INT_MAX;
+ me->totpoly = INT_MAX;
+ me->totloop = INT_MAX;
+#else
+ me->totvert = 0;
+ me->totedge = 0;
+ me->totpoly = 0;
+ me->totloop = 0;
+#endif
+
+ EditMeshData *edit_data = me->runtime.edit_data;
+ edit_data->vertexCos = vertexCos;
+ return me;
+}
+
+Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em,
+ const CustomData_MeshMasks *cd_mask_extra,
+ const Mesh *me_settings)
+{
+ return BKE_mesh_wrapper_from_editmesh_with_coords(em, cd_mask_extra, NULL, me_settings);
+}
+
+void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
+{
+ if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
+ return;
+ }
+ const eMeshWrapperType geom_type_orig = me->runtime.wrapper_type;
+ me->runtime.wrapper_type = ME_WRAPPER_TYPE_MDATA;
+
+ switch (geom_type_orig) {
+ case ME_WRAPPER_TYPE_MDATA: {
+ break; /* Quiet warning. */
+ }
+ case ME_WRAPPER_TYPE_BMESH: {
+ me->totvert = 0;
+ me->totedge = 0;
+ me->totpoly = 0;
+ me->totloop = 0;
+
+ BLI_assert(me->edit_mesh != NULL);
+ BLI_assert(me->runtime.edit_data != NULL);
+
+ BMEditMesh *em = me->edit_mesh;
+ BM_mesh_bm_to_me_for_eval(em->bm, me, &me->runtime.cd_mask_extra);
+
+ EditMeshData *edit_data = me->runtime.edit_data;
+ if (edit_data->vertexCos) {
+ BKE_mesh_vert_coords_apply(me, edit_data->vertexCos);
+ me->runtime.is_original = false;
+ }
+ break;
+ }
+ }
+
+ if (me->runtime.wrapper_type_finalize) {
+ BKE_mesh_wrapper_deferred_finalize(me, &me->runtime.cd_mask_extra);
+ }
+}
+
+bool BKE_mesh_wrapper_minmax(const Mesh *me, float min[3], float max[3])
+{
+ switch ((eMeshWrapperType)me->runtime.wrapper_type) {
+ case ME_WRAPPER_TYPE_BMESH:
+ return BKE_editmesh_cache_calc_minmax(me->edit_mesh, me->runtime.edit_data, min, max);
+ case ME_WRAPPER_TYPE_MDATA:
+ return BKE_mesh_minmax(me, min, max);
+ }
+ BLI_assert(0);
+ return false;
+}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 138ffbaaf71..324a9d3ccb0 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -50,6 +50,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_appdir.h"
#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
#include "BKE_global.h"
#include "BKE_idtype.h"
#include "BKE_key.h"
@@ -247,7 +248,7 @@ ModifierData *BKE_modifiers_findby_type(Object *ob, ModifierType type)
return md;
}
-ModifierData *BKE_modifiers_findny_name(Object *ob, const char *name)
+ModifierData *BKE_modifiers_findby_name(Object *ob, const char *name)
{
return BLI_findstring(&(ob->modifiers), name, offsetof(ModifierData, name));
}
@@ -947,6 +948,30 @@ void BKE_modifier_path_init(char *path, int path_maxlen, const char *name)
BLI_join_dirfile(path, path_maxlen, G.relbase_valid ? "//" : BKE_tempdir_session(), name);
}
+/**
+ * Call when #ModifierTypeInfo.dependsOnNormals callback requests normals.
+ */
+static void modwrap_dependsOnNormals(Mesh *me)
+{
+ switch ((eMeshWrapperType)me->runtime.wrapper_type) {
+ case ME_WRAPPER_TYPE_BMESH: {
+ EditMeshData *edit_data = me->runtime.edit_data;
+ if (edit_data->vertexCos) {
+ /* Note that 'ensure' is acceptable here since these values aren't modified in-place.
+ * If that changes we'll need to recalculate. */
+ BKE_editmesh_cache_ensure_vert_normals(me->edit_mesh, edit_data);
+ }
+ else {
+ BM_mesh_normals_update(me->edit_mesh->bm);
+ }
+ break;
+ }
+ case ME_WRAPPER_TYPE_MDATA:
+ BKE_mesh_calc_normals(me);
+ break;
+ }
+}
+
/* wrapper around ModifierTypeInfo.modifyMesh that ensures valid normals */
struct Mesh *BKE_modifier_modify_mesh(ModifierData *md,
@@ -956,8 +981,14 @@ struct Mesh *BKE_modifier_modify_mesh(ModifierData *md,
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
BLI_assert(CustomData_has_layer(&me->pdata, CD_NORMAL) == false);
+ if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
+ if ((mti->flags & eModifierTypeFlag_AcceptsBMesh) == 0) {
+ BKE_mesh_wrapper_ensure_mdata(me);
+ }
+ }
+
if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
- BKE_mesh_calc_normals(me);
+ modwrap_dependsOnNormals(me);
}
return mti->modifyMesh(md, ctx, me);
}
@@ -972,7 +1003,7 @@ void BKE_modifier_deform_verts(ModifierData *md,
BLI_assert(!me || CustomData_has_layer(&me->pdata, CD_NORMAL) == false);
if (me && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
- BKE_mesh_calc_normals(me);
+ modwrap_dependsOnNormals(me);
}
mti->deformVerts(md, ctx, me, vertexCos, numVerts);
}
@@ -1043,5 +1074,5 @@ struct ModifierData *BKE_modifier_get_evaluated(Depsgraph *depsgraph,
if (object_eval == object) {
return md;
}
- return BKE_modifiers_findny_name(object_eval, md->name);
+ return BKE_modifiers_findby_name(object_eval, md->name);
}
diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c
index 7312ac2bf5e..3564ae80d24 100644
--- a/source/blender/blenkernel/intern/multires_reshape_smooth.c
+++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c
@@ -55,7 +55,7 @@
/* Surface refers to a simplified and lower-memory footprint representation of the limit surface.
*
* Used to store pre-calculated information which is expensive or impossible to evaluate when
- * travesing the final limit surface. */
+ * traversing the final limit surface. */
typedef struct SurfacePoint {
float P[3];
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 6edccbccc76..7012688686b 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -49,6 +49,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_sound.h"
@@ -91,7 +92,7 @@ void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user)
// BKE_animremap_free();
/* free own F-Curves */
- free_fcurves(&strip->fcurves);
+ BKE_fcurves_free(&strip->fcurves);
/* free own F-Modifiers */
free_fmodifiers(&strip->modifiers);
@@ -197,7 +198,7 @@ NlaStrip *BKE_nlastrip_copy(Main *bmain,
}
/* copy F-Curves and modifiers */
- copy_fcurves(&strip_d->fcurves, &strip->fcurves);
+ BKE_fcurves_copy(&strip_d->fcurves, &strip->fcurves);
copy_fmodifiers(&strip_d->modifiers, &strip->modifiers);
/* make a copy of all the child-strips, one at a time */
@@ -425,6 +426,21 @@ NlaStrip *BKE_nla_add_soundstrip(Main *bmain, Scene *scene, Speaker *speaker)
return strip;
}
+/** Callback used by lib_query to walk over all ID usages (mimics `foreach_id` callback of
+ * `IDTypeInfo` structure). */
+void BKE_nla_strip_foreach_id(NlaStrip *strip, LibraryForeachIDData *data)
+{
+ BKE_LIB_FOREACHID_PROCESS(data, strip->act, IDWALK_CB_USER);
+
+ LISTBASE_FOREACH (FCurve *, fcu, &strip->fcurves) {
+ BKE_fcurve_foreach_id(fcu, data);
+ }
+
+ LISTBASE_FOREACH (NlaStrip *, substrip, &strip->strips) {
+ BKE_nla_strip_foreach_id(substrip, data);
+ }
+}
+
/* *************************************************** */
/* NLA Evaluation <-> Editing Stuff */
@@ -1478,12 +1494,12 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
/* if controlling influence... */
if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
/* try to get F-Curve */
- fcu = list_find_fcurve(&strip->fcurves, "influence", 0);
+ fcu = BKE_fcurve_find(&strip->fcurves, "influence", 0);
/* add one if not found */
if (fcu == NULL) {
/* make new F-Curve */
- fcu = MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
+ fcu = BKE_fcurve_create();
BLI_addtail(&strip->fcurves, fcu);
/* set default flags */
@@ -1509,12 +1525,12 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
/* if controlling time... */
if (strip->flag & NLASTRIP_FLAG_USR_TIME) {
/* try to get F-Curve */
- fcu = list_find_fcurve(&strip->fcurves, "strip_time", 0);
+ fcu = BKE_fcurve_find(&strip->fcurves, "strip_time", 0);
/* add one if not found */
if (fcu == NULL) {
/* make new F-Curve */
- fcu = MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
+ fcu = BKE_fcurve_create();
BLI_addtail(&strip->fcurves, fcu);
/* set default flags */
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index d17575195e3..e7a8d04e0b8 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -81,6 +81,7 @@
#include "BKE_displist.h"
#include "BKE_duplilist.h"
#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_fcurve_driver.h"
@@ -2086,8 +2087,8 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
}
/* make a copy of all the drivers (for now), then correct any links that need fixing */
- free_fcurves(&ob->adt->drivers);
- copy_fcurves(&ob->adt->drivers, &target->adt->drivers);
+ BKE_fcurves_free(&ob->adt->drivers);
+ BKE_fcurves_copy(&ob->adt->drivers, &target->adt->drivers);
for (fcu = ob->adt->drivers.first; fcu; fcu = fcu->next) {
ChannelDriver *driver = fcu->driver;
@@ -3089,7 +3090,7 @@ void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval)
INIT_MINMAX(min, max);
- if (!BKE_mesh_minmax(me_eval, min, max)) {
+ if (!BKE_mesh_wrapper_minmax(me_eval, min, max)) {
zero_v3(min);
zero_v3(max);
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 015c67806c6..eb485e1522f 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -4783,11 +4783,11 @@ void psys_get_dupli_texture(ParticleSystem *psys,
/* XXX: on checking '(psmd->dm != NULL)'
* This is incorrect but needed for metaball evaluation.
- * Ideally this would be calculated via the depsgraph, however with metaballs,
+ * Ideally this would be calculated via the depsgraph, however with meta-balls,
* the entire scenes dupli's are scanned, which also looks into uncalculated data.
*
* For now just include this workaround as an alternative to crashing,
- * but longer term metaballs should behave in a more manageable way, see: T46622. */
+ * but longer term meta-balls should behave in a more manageable way, see: T46622. */
uv[0] = uv[1] = 0.f;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index df74b7a75da..31d51a74e7f 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -2163,7 +2163,7 @@ static void psys_sph_flush_springs(SPHData *sphdata)
BLI_buffer_field_free(&sphdata->new_springs);
}
-void psys_sph_finalise(SPHData *sphdata)
+void psys_sph_finalize(SPHData *sphdata)
{
psys_sph_flush_springs(sphdata);
@@ -4046,7 +4046,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
BLI_spin_end(&task_data.spin);
- psys_sph_finalise(&sphdata);
+ psys_sph_finalize(&sphdata);
break;
}
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index e31d2a8e005..19f28047b80 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -61,7 +61,7 @@ typedef struct PBVHStack {
} PBVHStack;
typedef struct PBVHIter {
- PBVH *bvh;
+ PBVH *pbvh;
BKE_pbvh_SearchCallback scb;
void *search_data;
@@ -131,7 +131,7 @@ void BBC_update_centroid(BBC *bbc)
}
/* Not recursive */
-static void update_node_vb(PBVH *bvh, PBVHNode *node)
+static void update_node_vb(PBVH *pbvh, PBVHNode *node)
{
BB vb;
@@ -140,15 +140,15 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
if (node->flag & PBVH_Leaf) {
PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
+ BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL)
{
BB_expand(&vb, vd.co);
}
BKE_pbvh_vertex_iter_end;
}
else {
- BB_expand_with_bb(&vb, &bvh->nodes[node->children_offset].vb);
- BB_expand_with_bb(&vb, &bvh->nodes[node->children_offset + 1].vb);
+ BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset].vb);
+ BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset + 1].vb);
}
node->vb = vb;
@@ -197,24 +197,24 @@ static int partition_indices(int *prim_indices, int lo, int hi, int axis, float
}
/* Returns the index of the first element on the right of the partition */
-static int partition_indices_material(PBVH *bvh, int lo, int hi)
+static int partition_indices_material(PBVH *pbvh, int lo, int hi)
{
- const MPoly *mpoly = bvh->mpoly;
- const MLoopTri *looptri = bvh->looptri;
- const DMFlagMat *flagmats = bvh->grid_flag_mats;
- const int *indices = bvh->prim_indices;
+ const MPoly *mpoly = pbvh->mpoly;
+ const MLoopTri *looptri = pbvh->looptri;
+ const DMFlagMat *flagmats = pbvh->grid_flag_mats;
+ const int *indices = pbvh->prim_indices;
const void *first;
int i = lo, j = hi;
- if (bvh->looptri) {
- first = &mpoly[looptri[bvh->prim_indices[lo]].poly];
+ if (pbvh->looptri) {
+ first = &mpoly[looptri[pbvh->prim_indices[lo]].poly];
}
else {
- first = &flagmats[bvh->prim_indices[lo]];
+ first = &flagmats[pbvh->prim_indices[lo]];
}
for (;;) {
- if (bvh->looptri) {
+ if (pbvh->looptri) {
for (; face_materials_match(first, &mpoly[looptri[indices[i]].poly]); i++) {
/* pass */
}
@@ -235,36 +235,36 @@ static int partition_indices_material(PBVH *bvh, int lo, int hi)
return i;
}
- SWAP(int, bvh->prim_indices[i], bvh->prim_indices[j]);
+ SWAP(int, pbvh->prim_indices[i], pbvh->prim_indices[j]);
i++;
}
}
-void pbvh_grow_nodes(PBVH *bvh, int totnode)
+void pbvh_grow_nodes(PBVH *pbvh, int totnode)
{
- if (UNLIKELY(totnode > bvh->node_mem_count)) {
- bvh->node_mem_count = bvh->node_mem_count + (bvh->node_mem_count / 3);
- if (bvh->node_mem_count < totnode) {
- bvh->node_mem_count = totnode;
+ if (UNLIKELY(totnode > pbvh->node_mem_count)) {
+ pbvh->node_mem_count = pbvh->node_mem_count + (pbvh->node_mem_count / 3);
+ if (pbvh->node_mem_count < totnode) {
+ pbvh->node_mem_count = totnode;
}
- bvh->nodes = MEM_recallocN(bvh->nodes, sizeof(PBVHNode) * bvh->node_mem_count);
+ pbvh->nodes = MEM_recallocN(pbvh->nodes, sizeof(PBVHNode) * pbvh->node_mem_count);
}
- bvh->totnode = totnode;
+ pbvh->totnode = totnode;
}
/* Add a vertex to the map, with a positive value for unique vertices and
* a negative value for additional vertices */
static int map_insert_vert(
- PBVH *bvh, GHash *map, unsigned int *face_verts, unsigned int *uniq_verts, int vertex)
+ PBVH *pbvh, GHash *map, unsigned int *face_verts, unsigned int *uniq_verts, int vertex)
{
void *key, **value_p;
key = POINTER_FROM_INT(vertex);
if (!BLI_ghash_ensure_p(map, key, &value_p)) {
int value_i;
- if (BLI_BITMAP_TEST(bvh->vert_bitmap, vertex) == 0) {
- BLI_BITMAP_ENABLE(bvh->vert_bitmap, vertex);
+ if (BLI_BITMAP_TEST(pbvh->vert_bitmap, vertex) == 0) {
+ BLI_BITMAP_ENABLE(pbvh->vert_bitmap, vertex);
value_i = *uniq_verts;
(*uniq_verts)++;
}
@@ -281,7 +281,7 @@ static int map_insert_vert(
}
/* Find vertices used by the faces in this node and update the draw buffers */
-static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
+static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
{
bool has_visible = false;
@@ -295,19 +295,19 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
node->face_vert_indices = (const int(*)[3])face_vert_indices;
- if (bvh->respect_hide == false) {
+ if (pbvh->respect_hide == false) {
has_visible = true;
}
for (int i = 0; i < totface; i++) {
- const MLoopTri *lt = &bvh->looptri[node->prim_indices[i]];
+ const MLoopTri *lt = &pbvh->looptri[node->prim_indices[i]];
for (int j = 0; j < 3; j++) {
face_vert_indices[i][j] = map_insert_vert(
- bvh, map, &node->face_verts, &node->uniq_verts, bvh->mloop[lt->tri[j]].v);
+ pbvh, map, &node->face_verts, &node->uniq_verts, pbvh->mloop[lt->tri[j]].v);
}
if (has_visible == false) {
- if (!paint_is_face_hidden(lt, bvh->verts, bvh->mloop)) {
+ if (!paint_is_face_hidden(lt, pbvh->verts, pbvh->mloop)) {
has_visible = true;
}
}
@@ -347,11 +347,11 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
BLI_ghash_free(map, NULL, NULL);
}
-static void update_vb(PBVH *bvh, PBVHNode *node, BBC *prim_bbc, int offset, int count)
+static void update_vb(PBVH *pbvh, PBVHNode *node, BBC *prim_bbc, int offset, int count)
{
BB_reset(&node->vb);
for (int i = offset + count - 1; i >= offset; i--) {
- BB_expand_with_bb(&node->vb, (BB *)(&prim_bbc[bvh->prim_indices[i]]));
+ BB_expand_with_bb(&node->vb, (BB *)(&prim_bbc[pbvh->prim_indices[i]]));
}
node->orig_vb = node->vb;
}
@@ -389,77 +389,78 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
return totquad;
}
-void BKE_pbvh_sync_face_sets_to_grids(PBVH *bvh)
+void BKE_pbvh_sync_face_sets_to_grids(PBVH *pbvh)
{
- const int gridsize = bvh->gridkey.grid_size;
- for (int i = 0; i < bvh->totgrid; i++) {
- BLI_bitmap *gh = bvh->grid_hidden[i];
- const int face_index = BKE_subdiv_ccg_grid_to_face_index(bvh->subdiv_ccg, i);
- if (!gh && bvh->face_sets[face_index] < 0) {
- gh = bvh->grid_hidden[i] = BLI_BITMAP_NEW(bvh->gridkey.grid_area, "partialvis_update_grids");
+ const int gridsize = pbvh->gridkey.grid_size;
+ for (int i = 0; i < pbvh->totgrid; i++) {
+ BLI_bitmap *gh = pbvh->grid_hidden[i];
+ const int face_index = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, i);
+ if (!gh && pbvh->face_sets[face_index] < 0) {
+ gh = pbvh->grid_hidden[i] = BLI_BITMAP_NEW(pbvh->gridkey.grid_area,
+ "partialvis_update_grids");
}
if (gh) {
for (int y = 0; y < gridsize; y++) {
for (int x = 0; x < gridsize; x++) {
- BLI_BITMAP_SET(gh, y * gridsize + x, bvh->face_sets[face_index] < 0);
+ BLI_BITMAP_SET(gh, y * gridsize + x, pbvh->face_sets[face_index] < 0);
}
}
}
}
}
-static void build_grid_leaf_node(PBVH *bvh, PBVHNode *node)
+static void build_grid_leaf_node(PBVH *pbvh, PBVHNode *node)
{
int totquads = BKE_pbvh_count_grid_quads(
- bvh->grid_hidden, node->prim_indices, node->totprim, bvh->gridkey.grid_size);
+ pbvh->grid_hidden, node->prim_indices, node->totprim, pbvh->gridkey.grid_size);
BKE_pbvh_node_fully_hidden_set(node, (totquads == 0));
BKE_pbvh_node_mark_rebuild_draw(node);
}
-static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc, int offset, int count)
+static void build_leaf(PBVH *pbvh, int node_index, BBC *prim_bbc, int offset, int count)
{
- bvh->nodes[node_index].flag |= PBVH_Leaf;
+ pbvh->nodes[node_index].flag |= PBVH_Leaf;
- bvh->nodes[node_index].prim_indices = bvh->prim_indices + offset;
- bvh->nodes[node_index].totprim = count;
+ pbvh->nodes[node_index].prim_indices = pbvh->prim_indices + offset;
+ pbvh->nodes[node_index].totprim = count;
/* Still need vb for searches */
- update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
+ update_vb(pbvh, &pbvh->nodes[node_index], prim_bbc, offset, count);
- if (bvh->looptri) {
- build_mesh_leaf_node(bvh, bvh->nodes + node_index);
+ if (pbvh->looptri) {
+ build_mesh_leaf_node(pbvh, pbvh->nodes + node_index);
}
else {
- build_grid_leaf_node(bvh, bvh->nodes + node_index);
+ build_grid_leaf_node(pbvh, pbvh->nodes + node_index);
}
}
/* Return zero if all primitives in the node can be drawn with the
* same material (including flat/smooth shading), non-zero otherwise */
-static bool leaf_needs_material_split(PBVH *bvh, int offset, int count)
+static bool leaf_needs_material_split(PBVH *pbvh, int offset, int count)
{
if (count <= 1) {
return false;
}
- if (bvh->looptri) {
- const MLoopTri *first = &bvh->looptri[bvh->prim_indices[offset]];
- const MPoly *mp = &bvh->mpoly[first->poly];
+ if (pbvh->looptri) {
+ const MLoopTri *first = &pbvh->looptri[pbvh->prim_indices[offset]];
+ const MPoly *mp = &pbvh->mpoly[first->poly];
for (int i = offset + count - 1; i > offset; i--) {
- int prim = bvh->prim_indices[i];
- const MPoly *mp_other = &bvh->mpoly[bvh->looptri[prim].poly];
+ int prim = pbvh->prim_indices[i];
+ const MPoly *mp_other = &pbvh->mpoly[pbvh->looptri[prim].poly];
if (!face_materials_match(mp, mp_other)) {
return true;
}
}
}
else {
- const DMFlagMat *first = &bvh->grid_flag_mats[bvh->prim_indices[offset]];
+ const DMFlagMat *first = &pbvh->grid_flag_mats[pbvh->prim_indices[offset]];
for (int i = offset + count - 1; i > offset; i--) {
- int prim = bvh->prim_indices[i];
- if (!grid_materials_match(first, &bvh->grid_flag_mats[prim])) {
+ int prim = pbvh->prim_indices[i];
+ if (!grid_materials_match(first, &pbvh->grid_flag_mats[prim])) {
return true;
}
}
@@ -479,26 +480,26 @@ static bool leaf_needs_material_split(PBVH *bvh, int offset, int count)
* offset and start indicate a range in the array of primitive indices
*/
-static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, int offset, int count)
+static void build_sub(PBVH *pbvh, int node_index, BB *cb, BBC *prim_bbc, int offset, int count)
{
int end;
BB cb_backing;
/* Decide whether this is a leaf or not */
- const bool below_leaf_limit = count <= bvh->leaf_limit;
+ const bool below_leaf_limit = count <= pbvh->leaf_limit;
if (below_leaf_limit) {
- if (!leaf_needs_material_split(bvh, offset, count)) {
- build_leaf(bvh, node_index, prim_bbc, offset, count);
+ if (!leaf_needs_material_split(pbvh, offset, count)) {
+ build_leaf(pbvh, node_index, prim_bbc, offset, count);
return;
}
}
/* Add two child nodes */
- bvh->nodes[node_index].children_offset = bvh->totnode;
- pbvh_grow_nodes(bvh, bvh->totnode + 2);
+ pbvh->nodes[node_index].children_offset = pbvh->totnode;
+ pbvh_grow_nodes(pbvh, pbvh->totnode + 2);
/* Update parent node bounding box */
- update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
+ update_vb(pbvh, &pbvh->nodes[node_index], prim_bbc, offset, count);
if (!below_leaf_limit) {
/* Find axis with widest range of primitive centroids */
@@ -506,13 +507,13 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, int offs
cb = &cb_backing;
BB_reset(cb);
for (int i = offset + count - 1; i >= offset; i--) {
- BB_expand(cb, prim_bbc[bvh->prim_indices[i]].bcentroid);
+ BB_expand(cb, prim_bbc[pbvh->prim_indices[i]].bcentroid);
}
}
const int axis = BB_widest_axis(cb);
/* Partition primitives along that axis */
- end = partition_indices(bvh->prim_indices,
+ end = partition_indices(pbvh->prim_indices,
offset,
offset + count - 1,
axis,
@@ -521,38 +522,42 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, int offs
}
else {
/* Partition primitives by material */
- end = partition_indices_material(bvh, offset, offset + count - 1);
+ end = partition_indices_material(pbvh, offset, offset + count - 1);
}
/* Build children */
- build_sub(bvh, bvh->nodes[node_index].children_offset, NULL, prim_bbc, offset, end - offset);
- build_sub(
- bvh, bvh->nodes[node_index].children_offset + 1, NULL, prim_bbc, end, offset + count - end);
+ build_sub(pbvh, pbvh->nodes[node_index].children_offset, NULL, prim_bbc, offset, end - offset);
+ build_sub(pbvh,
+ pbvh->nodes[node_index].children_offset + 1,
+ NULL,
+ prim_bbc,
+ end,
+ offset + count - end);
}
-static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
+static void pbvh_build(PBVH *pbvh, BB *cb, BBC *prim_bbc, int totprim)
{
- if (totprim != bvh->totprim) {
- bvh->totprim = totprim;
- if (bvh->nodes) {
- MEM_freeN(bvh->nodes);
+ if (totprim != pbvh->totprim) {
+ pbvh->totprim = totprim;
+ if (pbvh->nodes) {
+ MEM_freeN(pbvh->nodes);
}
- if (bvh->prim_indices) {
- MEM_freeN(bvh->prim_indices);
+ if (pbvh->prim_indices) {
+ MEM_freeN(pbvh->prim_indices);
}
- bvh->prim_indices = MEM_mallocN(sizeof(int) * totprim, "bvh prim indices");
+ pbvh->prim_indices = MEM_mallocN(sizeof(int) * totprim, "bvh prim indices");
for (int i = 0; i < totprim; i++) {
- bvh->prim_indices[i] = i;
+ pbvh->prim_indices[i] = i;
}
- bvh->totnode = 0;
- if (bvh->node_mem_count < 100) {
- bvh->node_mem_count = 100;
- bvh->nodes = MEM_callocN(sizeof(PBVHNode) * bvh->node_mem_count, "bvh initial nodes");
+ pbvh->totnode = 0;
+ if (pbvh->node_mem_count < 100) {
+ pbvh->node_mem_count = 100;
+ pbvh->nodes = MEM_callocN(sizeof(PBVHNode) * pbvh->node_mem_count, "bvh initial nodes");
}
}
- bvh->totnode = 1;
- build_sub(bvh, 0, cb, prim_bbc, 0, totprim);
+ pbvh->totnode = 1;
+ build_sub(pbvh, 0, cb, prim_bbc, 0, totprim);
}
/**
@@ -561,7 +566,7 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
* \note Unlike mpoly/mloop/verts, looptri is **totally owned** by PBVH
* (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply().
*/
-void BKE_pbvh_build_mesh(PBVH *bvh,
+void BKE_pbvh_build_mesh(PBVH *pbvh,
const Mesh *mesh,
const MPoly *mpoly,
const MLoop *mloop,
@@ -576,21 +581,21 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
BBC *prim_bbc = NULL;
BB cb;
- bvh->mesh = mesh;
- bvh->type = PBVH_FACES;
- bvh->mpoly = mpoly;
- bvh->mloop = mloop;
- bvh->looptri = looptri;
- bvh->verts = verts;
- bvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
- bvh->totvert = totvert;
- bvh->leaf_limit = LEAF_LIMIT;
- bvh->vdata = vdata;
- bvh->ldata = ldata;
- bvh->pdata = pdata;
-
- bvh->face_sets_color_seed = mesh->face_sets_color_seed;
- bvh->face_sets_color_default = mesh->face_sets_color_default;
+ pbvh->mesh = mesh;
+ pbvh->type = PBVH_FACES;
+ pbvh->mpoly = mpoly;
+ pbvh->mloop = mloop;
+ pbvh->looptri = looptri;
+ pbvh->verts = verts;
+ pbvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
+ pbvh->totvert = totvert;
+ pbvh->leaf_limit = LEAF_LIMIT;
+ pbvh->vdata = vdata;
+ pbvh->ldata = ldata;
+ pbvh->pdata = pdata;
+
+ pbvh->face_sets_color_seed = mesh->face_sets_color_seed;
+ pbvh->face_sets_color_default = mesh->face_sets_color_default;
BB_reset(&cb);
@@ -605,7 +610,7 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
BB_reset((BB *)bbc);
for (int j = 0; j < sides; j++) {
- BB_expand((BB *)bbc, verts[bvh->mloop[lt->tri[j]].v].co);
+ BB_expand((BB *)bbc, verts[pbvh->mloop[lt->tri[j]].v].co);
}
BBC_update_centroid(bbc);
@@ -614,15 +619,15 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
}
if (looptri_num) {
- pbvh_build(bvh, &cb, prim_bbc, looptri_num);
+ pbvh_build(pbvh, &cb, prim_bbc, looptri_num);
}
MEM_freeN(prim_bbc);
- MEM_freeN(bvh->vert_bitmap);
+ MEM_freeN(pbvh->vert_bitmap);
}
/* Do a full rebuild with on Grids data structure */
-void BKE_pbvh_build_grids(PBVH *bvh,
+void BKE_pbvh_build_grids(PBVH *pbvh,
CCGElem **grids,
int totgrid,
CCGKey *key,
@@ -632,14 +637,14 @@ void BKE_pbvh_build_grids(PBVH *bvh,
{
const int gridsize = key->grid_size;
- bvh->type = PBVH_GRIDS;
- bvh->grids = grids;
- bvh->gridfaces = gridfaces;
- bvh->grid_flag_mats = flagmats;
- bvh->totgrid = totgrid;
- bvh->gridkey = *key;
- bvh->grid_hidden = grid_hidden;
- bvh->leaf_limit = max_ii(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1);
+ pbvh->type = PBVH_GRIDS;
+ pbvh->grids = grids;
+ pbvh->gridfaces = gridfaces;
+ pbvh->grid_flag_mats = flagmats;
+ pbvh->totgrid = totgrid;
+ pbvh->gridkey = *key;
+ pbvh->grid_hidden = grid_hidden;
+ pbvh->leaf_limit = max_ii(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1);
BB cb;
BB_reset(&cb);
@@ -663,7 +668,7 @@ void BKE_pbvh_build_grids(PBVH *bvh,
}
if (totgrid) {
- pbvh_build(bvh, &cb, prim_bbc, totgrid);
+ pbvh_build(pbvh, &cb, prim_bbc, totgrid);
}
MEM_freeN(prim_bbc);
@@ -671,15 +676,15 @@ void BKE_pbvh_build_grids(PBVH *bvh,
PBVH *BKE_pbvh_new(void)
{
- PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh");
- bvh->respect_hide = true;
- return bvh;
+ PBVH *pbvh = MEM_callocN(sizeof(PBVH), "pbvh");
+ pbvh->respect_hide = true;
+ return pbvh;
}
-void BKE_pbvh_free(PBVH *bvh)
+void BKE_pbvh_free(PBVH *pbvh)
{
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *node = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *node = &pbvh->nodes[i];
if (node->flag & PBVH_Leaf) {
if (node->draw_buffers) {
@@ -703,42 +708,42 @@ void BKE_pbvh_free(PBVH *bvh)
}
}
- if (bvh->deformed) {
- if (bvh->verts) {
+ if (pbvh->deformed) {
+ if (pbvh->verts) {
/* if pbvh was deformed, new memory was allocated for verts/faces -- free it */
- MEM_freeN((void *)bvh->verts);
+ MEM_freeN((void *)pbvh->verts);
}
}
- if (bvh->looptri) {
- MEM_freeN((void *)bvh->looptri);
+ if (pbvh->looptri) {
+ MEM_freeN((void *)pbvh->looptri);
}
- if (bvh->nodes) {
- MEM_freeN(bvh->nodes);
+ if (pbvh->nodes) {
+ MEM_freeN(pbvh->nodes);
}
- if (bvh->prim_indices) {
- MEM_freeN(bvh->prim_indices);
+ if (pbvh->prim_indices) {
+ MEM_freeN(pbvh->prim_indices);
}
- MEM_freeN(bvh);
+ MEM_freeN(pbvh);
}
static void pbvh_iter_begin(PBVHIter *iter,
- PBVH *bvh,
+ PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data)
{
- iter->bvh = bvh;
+ iter->pbvh = pbvh;
iter->scb = scb;
iter->search_data = search_data;
iter->stack = iter->stackfixed;
iter->stackspace = STACK_FIXED_DEPTH;
- iter->stack[0].node = bvh->nodes;
+ iter->stack[0].node = pbvh->nodes;
iter->stack[0].revisiting = false;
iter->stacksize = 1;
}
@@ -804,8 +809,8 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter)
pbvh_stack_push(iter, node, true);
/* push two child nodes on the stack */
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, false);
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, false);
+ pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset + 1, false);
+ pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset, false);
}
}
@@ -834,8 +839,8 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
return node;
}
else {
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, false);
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, false);
+ pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset + 1, false);
+ pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset, false);
}
}
@@ -843,13 +848,13 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
}
void BKE_pbvh_search_gather(
- PBVH *bvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***r_array, int *r_tot)
+ PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***r_array, int *r_tot)
{
PBVHIter iter;
PBVHNode **array = NULL, *node;
int tot = 0, space = 0;
- pbvh_iter_begin(&iter, bvh, scb, search_data);
+ pbvh_iter_begin(&iter, pbvh, scb, search_data);
while ((node = pbvh_iter_next(&iter))) {
if (node->flag & PBVH_Leaf) {
@@ -875,7 +880,7 @@ void BKE_pbvh_search_gather(
*r_tot = tot;
}
-void BKE_pbvh_search_callback(PBVH *bvh,
+void BKE_pbvh_search_callback(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
BKE_pbvh_HitCallback hcb,
@@ -884,7 +889,7 @@ void BKE_pbvh_search_callback(PBVH *bvh,
PBVHIter iter;
PBVHNode *node;
- pbvh_iter_begin(&iter, bvh, scb, search_data);
+ pbvh_iter_begin(&iter, pbvh, scb, search_data);
while ((node = pbvh_iter_next(&iter))) {
if (node->flag & PBVH_Leaf) {
@@ -958,7 +963,7 @@ float BKE_pbvh_node_get_tmin(PBVHNode *node)
return node->tmin;
}
-static void BKE_pbvh_search_callback_occluded(PBVH *bvh,
+static void BKE_pbvh_search_callback_occluded(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
BKE_pbvh_HitOccludedCallback hcb,
@@ -968,7 +973,7 @@ static void BKE_pbvh_search_callback_occluded(PBVH *bvh,
PBVHNode *node;
node_tree *tree = NULL;
- pbvh_iter_begin(&iter, bvh, scb, search_data);
+ pbvh_iter_begin(&iter, pbvh, scb, search_data);
while ((node = pbvh_iter_next_occluded(&iter))) {
if (node->flag & PBVH_Leaf) {
@@ -1009,7 +1014,7 @@ static bool update_search_cb(PBVHNode *node, void *data_v)
}
typedef struct PBVHUpdateData {
- PBVH *bvh;
+ PBVH *pbvh;
PBVHNode **nodes;
int totnode;
@@ -1024,7 +1029,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
float(*vnors)[3] = data->vnors;
@@ -1036,25 +1041,25 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
const int totface = node->totprim;
for (int i = 0; i < totface; i++) {
- const MLoopTri *lt = &bvh->looptri[faces[i]];
+ const MLoopTri *lt = &pbvh->looptri[faces[i]];
const unsigned int vtri[3] = {
- bvh->mloop[lt->tri[0]].v,
- bvh->mloop[lt->tri[1]].v,
- bvh->mloop[lt->tri[2]].v,
+ pbvh->mloop[lt->tri[0]].v,
+ pbvh->mloop[lt->tri[1]].v,
+ pbvh->mloop[lt->tri[2]].v,
};
const int sides = 3;
/* Face normal and mask */
if (lt->poly != mpoly_prev) {
- const MPoly *mp = &bvh->mpoly[lt->poly];
- BKE_mesh_calc_poly_normal(mp, &bvh->mloop[mp->loopstart], bvh->verts, fn);
+ const MPoly *mp = &pbvh->mpoly[lt->poly];
+ BKE_mesh_calc_poly_normal(mp, &pbvh->mloop[mp->loopstart], pbvh->verts, fn);
mpoly_prev = lt->poly;
}
for (int j = sides; j--;) {
const int v = vtri[j];
- if (bvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
+ if (pbvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
/* Note: This avoids `lock, add_v3_v3, unlock`
* and is five to ten times quicker than a spin-lock.
* Not exact equivalent though, since atomicity is only ensured for one component
@@ -1073,7 +1078,7 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
const TaskParallelTLS *__restrict UNUSED(tls))
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
float(*vnors)[3] = data->vnors;
@@ -1083,7 +1088,7 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
for (int i = 0; i < totvert; i++) {
const int v = verts[i];
- MVert *mvert = &bvh->verts[v];
+ MVert *mvert = &pbvh->verts[v];
/* No atomics necessary because we are iterating over uniq_verts only,
* so we know only this thread will handle this vertex. */
@@ -1098,11 +1103,11 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
}
}
-static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode)
+static void pbvh_faces_update_normals(PBVH *pbvh, PBVHNode **nodes, int totnode)
{
/* could be per node to save some memory, but also means
* we have to store for each vertex which node it is in */
- float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * bvh->totvert, __func__);
+ float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * pbvh->totvert, __func__);
/* subtle assumptions:
* - We know that for all edited vertices, the nodes with faces
@@ -1115,7 +1120,7 @@ static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode)
*/
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
.vnors = vnors,
};
@@ -1135,7 +1140,7 @@ static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_UpdateMask) {
@@ -1144,7 +1149,7 @@ static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
if (node->flag & PBVH_Leaf) {
PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
+ BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL)
{
if (vd.mask && *vd.mask < 1.0f) {
has_unmasked = true;
@@ -1166,10 +1171,10 @@ static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
}
}
-static void pbvh_update_mask_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
+static void pbvh_update_mask_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
{
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
.flag = flag,
};
@@ -1185,14 +1190,14 @@ static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata,
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_UpdateVisibility) {
node->flag &= ~PBVH_UpdateVisibility;
BKE_pbvh_node_fully_hidden_set(node, true);
if (node->flag & PBVH_Leaf) {
PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
+ BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL)
{
if (vd.visible) {
BKE_pbvh_node_fully_hidden_set(node, false);
@@ -1204,10 +1209,10 @@ static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata,
}
}
-static void pbvh_update_visibility_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
+static void pbvh_update_visibility_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
{
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
.flag = flag,
};
@@ -1222,14 +1227,14 @@ static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata,
const TaskParallelTLS *__restrict UNUSED(tls))
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
const int flag = data->flag;
if ((flag & PBVH_UpdateBB) && (node->flag & PBVH_UpdateBB)) {
/* don't clear flag yet, leave it for flushing later */
/* Note that bvh usage is read-only here, so no need to thread-protect it. */
- update_node_vb(bvh, node);
+ update_node_vb(pbvh, node);
}
if ((flag & PBVH_UpdateOriginalBB) && (node->flag & PBVH_UpdateOriginalBB)) {
@@ -1241,11 +1246,11 @@ static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata,
}
}
-void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
+void pbvh_update_BB_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
{
/* update BB, redraw flag */
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
.flag = flag,
};
@@ -1255,7 +1260,7 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
BLI_task_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings);
}
-static int pbvh_get_buffers_update_flags(PBVH *UNUSED(bvh))
+static int pbvh_get_buffers_update_flags(PBVH *UNUSED(pbvh))
{
int update_flags = GPU_PBVH_BUFFERS_SHOW_VCOL | GPU_PBVH_BUFFERS_SHOW_MASK |
GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS;
@@ -1270,61 +1275,61 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
* do any OpenGL calls. Flags are not cleared immediately, that happens
* after GPU_pbvh_buffer_flush() which does the final OpenGL calls. */
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_RebuildDrawBuffers) {
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_GRIDS:
- node->draw_buffers = GPU_pbvh_grid_buffers_build(node->totprim, bvh->grid_hidden);
+ node->draw_buffers = GPU_pbvh_grid_buffers_build(node->totprim, pbvh->grid_hidden);
break;
case PBVH_FACES:
node->draw_buffers = GPU_pbvh_mesh_buffers_build(
- bvh->mpoly,
- bvh->mloop,
- bvh->looptri,
- bvh->verts,
+ pbvh->mpoly,
+ pbvh->mloop,
+ pbvh->looptri,
+ pbvh->verts,
node->prim_indices,
- CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS),
+ CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS),
node->totprim,
- bvh->mesh);
+ pbvh->mesh);
break;
case PBVH_BMESH:
- node->draw_buffers = GPU_pbvh_bmesh_buffers_build(bvh->flags &
+ node->draw_buffers = GPU_pbvh_bmesh_buffers_build(pbvh->flags &
PBVH_DYNTOPO_SMOOTH_SHADING);
break;
}
}
if (node->flag & PBVH_UpdateDrawBuffers) {
- const int update_flags = pbvh_get_buffers_update_flags(bvh);
- switch (bvh->type) {
+ const int update_flags = pbvh_get_buffers_update_flags(pbvh);
+ switch (pbvh->type) {
case PBVH_GRIDS:
GPU_pbvh_grid_buffers_update(node->draw_buffers,
- bvh->subdiv_ccg,
- bvh->grids,
- bvh->grid_flag_mats,
+ pbvh->subdiv_ccg,
+ pbvh->grids,
+ pbvh->grid_flag_mats,
node->prim_indices,
node->totprim,
- bvh->face_sets,
- bvh->face_sets_color_seed,
- bvh->face_sets_color_default,
- &bvh->gridkey,
+ pbvh->face_sets,
+ pbvh->face_sets_color_seed,
+ pbvh->face_sets_color_default,
+ &pbvh->gridkey,
update_flags);
break;
case PBVH_FACES:
GPU_pbvh_mesh_buffers_update(node->draw_buffers,
- bvh->verts,
- CustomData_get_layer(bvh->vdata, CD_PAINT_MASK),
- CustomData_get_layer(bvh->ldata, CD_MLOOPCOL),
- CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS),
- bvh->face_sets_color_seed,
- bvh->face_sets_color_default,
+ pbvh->verts,
+ CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK),
+ CustomData_get_layer(pbvh->ldata, CD_MLOOPCOL),
+ CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS),
+ pbvh->face_sets_color_seed,
+ pbvh->face_sets_color_default,
update_flags);
break;
case PBVH_BMESH:
GPU_pbvh_bmesh_buffers_update(node->draw_buffers,
- bvh->bm,
+ pbvh->bm,
node->bm_faces,
node->bm_unique_verts,
node->bm_other_verts,
@@ -1334,9 +1339,9 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
}
}
-static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, int update_flag)
+static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag)
{
- if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(bvh->type, PBVH_GRIDS, PBVH_BMESH)) {
+ if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) {
/* Free buffers uses OpenGL, so not in parallel. */
for (int n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
@@ -1345,11 +1350,11 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, i
node->draw_buffers = NULL;
}
else if ((node->flag & PBVH_UpdateDrawBuffers) && node->draw_buffers) {
- if (bvh->type == PBVH_GRIDS) {
+ if (pbvh->type == PBVH_GRIDS) {
GPU_pbvh_grid_buffers_update_free(
- node->draw_buffers, bvh->grid_flag_mats, node->prim_indices);
+ node->draw_buffers, pbvh->grid_flag_mats, node->prim_indices);
}
- else if (bvh->type == PBVH_BMESH) {
+ else if (pbvh->type == PBVH_BMESH) {
GPU_pbvh_bmesh_buffers_update_free(node->draw_buffers);
}
}
@@ -1358,7 +1363,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, i
/* Parallel creation and update of draw buffers. */
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
};
@@ -1367,7 +1372,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, i
BLI_task_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings);
}
-static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
+static int pbvh_flush_bb(PBVH *pbvh, PBVHNode *node, int flag)
{
int update = 0;
@@ -1386,11 +1391,11 @@ static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
return update;
}
else {
- update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset, flag);
- update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset + 1, flag);
+ update |= pbvh_flush_bb(pbvh, pbvh->nodes + node->children_offset, flag);
+ update |= pbvh_flush_bb(pbvh, pbvh->nodes + node->children_offset + 1, flag);
if (update & PBVH_UpdateBB) {
- update_node_vb(bvh, node);
+ update_node_vb(pbvh, node);
}
if (update & PBVH_UpdateOriginalBB) {
node->orig_vb = node->vb;
@@ -1400,45 +1405,45 @@ static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
return update;
}
-void BKE_pbvh_update_bounds(PBVH *bvh, int flag)
+void BKE_pbvh_update_bounds(PBVH *pbvh, int flag)
{
- if (!bvh->nodes) {
+ if (!pbvh->nodes) {
return;
}
PBVHNode **nodes;
int totnode;
- BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw)) {
- pbvh_update_BB_redraw(bvh, nodes, totnode, flag);
+ pbvh_update_BB_redraw(pbvh, nodes, totnode, flag);
}
if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB)) {
- pbvh_flush_bb(bvh, bvh->nodes, flag);
+ pbvh_flush_bb(pbvh, pbvh->nodes, flag);
}
MEM_SAFE_FREE(nodes);
}
-void BKE_pbvh_update_vertex_data(PBVH *bvh, int flag)
+void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag)
{
- if (!bvh->nodes) {
+ if (!pbvh->nodes) {
return;
}
PBVHNode **nodes;
int totnode;
- BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
if (flag & (PBVH_UpdateMask)) {
- pbvh_update_mask_redraw(bvh, nodes, totnode, flag);
+ pbvh_update_mask_redraw(pbvh, nodes, totnode, flag);
}
if (flag & (PBVH_UpdateVisibility)) {
- pbvh_update_visibility_redraw(bvh, nodes, totnode, flag);
+ pbvh_update_visibility_redraw(pbvh, nodes, totnode, flag);
}
if (nodes) {
@@ -1446,13 +1451,13 @@ void BKE_pbvh_update_vertex_data(PBVH *bvh, int flag)
}
}
-static void pbvh_faces_node_visibility_update(PBVH *bvh, PBVHNode *node)
+static void pbvh_faces_node_visibility_update(PBVH *pbvh, PBVHNode *node)
{
MVert *mvert;
const int *vert_indices;
int totvert, i;
- BKE_pbvh_node_num_verts(bvh, node, NULL, &totvert);
- BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &mvert);
+ BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
+ BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
for (i = 0; i < totvert; i++) {
MVert *v = &mvert[vert_indices[i]];
@@ -1465,15 +1470,15 @@ static void pbvh_faces_node_visibility_update(PBVH *bvh, PBVHNode *node)
BKE_pbvh_node_fully_hidden_set(node, true);
}
-static void pbvh_grids_node_visibility_update(PBVH *bvh, PBVHNode *node)
+static void pbvh_grids_node_visibility_update(PBVH *pbvh, PBVHNode *node)
{
CCGElem **grids;
BLI_bitmap **grid_hidden;
int *grid_indices, totgrid, i;
- BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, NULL, &grids);
- grid_hidden = BKE_pbvh_grid_hidden(bvh);
- CCGKey key = *BKE_pbvh_get_grid_key(bvh);
+ BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, NULL, &grids);
+ grid_hidden = BKE_pbvh_grid_hidden(pbvh);
+ CCGKey key = *BKE_pbvh_get_grid_key(pbvh);
for (i = 0; i < totgrid; i++) {
int g = grid_indices[i], x, y;
@@ -1530,15 +1535,15 @@ static void pbvh_update_visibility_task_cb(void *__restrict userdata,
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_UpdateMask) {
- switch (BKE_pbvh_type(bvh)) {
+ switch (BKE_pbvh_type(pbvh)) {
case PBVH_FACES:
- pbvh_faces_node_visibility_update(bvh, node);
+ pbvh_faces_node_visibility_update(pbvh, node);
break;
case PBVH_GRIDS:
- pbvh_grids_node_visibility_update(bvh, node);
+ pbvh_grids_node_visibility_update(pbvh, node);
break;
case PBVH_BMESH:
pbvh_bmesh_node_visibility_update(node);
@@ -1548,10 +1553,10 @@ static void pbvh_update_visibility_task_cb(void *__restrict userdata,
}
}
-static void pbvh_update_visibility(PBVH *bvh, PBVHNode **nodes, int totnode)
+static void pbvh_update_visibility(PBVH *pbvh, PBVHNode **nodes, int totnode)
{
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
};
@@ -1560,9 +1565,9 @@ static void pbvh_update_visibility(PBVH *bvh, PBVHNode **nodes, int totnode)
BLI_task_parallel_range(0, totnode, &data, pbvh_update_visibility_task_cb, &settings);
}
-void BKE_pbvh_update_visibility(PBVH *bvh)
+void BKE_pbvh_update_visibility(PBVH *pbvh)
{
- if (!bvh->nodes) {
+ if (!pbvh->nodes) {
return;
}
@@ -1570,15 +1575,15 @@ void BKE_pbvh_update_visibility(PBVH *bvh)
int totnode;
BKE_pbvh_search_gather(
- bvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateVisibility), &nodes, &totnode);
- pbvh_update_visibility(bvh, nodes, totnode);
+ pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateVisibility), &nodes, &totnode);
+ pbvh_update_visibility(pbvh, nodes, totnode);
if (nodes) {
MEM_freeN(nodes);
}
}
-void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
+void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3])
{
PBVHIter iter;
PBVHNode *node;
@@ -1586,7 +1591,7 @@ void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
BB_reset(&bb);
- pbvh_iter_begin(&iter, bvh, NULL, NULL);
+ pbvh_iter_begin(&iter, pbvh, NULL, NULL);
while ((node = pbvh_iter_next(&iter))) {
if (node->flag & PBVH_UpdateRedraw) {
@@ -1600,18 +1605,18 @@ void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
copy_v3_v3(bb_max, bb.bmax);
}
-void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface)
+void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface)
{
GSet *face_set = BLI_gset_ptr_new(__func__);
PBVHNode *node;
PBVHIter iter;
- pbvh_iter_begin(&iter, bvh, NULL, NULL);
+ pbvh_iter_begin(&iter, pbvh, NULL, NULL);
while ((node = pbvh_iter_next(&iter))) {
if (node->flag & PBVH_UpdateNormals) {
for (uint i = 0; i < node->totprim; i++) {
- void *face = bvh->gridfaces[node->prim_indices[i]];
+ void *face = pbvh->gridfaces[node->prim_indices[i]];
BLI_gset_add(face_set, face);
}
@@ -1647,25 +1652,25 @@ void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *
/***************************** PBVH Access ***********************************/
-PBVHType BKE_pbvh_type(const PBVH *bvh)
+PBVHType BKE_pbvh_type(const PBVH *pbvh)
{
- return bvh->type;
+ return pbvh->type;
}
-bool BKE_pbvh_has_faces(const PBVH *bvh)
+bool BKE_pbvh_has_faces(const PBVH *pbvh)
{
- if (bvh->type == PBVH_BMESH) {
- return (bvh->bm->totface != 0);
+ if (pbvh->type == PBVH_BMESH) {
+ return (pbvh->bm->totface != 0);
}
else {
- return (bvh->totprim != 0);
+ return (pbvh->totprim != 0);
}
}
-void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3])
+void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3])
{
- if (bvh->totnode) {
- const BB *bb = &bvh->nodes[0].vb;
+ if (pbvh->totnode) {
+ const BB *bb = &pbvh->nodes[0].vb;
copy_v3_v3(min, bb->bmin);
copy_v3_v3(max, bb->bmax);
}
@@ -1675,34 +1680,40 @@ void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3])
}
}
-BLI_bitmap **BKE_pbvh_grid_hidden(const PBVH *bvh)
+BLI_bitmap **BKE_pbvh_grid_hidden(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_GRIDS);
- return bvh->grid_hidden;
+ BLI_assert(pbvh->type == PBVH_GRIDS);
+ return pbvh->grid_hidden;
}
-const CCGKey *BKE_pbvh_get_grid_key(const PBVH *bvh)
+const CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_GRIDS);
- return &bvh->gridkey;
+ BLI_assert(pbvh->type == PBVH_GRIDS);
+ return &pbvh->gridkey;
}
-struct CCGElem **BKE_pbvh_get_grids(const PBVH *bvh)
+struct CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_GRIDS);
- return bvh->grids;
+ BLI_assert(pbvh->type == PBVH_GRIDS);
+ return pbvh->grids;
}
-int BKE_pbvh_get_grid_num_vertices(const PBVH *bvh)
+BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_GRIDS);
- return bvh->totgrid * bvh->gridkey.grid_area;
+ BLI_assert(pbvh->type == PBVH_GRIDS);
+ return pbvh->grid_hidden;
}
-BMesh *BKE_pbvh_get_bmesh(PBVH *bvh)
+int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_BMESH);
- return bvh->bm;
+ BLI_assert(pbvh->type == PBVH_GRIDS);
+ return pbvh->totgrid * pbvh->gridkey.grid_area;
+}
+
+BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh)
+{
+ BLI_assert(pbvh->type == PBVH_BMESH);
+ return pbvh->bm;
}
/***************************** Node Access ***********************************/
@@ -1785,7 +1796,7 @@ bool BKE_pbvh_node_fully_unmasked_get(PBVHNode *node)
return (node->flag & PBVH_Leaf) && (node->flag & PBVH_FullyUnmasked);
}
-void BKE_pbvh_node_get_verts(PBVH *bvh,
+void BKE_pbvh_node_get_verts(PBVH *pbvh,
PBVHNode *node,
const int **r_vert_indices,
MVert **r_verts)
@@ -1795,17 +1806,17 @@ void BKE_pbvh_node_get_verts(PBVH *bvh,
}
if (r_verts) {
- *r_verts = bvh->verts;
+ *r_verts = pbvh->verts;
}
}
-void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *r_uniquevert, int *r_totvert)
+void BKE_pbvh_node_num_verts(PBVH *pbvh, PBVHNode *node, int *r_uniquevert, int *r_totvert)
{
int tot;
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_GRIDS:
- tot = node->totprim * bvh->gridkey.grid_area;
+ tot = node->totprim * pbvh->gridkey.grid_area;
if (r_totvert) {
*r_totvert = tot;
}
@@ -1833,7 +1844,7 @@ void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *r_uniquevert, int *
}
}
-void BKE_pbvh_node_get_grids(PBVH *bvh,
+void BKE_pbvh_node_get_grids(PBVH *pbvh,
PBVHNode *node,
int **r_grid_indices,
int *r_totgrid,
@@ -1841,7 +1852,7 @@ void BKE_pbvh_node_get_grids(PBVH *bvh,
int *r_gridsize,
CCGElem ***r_griddata)
{
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_GRIDS:
if (r_grid_indices) {
*r_grid_indices = node->prim_indices;
@@ -1850,13 +1861,13 @@ void BKE_pbvh_node_get_grids(PBVH *bvh,
*r_totgrid = node->totprim;
}
if (r_maxgrid) {
- *r_maxgrid = bvh->totgrid;
+ *r_maxgrid = pbvh->totgrid;
}
if (r_gridsize) {
- *r_gridsize = bvh->gridkey.grid_size;
+ *r_gridsize = pbvh->gridkey.grid_size;
}
if (r_griddata) {
- *r_griddata = bvh->grids;
+ *r_griddata = pbvh->grids;
}
break;
case PBVH_FACES:
@@ -1927,15 +1938,15 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
* however this is important to avoid having to recalculate bound-box & sync the buffers to the
* GPU (which is far more expensive!) See: T47232.
*/
-bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node)
+bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node)
{
- BLI_assert(bvh->type == PBVH_FACES);
+ BLI_assert(pbvh->type == PBVH_FACES);
const int *verts = node->vert_indices;
const int totvert = node->uniq_verts + node->face_verts;
for (int i = 0; i < totvert; i++) {
const int v = verts[i];
- const MVert *mvert = &bvh->verts[v];
+ const MVert *mvert = &pbvh->verts[v];
if (mvert->flag & ME_VERT_PBVH_UPDATE) {
return true;
@@ -1971,7 +1982,7 @@ static bool ray_aabb_intersect(PBVHNode *node, void *data_v)
return isect_ray_aabb_v3(&rcd->ray, bb_min, bb_max, &node->tmin);
}
-void BKE_pbvh_raycast(PBVH *bvh,
+void BKE_pbvh_raycast(PBVH *pbvh,
BKE_pbvh_HitOccludedCallback cb,
void *data,
const float ray_start[3],
@@ -1983,7 +1994,7 @@ void BKE_pbvh_raycast(PBVH *bvh,
isect_ray_aabb_v3_precalc(&rcd.ray, ray_start, ray_normal);
rcd.original = original;
- BKE_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
+ BKE_pbvh_search_callback_occluded(pbvh, ray_aabb_intersect, &rcd, cb, data);
}
bool ray_face_intersection_quad(const float ray_start[3],
@@ -2101,7 +2112,7 @@ bool ray_face_nearest_tri(const float ray_start[3],
}
}
-static bool pbvh_faces_node_raycast(PBVH *bvh,
+static bool pbvh_faces_node_raycast(PBVH *pbvh,
const PBVHNode *node,
float (*origco)[3],
const float ray_start[3],
@@ -2112,18 +2123,18 @@ static bool pbvh_faces_node_raycast(PBVH *bvh,
int *r_active_face_index,
float *r_face_normal)
{
- const MVert *vert = bvh->verts;
- const MLoop *mloop = bvh->mloop;
+ const MVert *vert = pbvh->verts;
+ const MLoop *mloop = pbvh->mloop;
const int *faces = node->prim_indices;
int totface = node->totprim;
bool hit = false;
float nearest_vertex_co[3] = {0.0f};
for (int i = 0; i < totface; i++) {
- const MLoopTri *lt = &bvh->looptri[faces[i]];
+ const MLoopTri *lt = &pbvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i];
- if (bvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
+ if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
continue;
}
@@ -2169,7 +2180,7 @@ static bool pbvh_faces_node_raycast(PBVH *bvh,
return hit;
}
-static bool pbvh_grids_node_raycast(PBVH *bvh,
+static bool pbvh_grids_node_raycast(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
const float ray_start[3],
@@ -2181,21 +2192,21 @@ static bool pbvh_grids_node_raycast(PBVH *bvh,
float *r_face_normal)
{
const int totgrid = node->totprim;
- const int gridsize = bvh->gridkey.grid_size;
+ const int gridsize = pbvh->gridkey.grid_size;
bool hit = false;
float nearest_vertex_co[3] = {0.0};
- const CCGKey *gridkey = &bvh->gridkey;
+ const CCGKey *gridkey = &pbvh->gridkey;
for (int i = 0; i < totgrid; i++) {
const int grid_index = node->prim_indices[i];
- CCGElem *grid = bvh->grids[grid_index];
+ CCGElem *grid = pbvh->grids[grid_index];
BLI_bitmap *gh;
if (!grid) {
continue;
}
- gh = bvh->grid_hidden[grid_index];
+ gh = pbvh->grid_hidden[grid_index];
for (int y = 0; y < gridsize - 1; y++) {
for (int x = 0; x < gridsize - 1; x++) {
@@ -2263,7 +2274,7 @@ static bool pbvh_grids_node_raycast(PBVH *bvh,
return hit;
}
-bool BKE_pbvh_node_raycast(PBVH *bvh,
+bool BKE_pbvh_node_raycast(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
@@ -2281,9 +2292,9 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
return false;
}
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_FACES:
- hit |= pbvh_faces_node_raycast(bvh,
+ hit |= pbvh_faces_node_raycast(pbvh,
node,
origco,
ray_start,
@@ -2295,7 +2306,7 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
face_normal);
break;
case PBVH_GRIDS:
- hit |= pbvh_grids_node_raycast(bvh,
+ hit |= pbvh_grids_node_raycast(pbvh,
node,
origco,
ray_start,
@@ -2307,7 +2318,7 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
face_normal);
break;
case PBVH_BMESH:
- BM_mesh_elem_index_ensure(bvh->bm, BM_VERT);
+ BM_mesh_elem_index_ensure(pbvh->bm, BM_VERT);
hit = pbvh_bmesh_node_raycast(node,
ray_start,
ray_normal,
@@ -2323,9 +2334,9 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
}
void BKE_pbvh_raycast_project_ray_root(
- PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3])
+ PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3])
{
- if (bvh->nodes) {
+ if (pbvh->nodes) {
float rootmin_start, rootmin_end;
float bb_min_root[3], bb_max_root[3], bb_center[3], bb_diff[3];
struct IsectRayAABB_Precalc ray;
@@ -2334,10 +2345,10 @@ void BKE_pbvh_raycast_project_ray_root(
float offset_vec[3] = {1e-3f, 1e-3f, 1e-3f};
if (original) {
- BKE_pbvh_node_get_original_BB(bvh->nodes, bb_min_root, bb_max_root);
+ BKE_pbvh_node_get_original_BB(pbvh->nodes, bb_min_root, bb_max_root);
}
else {
- BKE_pbvh_node_get_BB(bvh->nodes, bb_min_root, bb_max_root);
+ BKE_pbvh_node_get_BB(pbvh->nodes, bb_min_root, bb_max_root);
}
/* Slightly offset min and max in case we have a zero width node
@@ -2399,7 +2410,7 @@ static bool nearest_to_ray_aabb_dist_sq(PBVHNode *node, void *data_v)
return depth > 0.0f;
}
-void BKE_pbvh_find_nearest_to_ray(PBVH *bvh,
+void BKE_pbvh_find_nearest_to_ray(PBVH *pbvh,
BKE_pbvh_SearchNearestCallback cb,
void *data,
const float ray_start[3],
@@ -2411,10 +2422,10 @@ void BKE_pbvh_find_nearest_to_ray(PBVH *bvh,
dist_squared_ray_to_aabb_v3_precalc(&ncd.dist_ray_to_aabb_precalc, ray_start, ray_normal);
ncd.original = original;
- BKE_pbvh_search_callback_occluded(bvh, nearest_to_ray_aabb_dist_sq, &ncd, cb, data);
+ BKE_pbvh_search_callback_occluded(pbvh, nearest_to_ray_aabb_dist_sq, &ncd, cb, data);
}
-static bool pbvh_faces_node_nearest_to_ray(PBVH *bvh,
+static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
const PBVHNode *node,
float (*origco)[3],
const float ray_start[3],
@@ -2422,17 +2433,17 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *bvh,
float *depth,
float *dist_sq)
{
- const MVert *vert = bvh->verts;
- const MLoop *mloop = bvh->mloop;
+ const MVert *vert = pbvh->verts;
+ const MLoop *mloop = pbvh->mloop;
const int *faces = node->prim_indices;
int i, totface = node->totprim;
bool hit = false;
for (i = 0; i < totface; i++) {
- const MLoopTri *lt = &bvh->looptri[faces[i]];
+ const MLoopTri *lt = &pbvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i];
- if (bvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
+ if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
continue;
}
@@ -2461,7 +2472,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *bvh,
return hit;
}
-static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh,
+static bool pbvh_grids_node_nearest_to_ray(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
const float ray_start[3],
@@ -2470,18 +2481,18 @@ static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh,
float *dist_sq)
{
const int totgrid = node->totprim;
- const int gridsize = bvh->gridkey.grid_size;
+ const int gridsize = pbvh->gridkey.grid_size;
bool hit = false;
for (int i = 0; i < totgrid; i++) {
- CCGElem *grid = bvh->grids[node->prim_indices[i]];
+ CCGElem *grid = pbvh->grids[node->prim_indices[i]];
BLI_bitmap *gh;
if (!grid) {
continue;
}
- gh = bvh->grid_hidden[node->prim_indices[i]];
+ gh = pbvh->grid_hidden[node->prim_indices[i]];
for (int y = 0; y < gridsize - 1; y++) {
for (int x = 0; x < gridsize - 1; x++) {
@@ -2505,10 +2516,10 @@ static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh,
else {
hit |= ray_face_nearest_quad(ray_start,
ray_normal,
- CCG_grid_elem_co(&bvh->gridkey, grid, x, y),
- CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y),
- CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1),
- CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1),
+ CCG_grid_elem_co(&pbvh->gridkey, grid, x, y),
+ CCG_grid_elem_co(&pbvh->gridkey, grid, x + 1, y),
+ CCG_grid_elem_co(&pbvh->gridkey, grid, x + 1, y + 1),
+ CCG_grid_elem_co(&pbvh->gridkey, grid, x, y + 1),
depth,
dist_sq);
}
@@ -2523,7 +2534,7 @@ static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh,
return hit;
}
-bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
+bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
@@ -2538,14 +2549,14 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
return false;
}
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_FACES:
hit |= pbvh_faces_node_nearest_to_ray(
- bvh, node, origco, ray_start, ray_normal, depth, dist_sq);
+ pbvh, node, origco, ray_start, ray_normal, depth, dist_sq);
break;
case PBVH_GRIDS:
hit |= pbvh_grids_node_nearest_to_ray(
- bvh, node, origco, ray_start, ray_normal, depth, dist_sq);
+ pbvh, node, origco, ray_start, ray_normal, depth, dist_sq);
break;
case PBVH_BMESH:
hit = pbvh_bmesh_node_nearest_to_ray(
@@ -2619,26 +2630,26 @@ bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *data)
return test_frustum_aabb(bb_min, bb_max, data) != ISECT_INSIDE;
}
-void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg)
+void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg)
{
/* Update normals */
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(
- bvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals), &nodes, &totnode);
+ pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals), &nodes, &totnode);
if (totnode > 0) {
- if (bvh->type == PBVH_BMESH) {
+ if (pbvh->type == PBVH_BMESH) {
pbvh_bmesh_normals_update(nodes, totnode);
}
- else if (bvh->type == PBVH_FACES) {
- pbvh_faces_update_normals(bvh, nodes, totnode);
+ else if (pbvh->type == PBVH_FACES) {
+ pbvh_faces_update_normals(pbvh, nodes, totnode);
}
- else if (bvh->type == PBVH_GRIDS) {
+ else if (pbvh->type == PBVH_GRIDS) {
struct CCGFace **faces;
int num_faces;
- BKE_pbvh_get_grid_updates(bvh, true, (void ***)&faces, &num_faces);
+ BKE_pbvh_get_grid_updates(pbvh, true, (void ***)&faces, &num_faces);
if (num_faces > 0) {
BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces);
MEM_freeN(faces);
@@ -2649,10 +2660,10 @@ void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg)
MEM_SAFE_FREE(nodes);
}
-void BKE_pbvh_face_sets_color_set(PBVH *bvh, int seed, int color_default)
+void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default)
{
- bvh->face_sets_color_seed = seed;
- bvh->face_sets_color_default = color_default;
+ pbvh->face_sets_color_seed = seed;
+ pbvh->face_sets_color_default = color_default;
}
/**
@@ -2675,7 +2686,7 @@ static bool pbvh_draw_search_cb(PBVHNode *node, void *data_v)
return true;
}
-void BKE_pbvh_draw_cb(PBVH *bvh,
+void BKE_pbvh_draw_cb(PBVH *pbvh,
bool update_only_visible,
PBVHFrustumPlanes *update_frustum,
PBVHFrustumPlanes *draw_frustum,
@@ -2689,10 +2700,11 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
if (!update_only_visible) {
/* Update all draw buffers, also those outside the view. */
- BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(update_flag), &nodes, &totnode);
+ BKE_pbvh_search_gather(
+ pbvh, update_search_cb, POINTER_FROM_INT(update_flag), &nodes, &totnode);
if (totnode) {
- pbvh_update_draw_buffers(bvh, nodes, totnode, update_flag);
+ pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag);
}
MEM_SAFE_FREE(nodes);
@@ -2700,11 +2712,11 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
/* Gather visible nodes. */
PBVHDrawSearchData data = {.frustum = update_frustum, .accum_update_flag = 0};
- BKE_pbvh_search_gather(bvh, pbvh_draw_search_cb, &data, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, pbvh_draw_search_cb, &data, &nodes, &totnode);
if (update_only_visible && (data.accum_update_flag & update_flag)) {
/* Update draw buffers in visible nodes. */
- pbvh_update_draw_buffers(bvh, nodes, totnode, data.accum_update_flag);
+ pbvh_update_draw_buffers(pbvh, nodes, totnode, data.accum_update_flag);
}
/* Draw. */
@@ -2722,7 +2734,7 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
MEM_SAFE_FREE(nodes);
PBVHDrawSearchData draw_data = {.frustum = draw_frustum, .accum_update_flag = 0};
- BKE_pbvh_search_gather(bvh, pbvh_draw_search_cb, &draw_data, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, pbvh_draw_search_cb, &draw_data, &nodes, &totnode);
for (int a = 0; a < totnode; a++) {
PBVHNode *node = nodes[a];
@@ -2735,29 +2747,29 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
}
void BKE_pbvh_draw_debug_cb(
- PBVH *bvh,
+ PBVH *pbvh,
void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag),
void *user_data)
{
- for (int a = 0; a < bvh->totnode; a++) {
- PBVHNode *node = &bvh->nodes[a];
+ for (int a = 0; a < pbvh->totnode; a++) {
+ PBVHNode *node = &pbvh->nodes[a];
draw_fn(user_data, node->vb.bmin, node->vb.bmax, node->flag);
}
}
void BKE_pbvh_grids_update(
- PBVH *bvh, CCGElem **grids, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
+ PBVH *pbvh, CCGElem **grids, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
{
- bvh->grids = grids;
- bvh->gridfaces = gridfaces;
+ pbvh->grids = grids;
+ pbvh->gridfaces = gridfaces;
- if (flagmats != bvh->grid_flag_mats || bvh->grid_hidden != grid_hidden) {
- bvh->grid_flag_mats = flagmats;
- bvh->grid_hidden = grid_hidden;
+ if (flagmats != pbvh->grid_flag_mats || pbvh->grid_hidden != grid_hidden) {
+ pbvh->grid_flag_mats = flagmats;
+ pbvh->grid_hidden = grid_hidden;
- for (int a = 0; a < bvh->totnode; a++) {
- BKE_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]);
+ for (int a = 0; a < pbvh->totnode; a++) {
+ BKE_pbvh_node_mark_rebuild_draw(&pbvh->nodes[a]);
}
}
}
@@ -2830,7 +2842,7 @@ bool BKE_pbvh_is_deformed(PBVH *pbvh)
}
/* Proxies */
-PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
+PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node)
{
int index, totverts;
@@ -2845,7 +2857,7 @@ PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
node->proxies = MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy");
}
- BKE_pbvh_node_num_verts(bvh, node, &totverts, NULL);
+ BKE_pbvh_node_num_verts(pbvh, node, &totverts, NULL);
node->proxies[index].co = MEM_callocN(sizeof(float[3]) * totverts, "PBVHNodeProxy.co");
return node->proxies + index;
@@ -2893,7 +2905,7 @@ void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot)
*r_tot = tot;
}
-void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mode)
+void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode)
{
struct CCGElem **grids;
struct MVert *verts;
@@ -2906,16 +2918,16 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo
vi->fno = NULL;
vi->mvert = NULL;
- vi->respect_hide = bvh->respect_hide;
- if (bvh->respect_hide == false) {
+ vi->respect_hide = pbvh->respect_hide;
+ if (pbvh->respect_hide == false) {
/* The same value for all vertices. */
vi->visible = true;
}
- BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids);
- BKE_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert);
- BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &verts);
- vi->key = bvh->gridkey;
+ BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids);
+ BKE_pbvh_node_num_verts(pbvh, node, &uniq_verts, &totvert);
+ BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &verts);
+ vi->key = pbvh->gridkey;
vi->grids = grids;
vi->grid_indices = grid_indices;
@@ -2931,45 +2943,45 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo
vi->vert_indices = vert_indices;
vi->mverts = verts;
- if (bvh->type == PBVH_BMESH) {
+ if (pbvh->type == PBVH_BMESH) {
BLI_gsetIterator_init(&vi->bm_unique_verts, node->bm_unique_verts);
BLI_gsetIterator_init(&vi->bm_other_verts, node->bm_other_verts);
- vi->bm_vdata = &bvh->bm->vdata;
+ vi->bm_vdata = &pbvh->bm->vdata;
vi->cd_vert_mask_offset = CustomData_get_offset(vi->bm_vdata, CD_PAINT_MASK);
}
vi->gh = NULL;
if (vi->grids && mode == PBVH_ITER_UNIQUE) {
- vi->grid_hidden = bvh->grid_hidden;
+ vi->grid_hidden = pbvh->grid_hidden;
}
vi->mask = NULL;
- if (bvh->type == PBVH_FACES) {
- vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK);
+ if (pbvh->type == PBVH_FACES) {
+ vi->vmask = CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK);
}
}
-bool pbvh_has_mask(PBVH *bvh)
+bool pbvh_has_mask(PBVH *pbvh)
{
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_GRIDS:
- return (bvh->gridkey.has_mask != 0);
+ return (pbvh->gridkey.has_mask != 0);
case PBVH_FACES:
- return (bvh->vdata && CustomData_get_layer(bvh->vdata, CD_PAINT_MASK));
+ return (pbvh->vdata && CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK));
case PBVH_BMESH:
- return (bvh->bm && (CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK) != -1));
+ return (pbvh->bm && (CustomData_get_offset(&pbvh->bm->vdata, CD_PAINT_MASK) != -1));
}
return false;
}
-bool pbvh_has_face_sets(PBVH *bvh)
+bool pbvh_has_face_sets(PBVH *pbvh)
{
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_GRIDS:
- return (bvh->pdata && CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS));
+ return (pbvh->pdata && CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS));
case PBVH_FACES:
- return (bvh->pdata && CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS));
+ return (pbvh->pdata && CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS));
case PBVH_BMESH:
return false;
}
@@ -2977,29 +2989,29 @@ bool pbvh_has_face_sets(PBVH *bvh)
return false;
}
-void pbvh_show_mask_set(PBVH *bvh, bool show_mask)
+void pbvh_show_mask_set(PBVH *pbvh, bool show_mask)
{
- bvh->show_mask = show_mask;
+ pbvh->show_mask = show_mask;
}
-void pbvh_show_face_sets_set(PBVH *bvh, bool show_face_sets)
+void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets)
{
- bvh->show_face_sets = show_face_sets;
+ pbvh->show_face_sets = show_face_sets;
}
-void BKE_pbvh_set_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes)
+void BKE_pbvh_set_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes)
{
- bvh->num_planes = planes->num_planes;
- for (int i = 0; i < bvh->num_planes; i++) {
- copy_v4_v4(bvh->planes[i], planes->planes[i]);
+ pbvh->num_planes = planes->num_planes;
+ for (int i = 0; i < pbvh->num_planes; i++) {
+ copy_v4_v4(pbvh->planes[i], planes->planes[i]);
}
}
-void BKE_pbvh_get_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes)
+void BKE_pbvh_get_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes)
{
- planes->num_planes = bvh->num_planes;
+ planes->num_planes = pbvh->num_planes;
for (int i = 0; i < planes->num_planes; i++) {
- copy_v4_v4(planes->planes[i], bvh->planes[i]);
+ copy_v4_v4(planes->planes[i], pbvh->planes[i]);
}
}
@@ -3011,23 +3023,23 @@ void BKE_pbvh_parallel_range_settings(TaskParallelSettings *settings,
settings->use_threading = use_threading && totnode > 1;
}
-MVert *BKE_pbvh_get_verts(const PBVH *bvh)
+MVert *BKE_pbvh_get_verts(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_FACES);
- return bvh->verts;
+ BLI_assert(pbvh->type == PBVH_FACES);
+ return pbvh->verts;
}
-void BKE_pbvh_subdiv_cgg_set(PBVH *bvh, SubdivCCG *subdiv_ccg)
+void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg)
{
- bvh->subdiv_ccg = subdiv_ccg;
+ pbvh->subdiv_ccg = subdiv_ccg;
}
-void BKE_pbvh_face_sets_set(PBVH *bvh, int *face_sets)
+void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets)
{
- bvh->face_sets = face_sets;
+ pbvh->face_sets = face_sets;
}
-void BKE_pbvh_respect_hide_set(PBVH *bvh, bool respect_hide)
+void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide)
{
- bvh->respect_hide = respect_hide;
+ pbvh->respect_hide = respect_hide;
}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 73042222436..e87c7c8d46d 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -62,7 +62,7 @@
// #define USE_VERIFY
#ifdef USE_VERIFY
-static void pbvh_bmesh_verify(PBVH *bvh);
+static void pbvh_bmesh_verify(PBVH *pbvh);
#endif
/** \name BMesh Utility API
@@ -200,13 +200,13 @@ static BMVert *bm_vert_hash_lookup_chain(GHash *deleted_verts, BMVert *v)
/****************************** Building ******************************/
/* Update node data after splitting */
-static void pbvh_bmesh_node_finalize(PBVH *bvh,
+static void pbvh_bmesh_node_finalize(PBVH *pbvh,
const int node_index,
const int cd_vert_node_offset,
const int cd_face_node_offset)
{
GSetIterator gs_iter;
- PBVHNode *n = &bvh->nodes[node_index];
+ PBVHNode *n = &pbvh->nodes[node_index];
bool has_visible = false;
/* Create vert hash sets */
@@ -258,15 +258,15 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh,
}
/* Recursively split the node if it exceeds the leaf_limit */
-static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_index)
+static void pbvh_bmesh_node_split(PBVH *pbvh, const BBC *bbc_array, int node_index)
{
- const int cd_vert_node_offset = bvh->cd_vert_node_offset;
- const int cd_face_node_offset = bvh->cd_face_node_offset;
- PBVHNode *n = &bvh->nodes[node_index];
+ const int cd_vert_node_offset = pbvh->cd_vert_node_offset;
+ const int cd_face_node_offset = pbvh->cd_face_node_offset;
+ PBVHNode *n = &pbvh->nodes[node_index];
- if (BLI_gset_len(n->bm_faces) <= bvh->leaf_limit) {
+ if (BLI_gset_len(n->bm_faces) <= pbvh->leaf_limit) {
/* Node limit not exceeded */
- pbvh_bmesh_node_finalize(bvh, node_index, cd_vert_node_offset, cd_face_node_offset);
+ pbvh_bmesh_node_finalize(pbvh, node_index, cd_vert_node_offset, cd_face_node_offset);
return;
}
@@ -286,15 +286,15 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
const float mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f;
/* Add two new child nodes */
- const int children = bvh->totnode;
+ const int children = pbvh->totnode;
n->children_offset = children;
- pbvh_grow_nodes(bvh, bvh->totnode + 2);
+ pbvh_grow_nodes(pbvh, pbvh->totnode + 2);
/* Array reallocated, update current node pointer */
- n = &bvh->nodes[node_index];
+ n = &pbvh->nodes[node_index];
/* Initialize children */
- PBVHNode *c1 = &bvh->nodes[children], *c2 = &bvh->nodes[children + 1];
+ PBVHNode *c1 = &pbvh->nodes[children], *c2 = &pbvh->nodes[children + 1];
c1->flag |= PBVH_Leaf;
c2->flag |= PBVH_Leaf;
c1->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_len(n->bm_faces) / 2);
@@ -370,25 +370,25 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
n->flag &= ~PBVH_Leaf;
/* Recurse */
- pbvh_bmesh_node_split(bvh, bbc_array, children);
- pbvh_bmesh_node_split(bvh, bbc_array, children + 1);
+ pbvh_bmesh_node_split(pbvh, bbc_array, children);
+ pbvh_bmesh_node_split(pbvh, bbc_array, children + 1);
/* Array maybe reallocated, update current node pointer */
- n = &bvh->nodes[node_index];
+ n = &pbvh->nodes[node_index];
/* Update bounding box */
BB_reset(&n->vb);
- BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset].vb);
- BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset + 1].vb);
+ BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset].vb);
+ BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset + 1].vb);
n->orig_vb = n->vb;
}
/* Recursively split the node if it exceeds the leaf_limit */
-static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
+static bool pbvh_bmesh_node_limit_ensure(PBVH *pbvh, int node_index)
{
- GSet *bm_faces = bvh->nodes[node_index].bm_faces;
+ GSet *bm_faces = pbvh->nodes[node_index].bm_faces;
const int bm_faces_size = BLI_gset_len(bm_faces);
- if (bm_faces_size <= bvh->leaf_limit) {
+ if (bm_faces_size <= pbvh->leaf_limit) {
/* Node limit not exceeded */
return false;
}
@@ -414,9 +414,9 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
BM_elem_index_set(f, i); /* set_dirty! */
}
/* Likely this is already dirty. */
- bvh->bm->elem_index_dirty |= BM_FACE;
+ pbvh->bm->elem_index_dirty |= BM_FACE;
- pbvh_bmesh_node_split(bvh, bbc_array, node_index);
+ pbvh_bmesh_node_split(pbvh, bbc_array, node_index);
MEM_freeN(bbc_array);
@@ -426,88 +426,91 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
/**********************************************************************/
#if 0
-static int pbvh_bmesh_node_offset_from_elem(PBVH *bvh, BMElem *ele)
+static int pbvh_bmesh_node_offset_from_elem(PBVH *pbvh, BMElem *ele)
{
switch (ele->head.htype) {
case BM_VERT:
- return bvh->cd_vert_node_offset;
+ return pbvh->cd_vert_node_offset;
default:
BLI_assert(ele->head.htype == BM_FACE);
- return bvh->cd_face_node_offset;
+ return pbvh->cd_face_node_offset;
}
}
-static int pbvh_bmesh_node_index_from_elem(PBVH *bvh, void *key)
+static int pbvh_bmesh_node_index_from_elem(PBVH *pbvh, void *key)
{
- const int cd_node_offset = pbvh_bmesh_node_offset_from_elem(bvh, key);
+ const int cd_node_offset = pbvh_bmesh_node_offset_from_elem(pbvh, key);
const int node_index = BM_ELEM_CD_GET_INT((BMElem *)key, cd_node_offset);
BLI_assert(node_index != DYNTOPO_NODE_NONE);
- BLI_assert(node_index < bvh->totnode);
- (void)bvh;
+ BLI_assert(node_index < pbvh->totnode);
+ (void)pbvh;
return node_index;
}
-static PBVHNode *pbvh_bmesh_node_from_elem(PBVH *bvh, void *key)
+static PBVHNode *pbvh_bmesh_node_from_elem(PBVH *pbvh, void *key)
{
- return &bvh->nodes[pbvh_bmesh_node_index_from_elem(bvh, key)];
+ return &pbvh->nodes[pbvh_bmesh_node_index_from_elem(pbvh, key)];
}
/* typecheck */
-# define pbvh_bmesh_node_index_from_elem(bvh, key) \
- (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_index_from_elem(bvh, key))
-# define pbvh_bmesh_node_from_elem(bvh, key) \
- (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_from_elem(bvh, key))
+# define pbvh_bmesh_node_index_from_elem(pbvh, key) \
+ (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_index_from_elem(pbvh, key))
+# define pbvh_bmesh_node_from_elem(pbvh, key) \
+ (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_from_elem(pbvh, key))
#endif
-BLI_INLINE int pbvh_bmesh_node_index_from_vert(PBVH *bvh, const BMVert *key)
+BLI_INLINE int pbvh_bmesh_node_index_from_vert(PBVH *pbvh, const BMVert *key)
{
- const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, bvh->cd_vert_node_offset);
+ const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, pbvh->cd_vert_node_offset);
BLI_assert(node_index != DYNTOPO_NODE_NONE);
- BLI_assert(node_index < bvh->totnode);
+ BLI_assert(node_index < pbvh->totnode);
return node_index;
}
-BLI_INLINE int pbvh_bmesh_node_index_from_face(PBVH *bvh, const BMFace *key)
+BLI_INLINE int pbvh_bmesh_node_index_from_face(PBVH *pbvh, const BMFace *key)
{
- const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, bvh->cd_face_node_offset);
+ const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, pbvh->cd_face_node_offset);
BLI_assert(node_index != DYNTOPO_NODE_NONE);
- BLI_assert(node_index < bvh->totnode);
+ BLI_assert(node_index < pbvh->totnode);
return node_index;
}
-BLI_INLINE PBVHNode *pbvh_bmesh_node_from_vert(PBVH *bvh, const BMVert *key)
+BLI_INLINE PBVHNode *pbvh_bmesh_node_from_vert(PBVH *pbvh, const BMVert *key)
{
- return &bvh->nodes[pbvh_bmesh_node_index_from_vert(bvh, key)];
+ return &pbvh->nodes[pbvh_bmesh_node_index_from_vert(pbvh, key)];
}
-BLI_INLINE PBVHNode *pbvh_bmesh_node_from_face(PBVH *bvh, const BMFace *key)
+BLI_INLINE PBVHNode *pbvh_bmesh_node_from_face(PBVH *pbvh, const BMFace *key)
{
- return &bvh->nodes[pbvh_bmesh_node_index_from_face(bvh, key)];
+ return &pbvh->nodes[pbvh_bmesh_node_index_from_face(pbvh, key)];
}
-static BMVert *pbvh_bmesh_vert_create(
- PBVH *bvh, int node_index, const float co[3], const float no[3], const int cd_vert_mask_offset)
+static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
+ int node_index,
+ const float co[3],
+ const float no[3],
+ const int cd_vert_mask_offset)
{
- PBVHNode *node = &bvh->nodes[node_index];
+ PBVHNode *node = &pbvh->nodes[node_index];
- BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode);
+ BLI_assert((pbvh->totnode == 1 || node_index) && node_index <= pbvh->totnode);
/* avoid initializing customdata because its quite involved */
- BMVert *v = BM_vert_create(bvh->bm, co, NULL, BM_CREATE_SKIP_CD);
- CustomData_bmesh_set_default(&bvh->bm->vdata, &v->head.data);
+ BMVert *v = BM_vert_create(pbvh->bm, co, NULL, BM_CREATE_SKIP_CD);
+ CustomData_bmesh_set_default(&pbvh->bm->vdata, &v->head.data);
/* This value is logged below */
copy_v3_v3(v->no, no);
BLI_gset_insert(node->bm_unique_verts, v);
- BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, node_index);
+ BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, node_index);
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
/* Log the new vertex */
- BM_log_vert_added(bvh->bm_log, v, cd_vert_mask_offset);
+ BM_log_vert_added(pbvh->bm_log, v, cd_vert_mask_offset);
return v;
}
@@ -516,38 +519,38 @@ static BMVert *pbvh_bmesh_vert_create(
* \note Callers are responsible for checking if the face exists before adding.
*/
static BMFace *pbvh_bmesh_face_create(
- PBVH *bvh, int node_index, BMVert *v_tri[3], BMEdge *e_tri[3], const BMFace *f_example)
+ PBVH *pbvh, int node_index, BMVert *v_tri[3], BMEdge *e_tri[3], const BMFace *f_example)
{
- PBVHNode *node = &bvh->nodes[node_index];
+ PBVHNode *node = &pbvh->nodes[node_index];
/* ensure we never add existing face */
BLI_assert(!BM_face_exists(v_tri, 3));
- BMFace *f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP);
+ BMFace *f = BM_face_create(pbvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP);
f->head.hflag = f_example->head.hflag;
BLI_gset_insert(node->bm_faces, f);
- BM_ELEM_CD_SET_INT(f, bvh->cd_face_node_offset, node_index);
+ BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, node_index);
/* mark node for update */
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
node->flag &= ~PBVH_FullyHidden;
/* Log the new face */
- BM_log_face_added(bvh->bm_log, f);
+ BM_log_face_added(pbvh->bm_log, f);
return f;
}
/* Return the number of faces in 'node' that use vertex 'v' */
#if 0
-static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v)
+static int pbvh_bmesh_node_vert_use_count(PBVH *pbvh, PBVHNode *node, BMVert *v)
{
BMFace *f;
int count = 0;
BM_FACES_OF_VERT_ITER_BEGIN (f, v) {
- PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f);
if (f_node == node) {
count++;
}
@@ -558,10 +561,10 @@ static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v)
}
#endif
-#define pbvh_bmesh_node_vert_use_count_is_equal(bvh, node, v, n) \
- (pbvh_bmesh_node_vert_use_count_at_most(bvh, node, v, (n) + 1) == n)
+#define pbvh_bmesh_node_vert_use_count_is_equal(pbvh, node, v, n) \
+ (pbvh_bmesh_node_vert_use_count_at_most(pbvh, node, v, (n) + 1) == n)
-static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *bvh,
+static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *pbvh,
PBVHNode *node,
BMVert *v,
const int count_max)
@@ -570,7 +573,7 @@ static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *bvh,
BMFace *f;
BM_FACES_OF_VERT_ITER_BEGIN (f, v) {
- PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f);
if (f_node == node) {
count++;
if (count == count_max) {
@@ -584,13 +587,13 @@ static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *bvh,
}
/* Return a node that uses vertex 'v' other than its current owner */
-static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v)
+static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *pbvh, BMVert *v)
{
- PBVHNode *current_node = pbvh_bmesh_node_from_vert(bvh, v);
+ PBVHNode *current_node = pbvh_bmesh_node_from_vert(pbvh, v);
BMFace *f;
BM_FACES_OF_VERT_ITER_BEGIN (f, v) {
- PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f);
if (f_node != current_node) {
return f_node;
@@ -601,9 +604,9 @@ static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v)
return NULL;
}
-static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, BMVert *v)
+static void pbvh_bmesh_vert_ownership_transfer(PBVH *pbvh, PBVHNode *new_owner, BMVert *v)
{
- PBVHNode *current_owner = pbvh_bmesh_node_from_vert(bvh, v);
+ PBVHNode *current_owner = pbvh_bmesh_node_from_vert(pbvh, v);
/* mark node for update */
current_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
@@ -613,7 +616,7 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, B
BLI_gset_remove(current_owner->bm_unique_verts, v, NULL);
/* Set new ownership */
- BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, new_owner - bvh->nodes);
+ BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, new_owner - pbvh->nodes);
BLI_gset_insert(new_owner->bm_unique_verts, v);
BLI_gset_remove(new_owner->bm_other_verts, v, NULL);
BLI_assert(!BLI_gset_haskey(new_owner->bm_other_verts, v));
@@ -622,26 +625,26 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, B
new_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
}
-static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
+static void pbvh_bmesh_vert_remove(PBVH *pbvh, BMVert *v)
{
/* never match for first time */
int f_node_index_prev = DYNTOPO_NODE_NONE;
- PBVHNode *v_node = pbvh_bmesh_node_from_vert(bvh, v);
+ PBVHNode *v_node = pbvh_bmesh_node_from_vert(pbvh, v);
BLI_gset_remove(v_node->bm_unique_verts, v, NULL);
- BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
+ BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
/* Have to check each neighboring face's node */
BMFace *f;
BM_FACES_OF_VERT_ITER_BEGIN (f, v) {
- const int f_node_index = pbvh_bmesh_node_index_from_face(bvh, f);
+ const int f_node_index = pbvh_bmesh_node_index_from_face(pbvh, f);
/* faces often share the same node,
* quick check to avoid redundant #BLI_gset_remove calls */
if (f_node_index_prev != f_node_index) {
f_node_index_prev = f_node_index;
- PBVHNode *f_node = &bvh->nodes[f_node_index];
+ PBVHNode *f_node = &pbvh->nodes[f_node_index];
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
/* Remove current ownership */
@@ -654,9 +657,9 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
BM_FACES_OF_VERT_ITER_END;
}
-static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
+static void pbvh_bmesh_face_remove(PBVH *pbvh, BMFace *f)
{
- PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f);
/* Check if any of this face's vertices need to be removed
* from the node */
@@ -664,16 +667,16 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
BMLoop *l_iter = l_first;
do {
BMVert *v = l_iter->v;
- if (pbvh_bmesh_node_vert_use_count_is_equal(bvh, f_node, v, 1)) {
+ if (pbvh_bmesh_node_vert_use_count_is_equal(pbvh, f_node, v, 1)) {
if (BLI_gset_haskey(f_node->bm_unique_verts, v)) {
/* Find a different node that uses 'v' */
PBVHNode *new_node;
- new_node = pbvh_bmesh_vert_other_node_find(bvh, v);
+ new_node = pbvh_bmesh_vert_other_node_find(pbvh, v);
BLI_assert(new_node || BM_vert_face_count_is_equal(v, 1));
if (new_node) {
- pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v);
+ pbvh_bmesh_vert_ownership_transfer(pbvh, new_node, v);
}
}
else {
@@ -685,10 +688,10 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
/* Remove face from node and top level */
BLI_gset_remove(f_node->bm_faces, f, NULL);
- BM_ELEM_CD_SET_INT(f, bvh->cd_face_node_offset, DYNTOPO_NODE_NONE);
+ BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, DYNTOPO_NODE_NONE);
/* Log removed face */
- BM_log_face_removed(bvh->bm_log, f);
+ BM_log_face_removed(pbvh->bm_log, f);
/* mark node for update */
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
@@ -766,10 +769,10 @@ typedef struct {
#ifdef USE_EDGEQUEUE_TAG_VERIFY
/* simply check no edges are tagged
* (it's a requirement that edges enter and leave a clean tag state) */
-static void pbvh_bmesh_edge_tag_verify(PBVH *bvh)
+static void pbvh_bmesh_edge_tag_verify(PBVH *pbvh)
{
- for (int n = 0; n < bvh->totnode; n++) {
- PBVHNode *node = &bvh->nodes[n];
+ for (int n = 0; n < pbvh->totnode; n++) {
+ PBVHNode *node = &pbvh->nodes[n];
if (node->bm_faces) {
GSetIterator gs_iter;
GSET_ITER (gs_iter, node->bm_faces) {
@@ -999,7 +1002,7 @@ static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx, BMFace *f)
* The highest priority (lowest number) is given to the longest edge.
*/
static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
- PBVH *bvh,
+ PBVH *pbvh,
const float center[3],
const float view_normal[3],
float radius,
@@ -1009,9 +1012,9 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
eq_ctx->q->heap = BLI_heapsimple_new();
eq_ctx->q->center = center;
eq_ctx->q->radius_squared = radius * radius;
- eq_ctx->q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len;
+ eq_ctx->q->limit_len_squared = pbvh->bm_max_edge_len * pbvh->bm_max_edge_len;
#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
- eq_ctx->q->limit_len = bvh->bm_max_edge_len;
+ eq_ctx->q->limit_len = pbvh->bm_max_edge_len;
#endif
eq_ctx->q->view_normal = view_normal;
@@ -1031,11 +1034,11 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
}
#ifdef USE_EDGEQUEUE_TAG_VERIFY
- pbvh_bmesh_edge_tag_verify(bvh);
+ pbvh_bmesh_edge_tag_verify(pbvh);
#endif
- for (int n = 0; n < bvh->totnode; n++) {
- PBVHNode *node = &bvh->nodes[n];
+ for (int n = 0; n < pbvh->totnode; n++) {
+ PBVHNode *node = &pbvh->nodes[n];
/* Check leaf nodes marked for topology update */
if ((node->flag & PBVH_Leaf) && (node->flag & PBVH_UpdateTopology) &&
@@ -1062,7 +1065,7 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
* The highest priority (lowest number) is given to the shortest edge.
*/
static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
- PBVH *bvh,
+ PBVH *pbvh,
const float center[3],
const float view_normal[3],
float radius,
@@ -1072,9 +1075,9 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
eq_ctx->q->heap = BLI_heapsimple_new();
eq_ctx->q->center = center;
eq_ctx->q->radius_squared = radius * radius;
- eq_ctx->q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+ eq_ctx->q->limit_len_squared = pbvh->bm_min_edge_len * pbvh->bm_min_edge_len;
#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
- eq_ctx->q->limit_len = bvh->bm_min_edge_len;
+ eq_ctx->q->limit_len = pbvh->bm_min_edge_len;
#endif
eq_ctx->q->view_normal = view_normal;
@@ -1093,8 +1096,8 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_sphere;
}
- for (int n = 0; n < bvh->totnode; n++) {
- PBVHNode *node = &bvh->nodes[n];
+ for (int n = 0; n < pbvh->totnode; n++) {
+ PBVHNode *node = &pbvh->nodes[n];
/* Check leaf nodes marked for topology update */
if ((node->flag & PBVH_Leaf) && (node->flag & PBVH_UpdateTopology) &&
@@ -1114,7 +1117,7 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
/*************************** Topology update **************************/
static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
- PBVH *bvh,
+ PBVH *pbvh,
BMEdge *e,
BLI_Buffer *edge_loops)
{
@@ -1130,7 +1133,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
int node_index = BM_ELEM_CD_GET_INT(e->v1, eq_ctx->cd_vert_node_offset);
BMVert *v_new = pbvh_bmesh_vert_create(
- bvh, node_index, co_mid, no_mid, eq_ctx->cd_vert_mask_offset);
+ pbvh, node_index, co_mid, no_mid, eq_ctx->cd_vert_mask_offset);
/* update paint mask */
if (eq_ctx->cd_vert_mask_offset != -1) {
@@ -1163,7 +1166,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
v2 = l_adj->next->v;
if (ni != node_index && i == 0) {
- pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new);
+ pbvh_bmesh_vert_ownership_transfer(pbvh, &pbvh->nodes[ni], v_new);
}
/**
@@ -1196,26 +1199,26 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
v_tri[0] = v1;
v_tri[1] = v_new;
v_tri[2] = v_opp;
- bm_edges_from_tri(bvh->bm, v_tri, e_tri);
- f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj);
+ bm_edges_from_tri(pbvh->bm, v_tri, e_tri);
+ f_new = pbvh_bmesh_face_create(pbvh, ni, v_tri, e_tri, f_adj);
long_edge_queue_face_add(eq_ctx, f_new);
v_tri[0] = v_new;
v_tri[1] = v2;
/* v_tri[2] = v_opp; */ /* unchanged */
- e_tri[0] = BM_edge_create(bvh->bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE);
+ e_tri[0] = BM_edge_create(pbvh->bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE);
e_tri[2] = e_tri[1]; /* switched */
- e_tri[1] = BM_edge_create(bvh->bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE);
- f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj);
+ e_tri[1] = BM_edge_create(pbvh->bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE);
+ f_new = pbvh_bmesh_face_create(pbvh, ni, v_tri, e_tri, f_adj);
long_edge_queue_face_add(eq_ctx, f_new);
/* Delete original */
- pbvh_bmesh_face_remove(bvh, f_adj);
- BM_face_kill(bvh->bm, f_adj);
+ pbvh_bmesh_face_remove(pbvh, f_adj);
+ BM_face_kill(pbvh->bm, f_adj);
/* Ensure new vertex is in the node */
- if (!BLI_gset_haskey(bvh->nodes[ni].bm_unique_verts, v_new)) {
- BLI_gset_add(bvh->nodes[ni].bm_other_verts, v_new);
+ if (!BLI_gset_haskey(pbvh->nodes[ni].bm_unique_verts, v_new)) {
+ BLI_gset_add(pbvh->nodes[ni].bm_other_verts, v_new);
}
if (BM_vert_edge_count_is_over(v_opp, 8)) {
@@ -1228,11 +1231,11 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
}
}
- BM_edge_kill(bvh->bm, e);
+ BM_edge_kill(pbvh->bm, e);
}
static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx,
- PBVH *bvh,
+ PBVH *pbvh,
BLI_Buffer *edge_loops)
{
bool any_subdivided = false;
@@ -1274,17 +1277,17 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx,
any_subdivided = true;
- pbvh_bmesh_split_edge(eq_ctx, bvh, e, edge_loops);
+ pbvh_bmesh_split_edge(eq_ctx, pbvh, e, edge_loops);
}
#ifdef USE_EDGEQUEUE_TAG_VERIFY
- pbvh_bmesh_edge_tag_verify(bvh);
+ pbvh_bmesh_edge_tag_verify(pbvh);
#endif
return any_subdivided;
}
-static void pbvh_bmesh_collapse_edge(PBVH *bvh,
+static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
BMEdge *e,
BMVert *v1,
BMVert *v2,
@@ -1306,20 +1309,20 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
}
/* Remove the merge vertex from the PBVH */
- pbvh_bmesh_vert_remove(bvh, v_del);
+ pbvh_bmesh_vert_remove(pbvh, v_del);
/* Remove all faces adjacent to the edge */
BMLoop *l_adj;
while ((l_adj = e->l)) {
BMFace *f_adj = l_adj->f;
- pbvh_bmesh_face_remove(bvh, f_adj);
- BM_face_kill(bvh->bm, f_adj);
+ pbvh_bmesh_face_remove(pbvh, f_adj);
+ BM_face_kill(pbvh->bm, f_adj);
}
/* Kill the edge */
BLI_assert(BM_edge_is_wire(e));
- BM_edge_kill(bvh->bm, e);
+ BM_edge_kill(pbvh->bm, e);
/* For all remaining faces of v_del, create a new face that is the
* same except it uses v_conn instead of v_del */
@@ -1364,10 +1367,10 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
BLI_assert(!BM_face_exists(v_tri, 3));
BMEdge *e_tri[3];
- PBVHNode *n = pbvh_bmesh_node_from_face(bvh, f);
- int ni = n - bvh->nodes;
- bm_edges_from_tri(bvh->bm, v_tri, e_tri);
- pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f);
+ PBVHNode *n = pbvh_bmesh_node_from_face(pbvh, f);
+ int ni = n - pbvh->nodes;
+ bm_edges_from_tri(pbvh->bm, v_tri, e_tri);
+ pbvh_bmesh_face_create(pbvh, ni, v_tri, e_tri, f);
/* Ensure that v_conn is in the new face's node */
if (!BLI_gset_haskey(n->bm_unique_verts, v_conn)) {
@@ -1398,14 +1401,14 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
e_tri[2] = l_iter->e;
/* Remove the face */
- pbvh_bmesh_face_remove(bvh, f_del);
- BM_face_kill(bvh->bm, f_del);
+ pbvh_bmesh_face_remove(pbvh, f_del);
+ BM_face_kill(pbvh->bm, f_del);
/* Check if any of the face's edges are now unused by any
* face, if so delete them */
for (int j = 0; j < 3; j++) {
if (BM_edge_is_wire(e_tri[j])) {
- BM_edge_kill(bvh->bm, e_tri[j]);
+ BM_edge_kill(pbvh->bm, e_tri[j]);
}
}
@@ -1413,15 +1416,15 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
* remove them from the PBVH */
for (int j = 0; j < 3; j++) {
if ((v_tri[j] != v_del) && (v_tri[j]->e == NULL)) {
- pbvh_bmesh_vert_remove(bvh, v_tri[j]);
+ pbvh_bmesh_vert_remove(pbvh, v_tri[j]);
- BM_log_vert_removed(bvh->bm_log, v_tri[j], eq_ctx->cd_vert_mask_offset);
+ BM_log_vert_removed(pbvh->bm_log, v_tri[j], eq_ctx->cd_vert_mask_offset);
if (v_tri[j] == v_conn) {
v_conn = NULL;
}
BLI_ghash_insert(deleted_verts, v_tri[j], NULL);
- BM_vert_kill(bvh->bm, v_tri[j]);
+ BM_vert_kill(pbvh->bm, v_tri[j]);
}
}
}
@@ -1429,7 +1432,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
/* Move v_conn to the midpoint of v_conn and v_del (if v_conn still exists, it
* may have been deleted above) */
if (v_conn != NULL) {
- BM_log_vert_before_modified(bvh->bm_log, v_conn, eq_ctx->cd_vert_mask_offset);
+ BM_log_vert_before_modified(pbvh->bm_log, v_conn, eq_ctx->cd_vert_mask_offset);
mid_v3_v3v3(v_conn->co, v_conn->co, v_del->co);
add_v3_v3(v_conn->no, v_del->no);
normalize_v3(v_conn->no);
@@ -1437,7 +1440,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
/* update boundboxes attached to the connected vertex
* note that we can often get-away without this but causes T48779 */
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_conn) {
- PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, l->f);
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, l->f);
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateBB;
}
BM_LOOPS_OF_VERT_ITER_END;
@@ -1445,17 +1448,17 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
/* Delete v_del */
BLI_assert(!BM_vert_face_check(v_del));
- BM_log_vert_removed(bvh->bm_log, v_del, eq_ctx->cd_vert_mask_offset);
+ BM_log_vert_removed(pbvh->bm_log, v_del, eq_ctx->cd_vert_mask_offset);
/* v_conn == NULL is OK */
BLI_ghash_insert(deleted_verts, v_del, v_conn);
- BM_vert_kill(bvh->bm, v_del);
+ BM_vert_kill(pbvh->bm, v_del);
}
static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
- PBVH *bvh,
+ PBVH *pbvh,
BLI_Buffer *deleted_faces)
{
- const float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+ const float min_len_squared = pbvh->bm_min_edge_len * pbvh->bm_min_edge_len;
bool any_collapsed = false;
/* deleted verts point to vertices they were merged into, or NULL when removed. */
GHash *deleted_verts = BLI_ghash_ptr_new("deleted_verts");
@@ -1496,7 +1499,7 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
any_collapsed = true;
- pbvh_bmesh_collapse_edge(bvh, e, v1, v2, deleted_verts, deleted_faces, eq_ctx);
+ pbvh_bmesh_collapse_edge(pbvh, e, v1, v2, deleted_verts, deleted_faces, eq_ctx);
}
BLI_ghash_free(deleted_verts, NULL, NULL);
@@ -1691,11 +1694,11 @@ struct FastNodeBuildInfo {
* to a sub part of the arrays.
*/
static void pbvh_bmesh_node_limit_ensure_fast(
- PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, MemArena *arena)
+ PBVH *pbvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, MemArena *arena)
{
struct FastNodeBuildInfo *child1, *child2;
- if (node->totface <= bvh->leaf_limit) {
+ if (node->totface <= pbvh->leaf_limit) {
return;
}
@@ -1782,38 +1785,38 @@ static void pbvh_bmesh_node_limit_ensure_fast(
child2->start = node->start + num_child1;
child1->child1 = child1->child2 = child2->child1 = child2->child2 = NULL;
- pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child1, arena);
- pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child2, arena);
+ pbvh_bmesh_node_limit_ensure_fast(pbvh, nodeinfo, bbc_array, child1, arena);
+ pbvh_bmesh_node_limit_ensure_fast(pbvh, nodeinfo, bbc_array, child2, arena);
}
static void pbvh_bmesh_create_nodes_fast_recursive(
- PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, int node_index)
+ PBVH *pbvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, int node_index)
{
- PBVHNode *n = bvh->nodes + node_index;
+ PBVHNode *n = pbvh->nodes + node_index;
/* two cases, node does not have children or does have children */
if (node->child1) {
- int children_offset = bvh->totnode;
+ int children_offset = pbvh->totnode;
n->children_offset = children_offset;
- pbvh_grow_nodes(bvh, bvh->totnode + 2);
+ pbvh_grow_nodes(pbvh, pbvh->totnode + 2);
pbvh_bmesh_create_nodes_fast_recursive(
- bvh, nodeinfo, bbc_array, node->child1, children_offset);
+ pbvh, nodeinfo, bbc_array, node->child1, children_offset);
pbvh_bmesh_create_nodes_fast_recursive(
- bvh, nodeinfo, bbc_array, node->child2, children_offset + 1);
+ pbvh, nodeinfo, bbc_array, node->child2, children_offset + 1);
- n = &bvh->nodes[node_index];
+ n = &pbvh->nodes[node_index];
/* Update bounding box */
BB_reset(&n->vb);
- BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset].vb);
- BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset + 1].vb);
+ BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset].vb);
+ BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset + 1].vb);
n->orig_vb = n->vb;
}
else {
/* node does not have children so it's a leaf node, populate with faces and tag accordingly
* this is an expensive part but it's not so easily thread-able due to vertex node indices */
- const int cd_vert_node_offset = bvh->cd_vert_node_offset;
- const int cd_face_node_offset = bvh->cd_face_node_offset;
+ const int cd_vert_node_offset = pbvh->cd_vert_node_offset;
+ const int cd_face_node_offset = pbvh->cd_face_node_offset;
bool has_visible = false;
@@ -1876,27 +1879,27 @@ static void pbvh_bmesh_create_nodes_fast_recursive(
/***************************** Public API *****************************/
/* Build a PBVH from a BMesh */
-void BKE_pbvh_build_bmesh(PBVH *bvh,
+void BKE_pbvh_build_bmesh(PBVH *pbvh,
BMesh *bm,
bool smooth_shading,
BMLog *log,
const int cd_vert_node_offset,
const int cd_face_node_offset)
{
- bvh->cd_vert_node_offset = cd_vert_node_offset;
- bvh->cd_face_node_offset = cd_face_node_offset;
- bvh->bm = bm;
+ pbvh->cd_vert_node_offset = cd_vert_node_offset;
+ pbvh->cd_face_node_offset = cd_face_node_offset;
+ pbvh->bm = bm;
- BKE_pbvh_bmesh_detail_size_set(bvh, 0.75);
+ BKE_pbvh_bmesh_detail_size_set(pbvh, 0.75);
- bvh->type = PBVH_BMESH;
- bvh->bm_log = log;
+ pbvh->type = PBVH_BMESH;
+ pbvh->bm_log = log;
/* TODO: choose leaf limit better */
- bvh->leaf_limit = 100;
+ pbvh->leaf_limit = 100;
if (smooth_shading) {
- bvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING;
+ pbvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING;
}
/* bounding box array of all faces, no need to recalculate every time */
@@ -1936,17 +1939,17 @@ void BKE_pbvh_build_bmesh(PBVH *bvh,
rootnode.totface = bm->totface;
/* start recursion, assign faces to nodes accordingly */
- pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, &rootnode, arena);
+ pbvh_bmesh_node_limit_ensure_fast(pbvh, nodeinfo, bbc_array, &rootnode, arena);
/* We now have all faces assigned to a node,
* next we need to assign those to the gsets of the nodes. */
/* Start with all faces in the root node */
- bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode");
- bvh->totnode = 1;
+ pbvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode");
+ pbvh->totnode = 1;
/* take root node and visit and populate children recursively */
- pbvh_bmesh_create_nodes_fast_recursive(bvh, nodeinfo, bbc_array, &rootnode, 0);
+ pbvh_bmesh_create_nodes_fast_recursive(pbvh, nodeinfo, bbc_array, &rootnode, 0);
BLI_memarena_free(arena);
MEM_freeN(bbc_array);
@@ -1954,7 +1957,7 @@ void BKE_pbvh_build_bmesh(PBVH *bvh,
}
/* Collapse short edges, subdivide long edges */
-bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
+bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
PBVHTopologyUpdateMode mode,
const float center[3],
const float view_normal[3],
@@ -1965,9 +1968,9 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
/* 2 is enough for edge faces - manifold edge */
BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2);
BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32);
- const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK);
- const int cd_vert_node_offset = bvh->cd_vert_node_offset;
- const int cd_face_node_offset = bvh->cd_face_node_offset;
+ const int cd_vert_mask_offset = CustomData_get_offset(&pbvh->bm->vdata, CD_PAINT_MASK);
+ const int cd_vert_node_offset = pbvh->cd_vert_node_offset;
+ const int cd_face_node_offset = pbvh->cd_face_node_offset;
bool modified = false;
@@ -1981,15 +1984,15 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
EdgeQueueContext eq_ctx = {
&q,
queue_pool,
- bvh->bm,
+ pbvh->bm,
cd_vert_mask_offset,
cd_vert_node_offset,
cd_face_node_offset,
};
short_edge_queue_create(
- &eq_ctx, bvh, center, view_normal, radius, use_frontface, use_projected);
- modified |= pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh, &deleted_faces);
+ &eq_ctx, pbvh, center, view_normal, radius, use_frontface, use_projected);
+ modified |= pbvh_bmesh_collapse_short_edges(&eq_ctx, pbvh, &deleted_faces);
BLI_heapsimple_free(q.heap, NULL);
BLI_mempool_destroy(queue_pool);
}
@@ -2000,22 +2003,22 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
EdgeQueueContext eq_ctx = {
&q,
queue_pool,
- bvh->bm,
+ pbvh->bm,
cd_vert_mask_offset,
cd_vert_node_offset,
cd_face_node_offset,
};
long_edge_queue_create(
- &eq_ctx, bvh, center, view_normal, radius, use_frontface, use_projected);
- modified |= pbvh_bmesh_subdivide_long_edges(&eq_ctx, bvh, &edge_loops);
+ &eq_ctx, pbvh, center, view_normal, radius, use_frontface, use_projected);
+ modified |= pbvh_bmesh_subdivide_long_edges(&eq_ctx, pbvh, &edge_loops);
BLI_heapsimple_free(q.heap, NULL);
BLI_mempool_destroy(queue_pool);
}
/* Unmark nodes */
- for (int n = 0; n < bvh->totnode; n++) {
- PBVHNode *node = &bvh->nodes[n];
+ for (int n = 0; n < pbvh->totnode; n++) {
+ PBVHNode *node = &pbvh->nodes[n];
if (node->flag & PBVH_Leaf && node->flag & PBVH_UpdateTopology) {
node->flag &= ~PBVH_UpdateTopology;
@@ -2025,7 +2028,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
BLI_buffer_free(&deleted_faces);
#ifdef USE_VERIFY
- pbvh_bmesh_verify(bvh);
+ pbvh_bmesh_verify(pbvh);
#endif
return modified;
@@ -2092,25 +2095,25 @@ void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, PBVHNode *node)
node->bm_tot_ortri = i;
}
-void BKE_pbvh_bmesh_after_stroke(PBVH *bvh)
+void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh)
{
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *n = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *n = &pbvh->nodes[i];
if (n->flag & PBVH_Leaf) {
/* Free orco/ortri data */
pbvh_bmesh_node_drop_orig(n);
/* Recursively split nodes that have gotten too many
* elements */
- pbvh_bmesh_node_limit_ensure(bvh, i);
+ pbvh_bmesh_node_limit_ensure(pbvh, i);
}
}
}
-void BKE_pbvh_bmesh_detail_size_set(PBVH *bvh, float detail_size)
+void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size)
{
- bvh->bm_max_edge_len = detail_size;
- bvh->bm_min_edge_len = bvh->bm_max_edge_len * 0.4f;
+ pbvh->bm_max_edge_len = detail_size;
+ pbvh->bm_min_edge_len = pbvh->bm_max_edge_len * 0.4f;
}
void BKE_pbvh_node_mark_topology_update(PBVHNode *node)
@@ -2137,25 +2140,25 @@ struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node)
#if 0
-static void pbvh_bmesh_print(PBVH *bvh)
+static void pbvh_bmesh_print(PBVH *pbvh)
{
- fprintf(stderr, "\npbvh=%p\n", bvh);
+ fprintf(stderr, "\npbvh=%p\n", pbvh);
fprintf(stderr, "bm_face_to_node:\n");
BMIter iter;
BMFace *f;
- BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) {
- fprintf(stderr, " %d -> %d\n", BM_elem_index_get(f), pbvh_bmesh_node_index_from_face(bvh, f));
+ BM_ITER_MESH (f, &iter, pbvh->bm, BM_FACES_OF_MESH) {
+ fprintf(stderr, " %d -> %d\n", BM_elem_index_get(f), pbvh_bmesh_node_index_from_face(pbvh, f));
}
fprintf(stderr, "bm_vert_to_node:\n");
BMVert *v;
- BM_ITER_MESH (v, &iter, bvh->bm, BM_FACES_OF_MESH) {
- fprintf(stderr, " %d -> %d\n", BM_elem_index_get(v), pbvh_bmesh_node_index_from_vert(bvh, v));
+ BM_ITER_MESH (v, &iter, pbvh->bm, BM_FACES_OF_MESH) {
+ fprintf(stderr, " %d -> %d\n", BM_elem_index_get(v), pbvh_bmesh_node_index_from_vert(pbvh, v));
}
- for (int n = 0; n < bvh->totnode; n++) {
- PBVHNode *node = &bvh->nodes[n];
+ for (int n = 0; n < pbvh->totnode; n++) {
+ PBVHNode *node = &pbvh->nodes[n];
if (!(node->flag & PBVH_Leaf)) {
continue;
}
@@ -2186,25 +2189,25 @@ static void print_flag_factors(int flag)
#ifdef USE_VERIFY
-static void pbvh_bmesh_verify(PBVH *bvh)
+static void pbvh_bmesh_verify(PBVH *pbvh)
{
/* build list of faces & verts to lookup */
- GSet *faces_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totface);
+ GSet *faces_all = BLI_gset_ptr_new_ex(__func__, pbvh->bm->totface);
BMIter iter;
{
BMFace *f;
- BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) {
- BLI_assert(BM_ELEM_CD_GET_INT(f, bvh->cd_face_node_offset) != DYNTOPO_NODE_NONE);
+ BM_ITER_MESH (f, &iter, pbvh->bm, BM_FACES_OF_MESH) {
+ BLI_assert(BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset) != DYNTOPO_NODE_NONE);
BLI_gset_insert(faces_all, f);
}
}
- GSet *verts_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totvert);
+ GSet *verts_all = BLI_gset_ptr_new_ex(__func__, pbvh->bm->totvert);
{
BMVert *v;
- BM_ITER_MESH (v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
- if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
+ BM_ITER_MESH (v, &iter, pbvh->bm, BM_VERTS_OF_MESH) {
+ if (BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
BLI_gset_insert(verts_all, v);
}
}
@@ -2213,8 +2216,8 @@ static void pbvh_bmesh_verify(PBVH *bvh)
/* Check vert/face counts */
{
int totface = 0, totvert = 0;
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *n = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *n = &pbvh->nodes[i];
totface += n->bm_faces ? BLI_gset_len(n->bm_faces) : 0;
totvert += n->bm_unique_verts ? BLI_gset_len(n->bm_unique_verts) : 0;
}
@@ -2225,10 +2228,10 @@ static void pbvh_bmesh_verify(PBVH *bvh)
{
BMFace *f;
- BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH (f, &iter, pbvh->bm, BM_FACES_OF_MESH) {
BMIter bm_iter;
BMVert *v;
- PBVHNode *n = pbvh_bmesh_node_lookup(bvh, f);
+ PBVHNode *n = pbvh_bmesh_node_lookup(pbvh, f);
/* Check that the face's node is a leaf */
BLI_assert(n->flag & PBVH_Leaf);
@@ -2244,7 +2247,7 @@ static void pbvh_bmesh_verify(PBVH *bvh)
BLI_assert(BLI_gset_haskey(n->bm_unique_verts, v) ^ BLI_gset_haskey(n->bm_other_verts, v));
/* Check that the vertex has a node owner */
- nv = pbvh_bmesh_node_lookup(bvh, v);
+ nv = pbvh_bmesh_node_lookup(pbvh, v);
/* Check that the vertex's node knows it owns the vert */
BLI_assert(BLI_gset_haskey(nv->bm_unique_verts, v));
@@ -2258,13 +2261,13 @@ static void pbvh_bmesh_verify(PBVH *bvh)
/* Check verts */
{
BMVert *v;
- BM_ITER_MESH (v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH (v, &iter, pbvh->bm, BM_VERTS_OF_MESH) {
/* vertex isn't tracked */
- if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) {
+ if (BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) {
continue;
}
- PBVHNode *n = pbvh_bmesh_node_lookup(bvh, v);
+ PBVHNode *n = pbvh_bmesh_node_lookup(pbvh, v);
/* Check that the vert's node is a leaf */
BLI_assert(n->flag & PBVH_Leaf);
@@ -2281,7 +2284,7 @@ static void pbvh_bmesh_verify(PBVH *bvh)
BMIter bm_iter;
BMFace *f = NULL;
BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
- if (pbvh_bmesh_node_lookup(bvh, f) == n) {
+ if (pbvh_bmesh_node_lookup(pbvh, f) == n) {
found = true;
break;
}
@@ -2291,8 +2294,8 @@ static void pbvh_bmesh_verify(PBVH *bvh)
# if 1
/* total freak stuff, check if node exists somewhere else */
/* Slow */
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *n_other = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *n_other = &pbvh->nodes[i];
if ((n != n_other) && (n_other->bm_unique_verts)) {
BLI_assert(!BLI_gset_haskey(n_other->bm_unique_verts, v));
}
@@ -2304,10 +2307,10 @@ static void pbvh_bmesh_verify(PBVH *bvh)
# if 0
/* check that every vert belongs somewhere */
/* Slow */
- BM_ITER_MESH (vi, &iter, bvh->bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH (vi, &iter, pbvh->bm, BM_VERTS_OF_MESH) {
bool has_unique = false;
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *n = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *n = &pbvh->nodes[i];
if ((n->bm_unique_verts != NULL) && BLI_gset_haskey(n->bm_unique_verts, vi)) {
has_unique = true;
}
@@ -2317,25 +2320,25 @@ static void pbvh_bmesh_verify(PBVH *bvh)
}
/* if totvert differs from number of verts inside the hash. hash-totvert is checked above */
- BLI_assert(vert_count == bvh->bm->totvert);
+ BLI_assert(vert_count == pbvh->bm->totvert);
# endif
/* Check that node elements are recorded in the top level */
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *n = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *n = &pbvh->nodes[i];
if (n->flag & PBVH_Leaf) {
GSetIterator gs_iter;
GSET_ITER (gs_iter, n->bm_faces) {
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
- PBVHNode *n_other = pbvh_bmesh_node_lookup(bvh, f);
+ PBVHNode *n_other = pbvh_bmesh_node_lookup(pbvh, f);
BLI_assert(n == n_other);
BLI_assert(BLI_gset_haskey(faces_all, f));
}
GSET_ITER (gs_iter, n->bm_unique_verts) {
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
- PBVHNode *n_other = pbvh_bmesh_node_lookup(bvh, v);
+ PBVHNode *n_other = pbvh_bmesh_node_lookup(pbvh, v);
BLI_assert(!BLI_gset_haskey(n->bm_other_verts, v));
BLI_assert(n == n_other);
BLI_assert(BLI_gset_haskey(verts_all, v));
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 4d37c2ea931..c9911d2cf85 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -2116,6 +2116,7 @@ void BKE_rigidbody_ensure_local_object(Main *bmain, Object *ob)
bool BKE_rigidbody_add_object(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
{
+ BKE_report(reports, RPT_ERROR, "Compiled without Bullet physics engine");
return false;
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 34249e0a8f7..aa2a1b14841 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -158,7 +158,7 @@ static void scene_init_data(ID *id)
scene->unit.mass_unit = (uchar)bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_MASS);
scene->unit.time_unit = (uchar)bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_TIME);
- /* Anti-aliasing threshold. */
+ /* Anti-Aliasing threshold. */
scene->grease_pencil_settings.smaa_threshold = 1.0f;
{
@@ -621,7 +621,7 @@ static void remove_sequencer_fcurves(Scene *sce)
if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
action_groups_remove_channel(adt->action, fcu);
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
}
}
}
@@ -668,7 +668,6 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
}
BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag);
- ts->imapaint.paintcursor = NULL;
ts->particle.paintcursor = NULL;
ts->particle.scene = NULL;
ts->particle.object = NULL;
@@ -1249,9 +1248,7 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce)
}
/**
- * This function is needed to cope with fractional frames - including two Blender rendering
- * features mblur (motion blur that renders 'subframes' and blurs them together),
- * and fields rendering.
+ * This function is needed to cope with fractional frames, needed for motion blur & physics.
*/
float BKE_scene_frame_get(const Scene *scene)
{
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
index a08bbf182fa..5c2d5b0087f 100644
--- a/source/blender/blenkernel/intern/seqcache.c
+++ b/source/blender/blenkernel/intern/seqcache.c
@@ -1217,6 +1217,11 @@ void BKE_sequencer_cache_cleanup_sequence(Scene *scene,
struct ImBuf *BKE_sequencer_cache_get(
const SeqRenderData *context, Sequence *seq, float cfra, int type, bool skip_disk_cache)
{
+
+ if (context->skip_cache || context->is_proxy_render || !seq) {
+ return NULL;
+ }
+
Scene *scene = context->scene;
if (context->is_prefetch_render) {
@@ -1314,6 +1319,10 @@ void BKE_sequencer_cache_put(const SeqRenderData *context,
float cost,
bool skip_disk_cache)
{
+ if (i == NULL || context->skip_cache || context->is_proxy_render || !seq) {
+ return;
+ }
+
Scene *scene = context->scene;
if (context->is_prefetch_render) {
@@ -1322,10 +1331,6 @@ void BKE_sequencer_cache_put(const SeqRenderData *context,
seq = BKE_sequencer_prefetch_get_original_sequence(seq, scene);
}
- if (i == NULL || context->skip_cache || context->is_proxy_render || !seq) {
- return;
- }
-
/* Prevent reinserting, it breaks cache key linking. */
ImBuf *test = BKE_sequencer_cache_get(context, seq, cfra, type, true);
if (test) {
diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c
index f00d517940a..30a371b5b28 100644
--- a/source/blender/blenkernel/intern/seqprefetch.c
+++ b/source/blender/blenkernel/intern/seqprefetch.c
@@ -179,12 +179,17 @@ static bool seq_prefetch_is_cache_full(Scene *scene)
return BKE_sequencer_cache_recycle_item(pfjob->scene) == false;
}
+static float seq_prefetch_cfra(PrefetchJob *pfjob)
+{
+ return pfjob->cfra + pfjob->num_frames_prefetched;
+}
+
void BKE_sequencer_prefetch_get_time_range(Scene *scene, int *start, int *end)
{
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
*start = pfjob->cfra;
- *end = pfjob->cfra + pfjob->num_frames_prefetched;
+ *end = seq_prefetch_cfra(pfjob);
}
static void seq_prefetch_free_depsgraph(PrefetchJob *pfjob)
@@ -198,8 +203,7 @@ static void seq_prefetch_free_depsgraph(PrefetchJob *pfjob)
static void seq_prefetch_update_depsgraph(PrefetchJob *pfjob)
{
- DEG_evaluate_on_framechange(
- pfjob->bmain_eval, pfjob->depsgraph, pfjob->cfra + pfjob->num_frames_prefetched);
+ DEG_evaluate_on_framechange(pfjob->bmain_eval, pfjob->depsgraph, seq_prefetch_cfra(pfjob));
}
static void seq_prefetch_init_depsgraph(PrefetchJob *pfjob)
@@ -347,7 +351,7 @@ static bool seq_prefetch_do_skip_frame(Scene *scene)
{
Editing *ed = scene->ed;
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
- float cfra = pfjob->cfra + pfjob->num_frames_prefetched;
+ float cfra = seq_prefetch_cfra(pfjob);
Sequence *seq_arr[MAXSEQ + 1];
int count = BKE_sequencer_get_shown_sequences(ed->seqbasep, cfra, 0, seq_arr);
SeqRenderData *ctx = &pfjob->context_cpy;
@@ -403,20 +407,36 @@ static bool seq_prefetch_do_skip_frame(Scene *scene)
return false;
}
+static bool seq_prefetch_need_suspend(PrefetchJob *pfjob)
+{
+ return seq_prefetch_is_cache_full(pfjob->scene) || seq_prefetch_is_scrubbing(pfjob->bmain) ||
+ (seq_prefetch_cfra(pfjob) >= pfjob->scene->r.efra);
+}
+
+static void seq_prefetch_do_suspend(PrefetchJob *pfjob)
+{
+ BLI_mutex_lock(&pfjob->prefetch_suspend_mutex);
+ while (seq_prefetch_need_suspend(pfjob) &&
+ (pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !pfjob->stop) {
+ pfjob->waiting = true;
+ BLI_condition_wait(&pfjob->prefetch_suspend_cond, &pfjob->prefetch_suspend_mutex);
+ seq_prefetch_update_area(pfjob);
+ }
+ pfjob->waiting = false;
+ BLI_mutex_unlock(&pfjob->prefetch_suspend_mutex);
+}
+
static void *seq_prefetch_frames(void *job)
{
PrefetchJob *pfjob = (PrefetchJob *)job;
- while (pfjob->cfra + pfjob->num_frames_prefetched <= pfjob->scene->r.efra) {
+ while (seq_prefetch_cfra(pfjob) <= pfjob->scene->r.efra) {
pfjob->scene_eval->ed->prefetch_job = NULL;
seq_prefetch_update_depsgraph(pfjob);
AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id);
- BKE_animsys_evaluate_animdata(&pfjob->context_cpy.scene->id,
- adt,
- pfjob->cfra + pfjob->num_frames_prefetched,
- ADT_RECALC_ALL,
- false);
+ BKE_animsys_evaluate_animdata(
+ &pfjob->context_cpy.scene->id, adt, seq_prefetch_cfra(pfjob), ADT_RECALC_ALL, false);
/* This is quite hacky solution:
* We need cross-reference original scene with copy for cache.
@@ -431,26 +451,17 @@ static void *seq_prefetch_frames(void *job)
continue;
}
- ImBuf *ibuf = BKE_sequencer_give_ibuf(
- &pfjob->context_cpy, pfjob->cfra + pfjob->num_frames_prefetched, 0);
+ ImBuf *ibuf = BKE_sequencer_give_ibuf(&pfjob->context_cpy, seq_prefetch_cfra(pfjob), 0);
BKE_sequencer_cache_free_temp_cache(
- pfjob->scene, pfjob->context.task_id, pfjob->cfra + pfjob->num_frames_prefetched);
+ pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob));
IMB_freeImBuf(ibuf);
- /* suspend thread */
- BLI_mutex_lock(&pfjob->prefetch_suspend_mutex);
- while ((seq_prefetch_is_cache_full(pfjob->scene) || seq_prefetch_is_scrubbing(pfjob->bmain)) &&
- pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE && !pfjob->stop) {
- pfjob->waiting = true;
- BLI_condition_wait(&pfjob->prefetch_suspend_cond, &pfjob->prefetch_suspend_mutex);
- seq_prefetch_update_area(pfjob);
- }
- pfjob->waiting = false;
- BLI_mutex_unlock(&pfjob->prefetch_suspend_mutex);
+ /* Suspend thread if there is nothing to be prefetched. */
+ seq_prefetch_do_suspend(pfjob);
/* Avoid "collision" with main thread, but make sure to fetch at least few frames */
if (pfjob->num_frames_prefetched > 5 &&
- (pfjob->cfra + pfjob->num_frames_prefetched - pfjob->scene->r.cfra) < 2) {
+ (seq_prefetch_cfra(pfjob) - pfjob->scene->r.cfra) < 2) {
break;
}
@@ -463,7 +474,7 @@ static void *seq_prefetch_frames(void *job)
}
BKE_sequencer_cache_free_temp_cache(
- pfjob->scene, pfjob->context.task_id, pfjob->cfra + pfjob->num_frames_prefetched);
+ pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob));
pfjob->running = false;
pfjob->scene_eval->ed->prefetch_job = NULL;
@@ -520,10 +531,12 @@ void BKE_sequencer_prefetch_start(const SeqRenderData *context, float cfra, floa
seq_prefetch_resume(scene);
/* conditions to start:
* prefetch enabled, prefetch not running, not scrubbing,
- * not playing and rendering-expensive footage, cache storage enabled, has strips to render
+ * not playing and rendering-expensive footage, cache storage enabled, has strips to render,
+ * not rendering, not doing modal transform - important, see D7820.
*/
if ((ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !running && !scrubbing &&
- !(playing && cost > 0.9) && ed->cache_flag & SEQ_CACHE_ALL_TYPES && has_strips) {
+ !(playing && cost > 0.9) && ed->cache_flag & SEQ_CACHE_ALL_TYPES && has_strips &&
+ !G.is_rendering && !G.moving) {
seq_prefetch_start(context, cfra);
}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 954dca0f679..90edebfaa97 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -5119,7 +5119,7 @@ void BKE_sequencer_dupe_animdata(Scene *scene, const char *name_src, const char
for (fcu = scene->adt->action->curves.first; fcu && fcu->prev != fcu_last; fcu = fcu->next) {
if (STREQLEN(fcu->rna_path, str_from, str_from_len)) {
- fcu_cpy = copy_fcurve(fcu);
+ fcu_cpy = BKE_fcurve_copy(fcu);
BLI_addtail(&lb, fcu_cpy);
}
}
@@ -5152,7 +5152,7 @@ static void seq_free_animdata(Scene *scene, Sequence *seq)
FCurve *next_fcu = fcu->next;
BLI_remlink(&scene->adt->action->curves, fcu);
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
fcu = next_fcu;
}
diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc
index 50770125a18..d5ba345928b 100644
--- a/source/blender/blenkernel/intern/simulation.cc
+++ b/source/blender/blenkernel/intern/simulation.cc
@@ -18,6 +18,8 @@
* \ingroup bke
*/
+#include <iostream>
+
#include "MEM_guardedalloc.h"
#include "DNA_ID.h"
@@ -46,6 +48,7 @@
#include "BLT_translation.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
static void simulation_init_data(ID *id)
{
@@ -122,6 +125,8 @@ void *BKE_simulation_add(Main *bmain, const char *name)
return simulation;
}
-void BKE_simulation_data_update(Depsgraph *UNUSED(depsgraph), Scene *UNUSED(scene))
+void BKE_simulation_data_update(Depsgraph *UNUSED(depsgraph),
+ Scene *UNUSED(scene),
+ Simulation *UNUSED(simulation))
{
}
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index aef274f7d91..4892e8d6ede 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -503,10 +503,8 @@ static void studiolight_create_equirect_radiance_gputexture(StudioLight *sl)
sl->equirect_radiance_gputexture = GPU_texture_create_2d(
ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL);
GPUTexture *tex = sl->equirect_radiance_gputexture;
- GPU_texture_bind(tex, 0);
GPU_texture_filter_mode(tex, true);
GPU_texture_wrap_mode(tex, true, true);
- GPU_texture_unbind(tex);
}
sl->flag |= STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE;
}
@@ -567,10 +565,8 @@ static void studiolight_create_equirect_irradiance_gputexture(StudioLight *sl)
sl->equirect_irradiance_gputexture = GPU_texture_create_2d(
ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL);
GPUTexture *tex = sl->equirect_irradiance_gputexture;
- GPU_texture_bind(tex, 0);
GPU_texture_filter_mode(tex, true);
GPU_texture_wrap_mode(tex, true, true);
- GPU_texture_unbind(tex);
}
sl->flag |= STUDIOLIGHT_EQUIRECT_IRRADIANCE_GPUTEXTURE;
}
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 3f44c13ba19..f37feab4b85 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -713,6 +713,113 @@ static bool ch_is_op(char op)
}
}
+/**
+ * Helper function for #unit_distribute_negatives to find the next negative to distribute.
+ *
+ * \note This unnecessarily skips the next space if it comes right after the "-"
+ * just to make a more predictable output.
+ */
+static char *find_next_negative(const char *str, const char *remaining_str)
+{
+ char *str_found = strstr(remaining_str, "-");
+
+ if (str_found == NULL) {
+ return NULL;
+ }
+
+ /* Don't use the "-" from scientific notation, but make sure we can look backwards first. */
+ if ((str_found != str) && ELEM(*(str_found - 1), 'e', 'E')) {
+ return find_next_negative(str, str_found + 1);
+ }
+
+ if (*(str_found + 1) == ' ') {
+ str_found++;
+ }
+
+ return str_found + 1;
+}
+
+/**
+ * Helper function for #unit_distribute_negatives to find the next operation, including "-".
+ *
+ * \note This unnecessarily skips the space before the operation character
+ * just to make a more predictable output.
+ */
+static char *find_next_op(const char *str, char *remaining_str, int len_max)
+{
+ int i;
+ bool scientific_notation = false;
+ for (i = 0; i < len_max; i++) {
+ if (remaining_str[i] == '\0') {
+ return remaining_str + i;
+ }
+
+ if (ch_is_op(remaining_str[i])) {
+ if (scientific_notation) {
+ scientific_notation = false;
+ continue;
+ }
+
+ /* Make sure we don't look backwards before the start of the string. */
+ if (remaining_str != str && i != 0) {
+ /* Check for scientific notation. */
+ if (remaining_str[i - 1] == 'e' || remaining_str[i - 1] == 'E') {
+ scientific_notation = true;
+ continue;
+ }
+
+ /* Return position before a space character. */
+ if (remaining_str[i - 1] == ' ') {
+ i--;
+ }
+ }
+
+ return remaining_str + i;
+ }
+ }
+ BLI_assert(!"String should be NULL terminated");
+ return remaining_str + i;
+}
+
+/**
+ * Put parentheses around blocks of values after negative signs to get rid of an implied "+"
+ * between numbers without an operation between them. For example:
+ *
+ * "-1m50cm + 1 - 2m50cm" -> "-(1m50cm) + 1 - (2m50cm)"
+ */
+static bool unit_distribute_negatives(char *str, const int len_max)
+{
+ bool changed = false;
+
+ char *remaining_str = str;
+ int remaining_str_len = len_max;
+ while ((remaining_str = find_next_negative(str, remaining_str)) != NULL) {
+ /* Exit early in the unlikely situation that we've run out of length to add the parentheses. */
+ remaining_str_len = len_max - (int)(remaining_str - str);
+ if (remaining_str_len <= 2) {
+ return changed;
+ }
+
+ changed = true;
+
+ /* Add '(', shift the following characters to the right to make space. */
+ memmove(remaining_str + 1, remaining_str, remaining_str_len - 2);
+ *remaining_str = '(';
+
+ /* Add the ')' before the next operation or at the end. */
+ remaining_str = find_next_op(str, remaining_str + 1, remaining_str_len);
+ remaining_str_len = len_max - (int)(remaining_str - str);
+ memmove(remaining_str + 1, remaining_str, remaining_str_len - 2);
+ *remaining_str = ')';
+
+ /* Only move forward by 1 even though we added two characters. Minus signs need to be able to
+ * apply to the next block of values too. */
+ remaining_str += 1;
+ }
+
+ return changed;
+}
+
static int unit_scale_str(char *str,
int len_max,
char *str_tmp,
@@ -896,6 +1003,10 @@ bool bUnit_ReplaceString(
char str_tmp[TEMP_STR_SIZE];
bool changed = false;
+ /* Fix cases like "-1m50cm" which would evaluate to -0.5m without this. */
+ changed |= unit_distribute_negatives(str, len_max);
+ printf("%s\n", str);
+
/* Try to find a default unit from current or previous string. */
default_unit = unit_detect_from_str(usys, str, str_prev);
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 3a69b95c114..4625fd76293 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -69,17 +69,9 @@ static void workspace_free_data(ID *id)
static void workspace_foreach_id(ID *id, LibraryForeachIDData *data)
{
WorkSpace *workspace = (WorkSpace *)id;
- ListBase *layouts = BKE_workspace_layouts_get(workspace);
- LISTBASE_FOREACH (WorkSpaceLayout *, layout, layouts) {
- bScreen *screen = BKE_workspace_layout_screen_get(layout);
-
- /* CALLBACK_INVOKE expects an actual pointer, not a variable holding the pointer.
- * However we can't access layout->screen here
- * since we are outside the workspace project. */
- BKE_LIB_FOREACHID_PROCESS(data, screen, IDWALK_CB_USER);
- /* allow callback to set a different screen */
- BKE_workspace_layout_screen_set(layout, screen);
+ LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
+ BKE_LIB_FOREACHID_PROCESS(data, layout->screen, IDWALK_CB_USER);
}
}
@@ -228,7 +220,7 @@ WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const Main *bmain)
/* set an active screen-layout for each possible window/workspace combination */
for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
- BKE_workspace_hook_layout_for_workspace_set(hook, workspace, workspace->layouts.first);
+ BKE_workspace_active_layout_set(hook, workspace, workspace->layouts.first);
}
return hook;
@@ -433,6 +425,10 @@ WorkSpace *BKE_workspace_active_get(WorkSpaceInstanceHook *hook)
}
void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace)
{
+ if (hook->active == workspace) {
+ return;
+ }
+
hook->active = workspace;
if (workspace) {
WorkSpaceLayout *layout = workspace_relation_get_data_matching_parent(
@@ -443,13 +439,47 @@ void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace)
}
}
+/**
+ * Get the layout that is active for \a hook (which is the visible layout for the active workspace
+ * in \a hook).
+ */
WorkSpaceLayout *BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook)
{
return hook->act_layout;
}
-void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook, WorkSpaceLayout *layout)
+
+/**
+ * Get the layout to be activated should \a workspace become or be the active workspace in \a hook.
+ */
+WorkSpaceLayout *BKE_workspace_active_layout_for_workspace_get(const WorkSpaceInstanceHook *hook,
+ const WorkSpace *workspace)
+{
+ /* If the workspace is active, the active layout can be returned, no need for a lookup. */
+ if (hook->active == workspace) {
+ return hook->act_layout;
+ }
+
+ /* Inactive workspace */
+ return workspace_relation_get_data_matching_parent(&workspace->hook_layout_relations, hook);
+}
+
+/**
+ * \brief Activate a layout
+ *
+ * Sets \a layout as active for \a workspace when activated through or already active in \a hook.
+ * So when the active workspace of \a hook is \a workspace, \a layout becomes the active layout of
+ * \a hook too. See #BKE_workspace_active_set().
+ *
+ * \a workspace does not need to be active for this.
+ *
+ * WorkSpaceInstanceHook.act_layout should only be modified directly to update the layout pointer.
+ */
+void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook,
+ WorkSpace *workspace,
+ WorkSpaceLayout *layout)
{
hook->act_layout = layout;
+ workspace_relation_ensure_updated(&workspace->hook_layout_relations, hook, layout);
}
bScreen *BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook)
@@ -462,12 +492,7 @@ void BKE_workspace_active_screen_set(WorkSpaceInstanceHook *hook,
{
/* we need to find the WorkspaceLayout that wraps this screen */
WorkSpaceLayout *layout = BKE_workspace_layout_find(hook->active, screen);
- BKE_workspace_hook_layout_for_workspace_set(hook, workspace, layout);
-}
-
-ListBase *BKE_workspace_layouts_get(WorkSpace *workspace)
-{
- return &workspace->layouts;
+ BKE_workspace_active_layout_set(hook, workspace, layout);
}
const char *BKE_workspace_layout_name_get(const WorkSpaceLayout *layout)
@@ -485,22 +510,5 @@ bScreen *BKE_workspace_layout_screen_get(const WorkSpaceLayout *layout)
{
return layout->screen;
}
-void BKE_workspace_layout_screen_set(WorkSpaceLayout *layout, bScreen *screen)
-{
- layout->screen = screen;
-}
-
-WorkSpaceLayout *BKE_workspace_hook_layout_for_workspace_get(const WorkSpaceInstanceHook *hook,
- const WorkSpace *workspace)
-{
- return workspace_relation_get_data_matching_parent(&workspace->hook_layout_relations, hook);
-}
-void BKE_workspace_hook_layout_for_workspace_set(WorkSpaceInstanceHook *hook,
- WorkSpace *workspace,
- WorkSpaceLayout *layout)
-{
- hook->act_layout = layout;
- workspace_relation_ensure_updated(&workspace->hook_layout_relations, hook, layout);
-}
/** \} */
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 16e56200131..724c4ab93b2 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -606,7 +606,10 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
c->gop_size = context->ffmpeg_gop_size;
c->max_b_frames = context->ffmpeg_max_b_frames;
- if (context->ffmpeg_crf >= 0) {
+ if (context->ffmpeg_type == FFMPEG_WEBM && context->ffmpeg_crf == 0) {
+ ffmpeg_dict_set_int(&opts, "lossless", 1);
+ }
+ else if (context->ffmpeg_crf >= 0) {
ffmpeg_dict_set_int(&opts, "crf", context->ffmpeg_crf);
}
else {
diff --git a/source/blender/blenlib/BLI_assert.h b/source/blender/blenlib/BLI_assert.h
index b9cb32a310e..603be115b35 100644
--- a/source/blender/blenlib/BLI_assert.h
+++ b/source/blender/blenlib/BLI_assert.h
@@ -69,7 +69,13 @@ extern "C" {
# endif
/* _BLI_ASSERT_ABORT */
# ifdef WITH_ASSERT_ABORT
-# define _BLI_ASSERT_ABORT abort
+# ifdef __GNUC__
+/* Cast to remove 'noreturn' attribute since this suppresses missing return statements,
+ * allowing changes to debug builds to accidentally to break release builds. */
+# define _BLI_ASSERT_ABORT ((void (*)(void))(*(((void **)abort))))
+# else
+# define _BLI_ASSERT_ABORT abort
+# endif
# else
# define _BLI_ASSERT_ABORT() (void)0
# endif
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index af28e826e84..d46c02a961c 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -436,6 +436,7 @@ MINLINE void normal_short_to_float_v3(float r[3], const short n[3]);
MINLINE void normal_float_to_short_v3(short r[3], const float n[3]);
MINLINE void normal_float_to_short_v4(short r[4], const float n[4]);
+void minmax_v4v4_v4(float min[4], float max[4], const float vec[4]);
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3]);
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2]);
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index 64dfdc2ad25..eee304a9b72 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -237,6 +237,82 @@ BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *setti
* Only here for code to be removed. */
int BLI_task_parallel_thread_id(const TaskParallelTLS *tls);
+/* Task Graph Scheduling */
+/* Task Graphs can be used to create a forest of directional trees and schedule work to any tree.
+ * The nodes in the graph can be run in separate threads.
+ *
+ * +---- [root] ----+
+ * | |
+ * v v
+ * [node_1] +---- [node_2] ----+
+ * | |
+ * v v
+ * [node_3] [node_4]
+ *
+ * TaskGraph *task_graph = BLI_task_graph_create();
+ * TaskNode *root = BLI_task_graph_node_create(task_graph, root_exec, NULL, NULL);
+ * TaskNode *node_1 = BLI_task_graph_node_create(task_graph, node_exec, NULL, NULL);
+ * TaskNode *node_2 = BLI_task_graph_node_create(task_graph, node_exec, NULL, NULL);
+ * TaskNode *node_3 = BLI_task_graph_node_create(task_graph, node_exec, NULL, NULL);
+ * TaskNode *node_4 = BLI_task_graph_node_create(task_graph, node_exec, NULL, NULL);
+ *
+ * BLI_task_graph_edge_create(root, node_1);
+ * BLI_task_graph_edge_create(root, node_2);
+ * BLI_task_graph_edge_create(node_2, node_3);
+ * BLI_task_graph_edge_create(node_2, node_4);
+ *
+ * Any node can be triggered to start a chain of tasks. Normally you would trigger a root node but
+ * it is supported to start the chain of tasks anywhere in the forest or tree. When a node
+ * completes, the execution flow is forwarded via the created edges.
+ * When a child node has multiple parents the child node will be triggered once for each parent.
+ *
+ * BLI_task_graph_node_push_work(root);
+ *
+ * In this example After `root` is finished, `node_1` and `node_2` will be started.
+ * Only after `node_2` is finished `node_3` and `node_4` will be started.
+ *
+ * After scheduling work we need to wait until all the tasks have been finished.
+ *
+ * BLI_task_graph_work_and_wait();
+ *
+ * When finished you can clean up all the resources by freeing the task_graph. Nodes are owned by
+ * the graph and are freed task_data will only be freed if a free_func was given.
+ *
+ * BLI_task_graph_free(task_graph);
+ *
+ * Work can enter a tree on any node. Normally this would be the root_node.
+ * A `task_graph` can be reused, but the caller needs to make sure the task_data is reset.
+ *
+ * ** Task-Data **
+ *
+ * Typically you want give a task data to work on.
+ * Task data can be shared with other nodes, but be careful not to free the data multiple times.
+ * Task data is freed when calling `BLI_task_graph_free`.
+ *
+ * MyData *task_data = MEM_callocN(sizeof(MyData), __func__);
+ * TaskNode *root = BLI_task_graph_node_create(task_graph, root_exec, task_data, MEM_freeN);
+ * TaskNode *node_1 = BLI_task_graph_node_create(task_graph, node_exec, task_data, NULL);
+ * TaskNode *node_2 = BLI_task_graph_node_create(task_graph, node_exec, task_data, NULL);
+ * TaskNode *node_3 = BLI_task_graph_node_create(task_graph, node_exec, task_data, NULL);
+ * TaskNode *node_4 = BLI_task_graph_node_create(task_graph, node_exec, task_data, NULL);
+ *
+ */
+struct TaskGraph;
+struct TaskNode;
+
+typedef void (*TaskGraphNodeRunFunction)(void *__restrict task_data);
+typedef void (*TaskGraphNodeFreeFunction)(void *task_data);
+
+struct TaskGraph *BLI_task_graph_create(void);
+void BLI_task_graph_work_and_wait(struct TaskGraph *task_graph);
+void BLI_task_graph_free(struct TaskGraph *task_graph);
+struct TaskNode *BLI_task_graph_node_create(struct TaskGraph *task_graph,
+ TaskGraphNodeRunFunction run,
+ void *task_data,
+ TaskGraphNodeFreeFunction free_func);
+bool BLI_task_graph_node_push_work(struct TaskNode *task_node);
+void BLI_task_graph_edge_create(struct TaskNode *from_node, struct TaskNode *to_node);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 18d58cdcaf3..7757b838afe 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -119,6 +119,7 @@ set(SRC
intern/string_utf8.c
intern/string_utils.c
intern/system.c
+ intern/task_graph.cc
intern/task_iterator.c
intern/task_pool.cc
intern/task_range.cc
@@ -138,7 +139,6 @@ set(SRC
intern/list_sort_impl.h
- BLI_asan.h
BLI_alloca.h
BLI_allocator.hh
BLI_args.h
@@ -148,6 +148,7 @@ set(SRC
BLI_array_store.h
BLI_array_store_utils.h
BLI_array_utils.h
+ BLI_asan.h
BLI_assert.h
BLI_astar.h
BLI_bitmap.h
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 3a07cef7cac..da67baf0ead 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -719,10 +719,10 @@ static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata,
refit_kdop_hull(data->tree, parent, parent_leafs_begin, parent_leafs_end);
split_axis = get_largest_axis(parent->bv);
- /* Save split axis (this can be used on raytracing to speedup the query time) */
+ /* Save split axis (this can be used on ray-tracing to speedup the query time) */
parent->main_axis = split_axis / 2;
- /* Split the childs along the split_axis, note: its not needed to sort the whole leafs array
+ /* Split the children along the split_axis, note: its not needed to sort the whole leafs array
* Only to assure that the elements are partitioned on a way that each child takes the elements
* it would take in case the whole array was sorted.
* Split_leafs takes care of that "sort" problem. */
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index 2ad9b53ba3d..1b388dcf11f 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -360,7 +360,7 @@ MINLINE int divide_floor_i(int a, int b)
}
/**
- * Integer division that ceils the result, instead of flooring like normal C division.
+ * Integer division that returns the ceiling, instead of flooring like normal C division.
*/
MINLINE uint divide_ceil_u(uint a, uint b)
{
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index cc29ebe4f20..c1f7b0c2907 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -91,6 +91,7 @@ void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv, int
break;
case BLI_YUV_ITU_BT709:
default:
+ BLI_assert(colorspace == BLI_YUV_ITU_BT709);
y = 0.2126f * r + 0.7152f * g + 0.0722f * b;
u = -0.09991f * r - 0.33609f * g + 0.436f * b;
v = 0.615f * r - 0.55861f * g - 0.05639f * b;
@@ -113,6 +114,8 @@ void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb, int
b = y + 2.032f * u;
break;
case BLI_YUV_ITU_BT709:
+ default:
+ BLI_assert(colorspace == BLI_YUV_ITU_BT709);
r = y + 1.28033f * v;
g = y - 0.21482f * u - 0.38059f * v;
b = y + 2.12798f * u;
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index a26824bd2b5..e7c1fc8c2d9 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -4220,7 +4220,19 @@ static float mean_value_half_tan_v2(const struct Float2_Len *d_curr,
void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[3])
{
- const float eps = 1e-5f; /* take care, low values cause [#36105] */
+ /* Before starting to calculate the weight, we need to figure out the floating point precision we
+ * can expect from the supplied data. */
+ float max_value = 0;
+
+ for (int i = 0; i < n; i++) {
+ max_value = max_ff(max_value, fabsf(v[i][0] - co[0]));
+ max_value = max_ff(max_value, fabsf(v[i][1] - co[1]));
+ max_value = max_ff(max_value, fabsf(v[i][2] - co[2]));
+ }
+
+ /* These to values we derived by empirically testing different values that works for the test
+ * files in D7772. */
+ const float eps = 16.0f * FLT_EPSILON * max_value;
const float eps_sq = eps * eps;
const float *v_curr, *v_next;
float ht_prev, ht; /* half tangents */
@@ -4293,8 +4305,20 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[
void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[2])
{
- const float eps = 1e-5f; /* take care, low values cause [#36105] */
+ /* Before starting to calculate the weight, we need to figure out the floating point precision we
+ * can expect from the supplied data. */
+ float max_value = 0;
+
+ for (int i = 0; i < n; i++) {
+ max_value = max_ff(max_value, fabsf(v[i][0] - co[0]));
+ max_value = max_ff(max_value, fabsf(v[i][1] - co[1]));
+ }
+
+ /* These to values we derived by empirically testing different values that works for the test
+ * files in D7772. */
+ const float eps = 16.0f * FLT_EPSILON * max_value;
const float eps_sq = eps * eps;
+
const float *v_curr, *v_next;
float ht_prev, ht; /* half tangents */
float totweight = 0.0f;
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 9009f73a62f..6ec7c960d6b 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -949,6 +949,35 @@ void print_vn(const char *str, const float v[], const int n)
printf("\n");
}
+void minmax_v4v4_v4(float min[4], float max[4], const float vec[4])
+{
+ if (min[0] > vec[0]) {
+ min[0] = vec[0];
+ }
+ if (min[1] > vec[1]) {
+ min[1] = vec[1];
+ }
+ if (min[2] > vec[2]) {
+ min[2] = vec[2];
+ }
+ if (min[3] > vec[3]) {
+ min[3] = vec[3];
+ }
+
+ if (max[0] < vec[0]) {
+ max[0] = vec[0];
+ }
+ if (max[1] < vec[1]) {
+ max[1] = vec[1];
+ }
+ if (max[2] < vec[2]) {
+ max[2] = vec[2];
+ }
+ if (max[3] < vec[3]) {
+ max[3] = vec[3];
+ }
+}
+
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
{
if (min[0] > vec[0]) {
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 87536ea8116..fbfb258693b 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -55,6 +55,7 @@
# include "utfconv.h"
# include <direct.h>
# include <io.h>
+# include <shobjidl_core.h>
# include <stdbool.h>
#else
# include <pwd.h>
@@ -226,12 +227,18 @@ size_t BLI_file_size(const char *path)
return stats.st_size;
}
+/* Return file attributes. Apple version of this function is defined in storage_apple.mm */
#ifndef __APPLE__
eFileAttributes BLI_file_attributes(const char *path)
{
int ret = 0;
# ifdef WIN32
+
+ if (BLI_path_extension_check(path, ".lnk")) {
+ return FILE_ATTR_ALIAS;
+ }
+
WCHAR wline[FILE_MAXDIR];
if (conv_utf_8_to_16(path, wline, ARRAY_SIZE(wline)) != 0) {
return ret;
@@ -284,15 +291,52 @@ eFileAttributes BLI_file_attributes(const char *path)
}
#endif
-/**
- * Returns the target path of a file-based redirection, like Mac Alias or Win32 Shortcut file.
- */
+/* Return alias/shortcut file target. Apple version is defined in storage_apple.mm */
#ifndef __APPLE__
-bool BLI_file_alias_target(char UNUSED(target[FILE_MAXDIR]), const char *UNUSED(filepath))
+bool BLI_file_alias_target(char target[FILE_MAXDIR], const char *filepath)
{
- /* TODO: Find target in Win32 Shortcut - Shell Link (.lnk) file.
- * Format: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/ */
+# ifdef WIN32
+ if (!BLI_path_extension_check(filepath, ".lnk")) {
+ return false;
+ }
+
+ IShellLinkW *Shortcut = NULL;
+ bool success = false;
+ CoInitializeEx(NULL, COINIT_MULTITHREADED);
+
+ HRESULT hr = CoCreateInstance(
+ &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (LPVOID *)&Shortcut);
+ if (SUCCEEDED(hr)) {
+ IPersistFile *PersistFile;
+ hr = Shortcut->lpVtbl->QueryInterface(Shortcut, &IID_IPersistFile, (LPVOID *)&PersistFile);
+ if (SUCCEEDED(hr)) {
+ WCHAR path_utf16[FILE_MAXDIR] = {0};
+ if (conv_utf_8_to_16(filepath, path_utf16, ARRAY_SIZE(path_utf16)) == 0) {
+ hr = PersistFile->lpVtbl->Load(PersistFile, path_utf16, STGM_READ);
+ if (SUCCEEDED(hr)) {
+ hr = Shortcut->lpVtbl->Resolve(Shortcut, 0, SLR_NO_UI | SLR_UPDATE);
+ if (SUCCEEDED(hr)) {
+ wchar_t target_utf16[FILE_MAXDIR] = {0};
+ hr = Shortcut->lpVtbl->GetPath(Shortcut, target_utf16, FILE_MAXDIR, NULL, 0);
+ if (SUCCEEDED(hr)) {
+ success = (conv_utf_16_to_8(target_utf16, target, FILE_MAXDIR) == 0);
+ }
+ }
+ PersistFile->lpVtbl->Release(PersistFile);
+ }
+ }
+ }
+ Shortcut->lpVtbl->Release(Shortcut);
+ }
+
+ return (success && target[0]);
+# endif
+
+# ifdef __linux__
+ UNUSED_VARS(target, filepath);
+ /* File-based redirection not supported. */
return false;
+# endif
}
#endif
diff --git a/source/blender/blenlib/intern/task_graph.cc b/source/blender/blenlib/intern/task_graph.cc
new file mode 100644
index 00000000000..4f112c5b2c8
--- /dev/null
+++ b/source/blender/blenlib/intern/task_graph.cc
@@ -0,0 +1,166 @@
+/*
+ * 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 bli
+ *
+ * Task graph.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_task.h"
+
+#include <memory>
+#include <vector>
+
+#ifdef WITH_TBB
+/* Quiet top level deprecation message, unrelated to API usage here. */
+# define TBB_SUPPRESS_DEPRECATED_MESSAGES 1
+# include <tbb/flow_graph.h>
+# include <tbb/tbb.h>
+#endif
+
+/* Task Graph */
+struct TaskGraph {
+#ifdef WITH_TBB
+ tbb::flow::graph tbb_graph;
+#endif
+ std::vector<std::unique_ptr<TaskNode>> nodes;
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("task_graph:TaskGraph")
+#endif
+};
+
+/* TaskNode - a node in the task graph. */
+struct TaskNode {
+ /* TBB Node. */
+#ifdef WITH_TBB
+ tbb::flow::continue_node<tbb::flow::continue_msg> tbb_node;
+#endif
+ /* Successors to execute after this task, for serial execution fallback. */
+ std::vector<TaskNode *> successors;
+
+ /* User function to be executed with given task data. */
+ TaskGraphNodeRunFunction run_func;
+ void *task_data;
+ /* Optional callback to free task data along with the graph. If task data
+ * is shared between nodes, only a single task node should free the data. */
+ TaskGraphNodeFreeFunction free_func;
+
+ TaskNode(TaskGraph *task_graph,
+ TaskGraphNodeRunFunction run_func,
+ void *task_data,
+ TaskGraphNodeFreeFunction free_func)
+ :
+#ifdef WITH_TBB
+ tbb_node(task_graph->tbb_graph,
+ tbb::flow::unlimited,
+ std::bind(&TaskNode::run, this, std::placeholders::_1)),
+#endif
+ run_func(run_func),
+ task_data(task_data),
+ free_func(free_func)
+ {
+#ifndef WITH_TBB
+ UNUSED_VARS(task_graph);
+#endif
+ }
+
+ TaskNode(const TaskNode &other) = delete;
+ TaskNode &operator=(const TaskNode &other) = delete;
+
+ ~TaskNode()
+ {
+ if (task_data && free_func) {
+ free_func(task_data);
+ }
+ }
+
+#ifdef WITH_TBB
+ tbb::flow::continue_msg run(const tbb::flow::continue_msg UNUSED(input))
+ {
+ tbb::this_task_arena::isolate([this] { run_func(task_data); });
+ return tbb::flow::continue_msg();
+ }
+#endif
+
+ void run_serial()
+ {
+ run_func(task_data);
+ for (TaskNode *successor : successors) {
+ successor->run_serial();
+ }
+ }
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("task_graph:TaskNode")
+#endif
+};
+
+TaskGraph *BLI_task_graph_create(void)
+{
+ return new TaskGraph();
+}
+
+void BLI_task_graph_free(TaskGraph *task_graph)
+{
+ delete task_graph;
+}
+
+void BLI_task_graph_work_and_wait(TaskGraph *task_graph)
+{
+#ifdef WITH_TBB
+ task_graph->tbb_graph.wait_for_all();
+#else
+ UNUSED_VARS(task_graph);
+#endif
+}
+
+struct TaskNode *BLI_task_graph_node_create(struct TaskGraph *task_graph,
+ TaskGraphNodeRunFunction run,
+ void *user_data,
+ TaskGraphNodeFreeFunction free_func)
+{
+ TaskNode *task_node = new TaskNode(task_graph, run, user_data, free_func);
+ task_graph->nodes.push_back(std::unique_ptr<TaskNode>(task_node));
+ return task_node;
+}
+
+bool BLI_task_graph_node_push_work(struct TaskNode *task_node)
+{
+#ifdef WITH_TBB
+ if (BLI_task_scheduler_num_threads() > 1) {
+ return task_node->tbb_node.try_put(tbb::flow::continue_msg());
+ }
+#endif
+
+ task_node->run_serial();
+ return true;
+}
+
+void BLI_task_graph_edge_create(struct TaskNode *from_node, struct TaskNode *to_node)
+{
+#ifdef WITH_TBB
+ if (BLI_task_scheduler_num_threads() > 1) {
+ tbb::flow::make_edge(from_node->tbb_node, to_node->tbb_node);
+ return;
+ }
+#endif
+
+ from_node->successors.push_back(to_node);
+}
diff --git a/source/blender/blenloader/BLO_read_write.h b/source/blender/blenloader/BLO_read_write.h
new file mode 100644
index 00000000000..1b86b5668cc
--- /dev/null
+++ b/source/blender/blenloader/BLO_read_write.h
@@ -0,0 +1,210 @@
+/*
+ * 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 blenloader
+ *
+ * This file contains an API that allows different parts of Blender to define what data is stored
+ * in .blend files.
+ *
+ * Four callbacks have to be provided to fully implement .blend I/O for a piece of data. One of
+ * those is related to file writing and three for file reading. Reading requires multiple
+ * callbacks, due to the way linking between files works.
+ *
+ * Brief description of the individual callbacks:
+ * - Blend Write: Define which structs and memory buffers are saved.
+ * - Blend Read Data: Loads structs and memory buffers from file and updates pointers them.
+ * - Blend Read Lib: Updates pointers to ID data blocks.
+ * - Blend Expand: Defines which other data blocks should be loaded (possibly from other files).
+ *
+ * Each of these callbacks uses a different API functions.
+ *
+ * Some parts of Blender, e.g. modifiers, don't require you to implement all four callbacks.
+ * Instead only the first two are necessary. The other two are handled by general ID management. In
+ * the future, we might want to get rid of those two callbacks entirely, but for now they are
+ * necessary.
+ */
+
+#ifndef __BLO_READ_WRITE_H__
+#define __BLO_READ_WRITE_H__
+
+/* for SDNA_TYPE_FROM_STRUCT() macro */
+#include "dna_type_offsets.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct BlendWriter BlendWriter;
+typedef struct BlendDataReader BlendDataReader;
+typedef struct BlendLibReader BlendLibReader;
+typedef struct BlendExpander BlendExpander;
+
+/* Blend Write API
+ * ===============
+ *
+ * Most functions fall into one of two categories. Either they write a DNA struct or a raw memory
+ * buffer to the .blend file.
+ *
+ * It is safe to pass NULL as data_ptr. In this case nothing will be stored.
+ *
+ * DNA Struct Writing
+ * ------------------
+ *
+ * Functions dealing with DNA structs begin with BLO_write_struct_*.
+ *
+ * DNA struct types can be identified in different ways:
+ * - Run-time Name: The name is provided as const char *.
+ * - Compile-time Name: The name is provided at compile time. This is more efficient.
+ * - Struct ID: Every DNA struct type has an integer ID that can be queried with
+ * BLO_get_struct_id_by_name. Providing this ID can be a useful optimization when many structs
+ * of the same type are stored AND if those structs are not in a continuous array.
+ *
+ * Often only a single instance of a struct is written at once. However, sometimes it is necessary
+ * to write arrays or linked lists. Separate functions for that are provided as well.
+ *
+ * There is a special macro for writing id structs: BLO_write_id_struct. Those are handled
+ * differently from other structs.
+ *
+ * Raw Data Writing
+ * ----------------
+ *
+ * At the core there is BLO_write_raw, which can write arbitrary memory buffers to the file. The
+ * code that reads this data might have to correct its byte-order. For the common cases there are
+ * convenience functions that write and read arrays of simple types such as int32. Those will
+ * correct endianness automatically.
+ */
+
+/* Mapping between names and ids. */
+int BLO_get_struct_id_by_name(BlendWriter *writer, const char *struct_name);
+#define BLO_get_struct_id(writer, struct_name) SDNA_TYPE_FROM_STRUCT(struct_name)
+
+/* Write single struct. */
+void BLO_write_struct_by_name(BlendWriter *writer, const char *struct_name, const void *data_ptr);
+void BLO_write_struct_by_id(BlendWriter *writer, int struct_id, const void *data_ptr);
+#define BLO_write_struct(writer, struct_name, data_ptr) \
+ BLO_write_struct_by_id(writer, BLO_get_struct_id(writer, struct_name), data_ptr)
+
+/* Write struct array. */
+void BLO_write_struct_array_by_name(BlendWriter *writer,
+ const char *struct_name,
+ int array_size,
+ const void *data_ptr);
+void BLO_write_struct_array_by_id(BlendWriter *writer,
+ int struct_id,
+ int array_size,
+ const void *data_ptr);
+#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr) \
+ BLO_write_struct_array_by_id( \
+ writer, BLO_get_struct_id(writer, struct_name), array_size, data_ptr)
+
+/* Write struct list. */
+void BLO_write_struct_list_by_name(BlendWriter *writer,
+ const char *struct_name,
+ struct ListBase *list);
+void BLO_write_struct_list_by_id(BlendWriter *writer, int struct_id, struct ListBase *list);
+#define BLO_write_struct_list(writer, struct_name, list_ptr) \
+ BLO_write_struct_list_by_id(writer, BLO_get_struct_id(writer, struct_name), list_ptr)
+
+/* Write id struct. */
+void blo_write_id_struct(BlendWriter *writer,
+ int struct_id,
+ const void *id_address,
+ const struct ID *id);
+#define BLO_write_id_struct(writer, struct_name, id_address, id) \
+ blo_write_id_struct(writer, BLO_get_struct_id(writer, struct_name), id_address, id)
+
+/* Write raw data. */
+void BLO_write_raw(BlendWriter *writer, int size_in_bytes, const void *data_ptr);
+void BLO_write_int32_array(BlendWriter *writer, int size, const int32_t *data_ptr);
+void BLO_write_uint32_array(BlendWriter *writer, int size, const uint32_t *data_ptr);
+void BLO_write_float_array(BlendWriter *writer, int size, const float *data_ptr);
+void BLO_write_float3_array(BlendWriter *writer, int size, const float *data_ptr);
+void BLO_write_pointer_array(BlendWriter *writer, int size, const void *data_ptr);
+void BLO_write_string(BlendWriter *writer, const char *data_ptr);
+
+/* Misc. */
+bool BLO_write_is_undo(BlendWriter *writer);
+
+/* Blend Read Data API
+ * ===================
+ *
+ * Generally, for every BLO_write_* call there should be a corresponding BLO_read_* call.
+ *
+ * Most BLO_read_* functions get a pointer to a pointer as argument. That allows the function to
+ * update the pointer to its new value.
+ *
+ * When the given pointer points to a memory buffer that was not stored in the file, the pointer is
+ * updated to be NULL. When it was pointing to NULL before, it will stay that way.
+ *
+ * Examples of matching calls:
+ * BLO_write_struct(writer, ClothSimSettings, clmd->sim_parms);
+ * BLO_read_data_address(reader, &clmd->sim_parms);
+ *
+ * BLO_write_struct_list(writer, TimeMarker, &action->markers);
+ * BLO_read_list(reader, &action->markers, NULL);
+ *
+ * BLO_write_int32_array(writer, hmd->totindex, hmd->indexar);
+ * BLO_read_int32_array(reader, hmd->totindex, &hmd->indexar);
+ */
+
+void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address);
+
+#define BLO_read_data_address(reader, ptr_p) \
+ *(ptr_p) = BLO_read_get_new_data_address((reader), *(ptr_p))
+
+typedef void (*BlendReadListFn)(BlendDataReader *reader, void *data);
+void BLO_read_list(BlendDataReader *reader, struct ListBase *list, BlendReadListFn callback);
+
+/* Update data pointers and correct byte-order if necessary. */
+void BLO_read_int32_array(BlendDataReader *reader, int array_size, int32_t **ptr_p);
+void BLO_read_uint32_array(BlendDataReader *reader, int array_size, uint32_t **ptr_p);
+void BLO_read_float_array(BlendDataReader *reader, int array_size, float **ptr_p);
+void BLO_read_float3_array(BlendDataReader *reader, int array_size, float **ptr_p);
+void BLO_read_double_array(BlendDataReader *reader, int array_size, double **ptr_p);
+void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p);
+
+/* Misc. */
+bool BLO_read_requires_endian_switch(BlendDataReader *reader);
+
+/* Blend Read Lib API
+ * ===================
+ *
+ * This API does almost the same as the Blend Read Data API. However, now only pointers to ID data
+ * blocks are updated.
+ */
+
+ID *BLO_read_get_new_id_address(BlendLibReader *reader, struct Library *lib, struct ID *id);
+
+#define BLO_read_id_address(reader, lib, id_ptr_p) \
+ *(id_ptr_p) = (void *)BLO_read_get_new_id_address((reader), (lib), (ID *)*(id_ptr_p))
+
+/* Blend Expand API
+ * ===================
+ *
+ * BLO_expand has to be called for every data block that should be loaded. If the data block is in
+ * a separate .blend file, it will be pulled from there.
+ */
+
+void BLO_expand_id(BlendExpander *expander, struct ID *id);
+
+#define BLO_expand(expander, id) BLO_expand_id(expander, (struct ID *)id)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BLO_READ_WRITE_H__ */
diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h
index f280b8f3b9c..f9300f8a521 100644
--- a/source/blender/blenloader/BLO_undofile.h
+++ b/source/blender/blenloader/BLO_undofile.h
@@ -26,6 +26,7 @@
*/
struct Scene;
+struct GHash;
typedef struct {
void *next, *prev;
@@ -38,6 +39,9 @@ typedef struct {
* detect unchanged IDs).
* Defined when writing the next step (i.e. last undo step has those always false). */
bool is_identical_future;
+ /** Session UUID of the ID being currently written (MAIN_ID_SESSION_UUID_UNSET when not writing
+ * ID-related data). Used to find matching chunks in previous memundo step. */
+ uint id_session_uuid;
} MemFileChunk;
typedef struct MemFile {
@@ -45,6 +49,17 @@ typedef struct MemFile {
size_t size;
} MemFile;
+typedef struct MemFileWriteData {
+ MemFile *written_memfile;
+ MemFile *reference_memfile;
+
+ uint current_id_session_uuid;
+ MemFileChunk *reference_current_chunk;
+
+ /** Maps an ID session uuid to its first reference MemFileChunk, if existing. */
+ struct GHash *id_session_uuid_mapping;
+} MemFileWriteData;
+
typedef struct MemFileUndoData {
char filename[1024]; /* FILE_MAX */
MemFile memfile;
@@ -52,10 +67,13 @@ typedef struct MemFileUndoData {
} MemFileUndoData;
/* actually only used writefile.c */
-extern void memfile_chunk_add(MemFile *memfile,
- const char *buf,
- unsigned int size,
- MemFileChunk **compchunk_step);
+
+void BLO_memfile_write_init(MemFileWriteData *mem_data,
+ MemFile *written_memfile,
+ MemFile *reference_memfile);
+void BLO_memfile_write_finalize(MemFileWriteData *mem_data);
+
+void BLO_memfile_chunk_add(MemFileWriteData *mem_data, const char *buf, unsigned int size);
/* exports */
extern void BLO_memfile_free(MemFile *memfile);
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 1555b9231ed..09e2f4bf417 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -64,6 +64,7 @@ set(SRC
BLO_blend_defs.h
BLO_blend_validate.h
BLO_readfile.h
+ BLO_read_write.h
BLO_undofile.h
BLO_writefile.h
intern/readfile.h
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index adf7db0267e..1309b3e3c33 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -428,41 +428,6 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain,
* but oldmain itself shall *never* be 'transferred' to new mainlist! */
BLI_assert(old_mainlist.first == oldmain);
- if (bfd && old_mainlist.first != old_mainlist.last) {
- /* Even though directly used libs have been already moved to new main,
- * indirect ones have not.
- * This is a bit annoying, but we have no choice but to keep them all for now -
- * means some now unused data may remain in memory, but think we'll have to live with it. */
- Main *libmain, *libmain_next;
- Main *newmain = bfd->main;
- ListBase new_mainlist = {newmain, newmain};
-
- for (libmain = oldmain->next; libmain; libmain = libmain_next) {
- libmain_next = libmain->next;
- /* Note that LIB_INDIRECT does not work with libraries themselves, so we use non-NULL
- * parent to detect indirect-linked ones. */
- if (libmain->curlib && (libmain->curlib->parent != NULL)) {
- BLI_remlink(&old_mainlist, libmain);
- BLI_addtail(&new_mainlist, libmain);
- }
- else {
-#ifdef PRINT_DEBUG
- printf("Dropped Main for lib: %s\n", libmain->curlib->id.name);
-#endif
- }
- }
- /* In any case, we need to move all lib data-blocks themselves - those are
- * 'first level data', getting rid of them would imply updating spaces & co
- * to prevent invalid pointers access. */
- BLI_movelisttolist(&newmain->libraries, &oldmain->libraries);
-
- blo_join_main(&new_mainlist);
- }
-
-#if 0
- printf("Remaining mains/libs in oldmain: %d\n", BLI_listbase_count(&fd->old_mainlist) - 1);
-#endif
-
/* That way, libs (aka mains) we did not reuse in new undone/redone state
* will be cleared together with oldmain... */
blo_join_main(&old_mainlist);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index b661a1e7696..53502a8138a 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -160,6 +160,7 @@
#include "BLO_blend_defs.h"
#include "BLO_blend_validate.h"
+#include "BLO_read_write.h"
#include "BLO_readfile.h"
#include "BLO_undofile.h"
@@ -691,7 +692,7 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
/* Important, consistency with main ID reading code from read_libblock(). */
lib->id.us = ID_FAKE_USERS(lib);
- /* Matches lib_link_library(). */
+ /* Matches direct_link_library(). */
id_us_ensure_real(&lib->id);
BLI_strncpy(lib->name, filepath, sizeof(lib->name));
@@ -713,6 +714,20 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
/** \name File Parsing
* \{ */
+typedef struct BlendDataReader {
+ FileData *fd;
+} BlendDataReader;
+
+typedef struct BlendLibReader {
+ FileData *fd;
+ Main *main;
+} BlendLibReader;
+
+typedef struct BlendExpander {
+ FileData *fd;
+ Main *main;
+} BlendExpander;
+
static void switch_endian_bh4(BHead4 *bhead)
{
/* the ID_.. codes */
@@ -2890,8 +2905,8 @@ static void direct_link_id_common(
id->tag = tag;
if (tag & LIB_TAG_ID_LINK_PLACEHOLDER) {
- /* For placeholder we only need to set the tag and properly init generic ID fieds above, no
- * further data to read. */
+ /* For placeholder we only need to set the tag and properly initialize generic ID fields above,
+ * no further data to read. */
return;
}
@@ -3415,11 +3430,6 @@ static void lib_link_nladata_strips(FileData *fd, ID *id, ListBase *list)
/* reassign the counted-reference to action */
strip->act = newlibadr(fd, id->lib, strip->act);
-
- /* fix action id-root (i.e. if it comes from a pre 2.57 .blend file) */
- if ((strip->act) && (strip->act->idroot == 0)) {
- strip->act->idroot = GS(id->name);
- }
}
}
@@ -3514,14 +3524,6 @@ static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt)
adt->action = newlibadr(fd, id->lib, adt->action);
adt->tmpact = newlibadr(fd, id->lib, adt->tmpact);
- /* fix action id-roots (i.e. if they come from a pre 2.57 .blend file) */
- if ((adt->action) && (adt->action->idroot == 0)) {
- adt->action->idroot = GS(id->name);
- }
- if ((adt->tmpact) && (adt->tmpact->idroot == 0)) {
- adt->tmpact->idroot = GS(id->name);
- }
-
/* link drivers */
lib_link_fcurves(fd, id, &adt->drivers);
@@ -3592,15 +3594,11 @@ static void direct_link_cachefile(FileData *fd, CacheFile *cache_file)
static void lib_link_workspaces(FileData *fd, Main *bmain, WorkSpace *workspace)
{
- ListBase *layouts = BKE_workspace_layouts_get(workspace);
ID *id = (ID *)workspace;
- id_us_ensure_real(id);
-
- for (WorkSpaceLayout *layout = layouts->first, *layout_next; layout; layout = layout_next) {
+ LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout, &workspace->layouts) {
layout->screen = newlibadr(fd, id->lib, layout->screen);
- layout_next = layout->next;
if (layout->screen) {
if (ID_IS_LINKED(id)) {
layout->screen->winid = 0;
@@ -3620,16 +3618,14 @@ static void lib_link_workspaces(FileData *fd, Main *bmain, WorkSpace *workspace)
static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main *main)
{
- link_list(fd, BKE_workspace_layouts_get(workspace));
+ link_list(fd, &workspace->layouts);
link_list(fd, &workspace->hook_layout_relations);
link_list(fd, &workspace->owner_ids);
link_list(fd, &workspace->tools);
LISTBASE_FOREACH (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) {
-
/* data from window - need to access through global oldnew-map */
relation->parent = newglobadr(fd, relation->parent);
-
relation->value = newdataadr(fd, relation->value);
}
@@ -3637,11 +3633,7 @@ static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main
* when reading windows, so have to update windows after/when reading workspaces. */
for (wmWindowManager *wm = main->wm.first; wm; wm = wm->id.next) {
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
- WorkSpaceLayout *act_layout = newdataadr(
- fd, BKE_workspace_active_layout_get(win->workspace_hook));
- if (act_layout) {
- BKE_workspace_active_layout_set(win->workspace_hook, act_layout);
- }
+ win->workspace_hook->act_layout = newdataadr(fd, win->workspace_hook->act_layout);
}
}
@@ -3652,6 +3644,8 @@ static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main
}
workspace->status_text = NULL;
+
+ id_us_ensure_real(&workspace->id);
}
static void lib_link_workspace_instance_hook(FileData *fd, WorkSpaceInstanceHook *hook, ID *id)
@@ -3897,23 +3891,23 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
}
#if 0
- if (ntree->previews) {
- bNodeInstanceHash* new_previews = BKE_node_instance_hash_new("node previews");
- bNodeInstanceHashIterator iter;
-
- NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
- bNodePreview* preview = BKE_node_instance_hash_iterator_get_value(&iter);
- if (preview) {
- bNodePreview* new_preview = newimaadr(fd, preview);
- if (new_preview) {
- bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
- BKE_node_instance_hash_insert(new_previews, key, new_preview);
- }
- }
- }
- BKE_node_instance_hash_free(ntree->previews, NULL);
- ntree->previews = new_previews;
- }
+ if (ntree->previews) {
+ bNodeInstanceHash* new_previews = BKE_node_instance_hash_new("node previews");
+ bNodeInstanceHashIterator iter;
+
+ NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
+ bNodePreview* preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ if (preview) {
+ bNodePreview* new_preview = newimaadr(fd, preview);
+ if (new_preview) {
+ bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+ BKE_node_instance_hash_insert(new_previews, key, new_preview);
+ }
+ }
+ }
+ BKE_node_instance_hash_free(ntree->previews, NULL);
+ ntree->previews = new_previews;
+ }
#else
/* XXX TODO */
ntree->previews = NULL;
@@ -4363,10 +4357,10 @@ static void direct_link_text(FileData *fd, Text *text)
text->compiled = NULL;
#if 0
- if (text->flags & TXT_ISEXT) {
- BKE_text_reload(text);
- }
- /* else { */
+ if (text->flags & TXT_ISEXT) {
+ BKE_text_reload(text);
+ }
+ /* else { */
#endif
link_list(fd, &text->lines);
@@ -5354,7 +5348,7 @@ static void lib_link_object(FileData *fd, Main *bmain, Object *ob)
* some leaked memory rather then crashing immediately
* while bad this _is_ an exceptional case - campbell */
#if 0
- BKE_pose_free(ob->pose);
+ BKE_pose_free(ob->pose);
#else
MEM_freeN(ob->pose);
#endif
@@ -5831,15 +5825,15 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb, Object *ob)
else if (md->type == eModifierType_Collision) {
CollisionModifierData *collmd = (CollisionModifierData *)md;
#if 0
- // TODO: CollisionModifier should use pointcache
- // + have proper reset events before enabling this
- collmd->x = newdataadr(fd, collmd->x);
- collmd->xnew = newdataadr(fd, collmd->xnew);
- collmd->mfaces = newdataadr(fd, collmd->mfaces);
-
- collmd->current_x = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_x");
- collmd->current_xnew = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_xnew");
- collmd->current_v = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_v");
+ // TODO: CollisionModifier should use pointcache
+ // + have proper reset events before enabling this
+ collmd->x = newdataadr(fd, collmd->x);
+ collmd->xnew = newdataadr(fd, collmd->xnew);
+ collmd->mfaces = newdataadr(fd, collmd->mfaces);
+
+ collmd->current_x = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_x");
+ collmd->current_xnew = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_xnew");
+ collmd->current_v = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_v");
#endif
collmd->x = NULL;
@@ -6962,7 +6956,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
direct_link_paint(fd, sce, &sce->toolsettings->imapaint.paint);
- sce->toolsettings->imapaint.paintcursor = NULL;
sce->toolsettings->particle.paintcursor = NULL;
sce->toolsettings->particle.scene = NULL;
sce->toolsettings->particle.object = NULL;
@@ -7545,10 +7538,10 @@ static void direct_link_area(FileData *fd, ScrArea *area)
* so sacrifice a few old files for now to avoid crashes with new files!
* committed: r28002 */
#if 0
- sima->gpd = newdataadr(fd, sima->gpd);
- if (sima->gpd) {
- direct_link_gpencil(fd, sima->gpd);
- }
+ sima->gpd = newdataadr(fd, sima->gpd);
+ if (sima->gpd) {
+ direct_link_gpencil(fd, sima->gpd);
+ }
#endif
}
else if (sl->spacetype == SPACE_NODE) {
@@ -7579,10 +7572,10 @@ static void direct_link_area(FileData *fd, ScrArea *area)
* simple return NULL here (sergey)
*/
#if 0
- if (sseq->gpd) {
- sseq->gpd = newdataadr(fd, sseq->gpd);
- direct_link_gpencil(fd, sseq->gpd);
- }
+ if (sseq->gpd) {
+ sseq->gpd = newdataadr(fd, sseq->gpd);
+ direct_link_gpencil(fd, sseq->gpd);
+ }
#endif
sseq->scopes.reference_ibuf = NULL;
sseq->scopes.zebra_ibuf = NULL;
@@ -8269,11 +8262,11 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map,
sima->iuser.scene = NULL;
#if 0
- /* Those are allocated and freed by space code, no need to handle them here. */
- MEM_SAFE_FREE(sima->scopes.waveform_1);
- MEM_SAFE_FREE(sima->scopes.waveform_2);
- MEM_SAFE_FREE(sima->scopes.waveform_3);
- MEM_SAFE_FREE(sima->scopes.vecscope);
+ /* Those are allocated and freed by space code, no need to handle them here. */
+ MEM_SAFE_FREE(sima->scopes.waveform_1);
+ MEM_SAFE_FREE(sima->scopes.waveform_2);
+ MEM_SAFE_FREE(sima->scopes.waveform_3);
+ MEM_SAFE_FREE(sima->scopes.vecscope);
#endif
sima->scopes.ok = 0;
@@ -8424,9 +8417,7 @@ void blo_lib_link_restore(Main *oldmain,
for (WorkSpace *workspace = newmain->workspaces.first; workspace;
workspace = workspace->id.next) {
- ListBase *layouts = BKE_workspace_layouts_get(workspace);
-
- LISTBASE_FOREACH (WorkSpaceLayout *, layout, layouts) {
+ LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
lib_link_workspace_layout_restore(id_map, newmain, layout);
}
}
@@ -8574,11 +8565,12 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
newmain->curlib = lib;
lib->parent = NULL;
+
+ id_us_ensure_real(&lib->id);
}
-static void lib_link_library(FileData *UNUSED(fd), Main *UNUSED(bmain), Library *lib)
+static void lib_link_library(FileData *UNUSED(fd), Main *UNUSED(bmain), Library *UNUSED(lib))
{
- id_us_ensure_real(&lib->id);
}
/* Always call this once you have loaded new library data to set the relative paths correctly
@@ -8646,8 +8638,8 @@ static void direct_link_speaker(FileData *fd, Speaker *spk)
direct_link_animdata(fd, spk->adt);
#if 0
- spk->sound = newdataadr(fd, spk->sound);
- direct_link_sound(fd, spk->sound);
+ spk->sound = newdataadr(fd, spk->sound);
+ direct_link_sound(fd, spk->sound);
#endif
}
@@ -9521,12 +9513,12 @@ static BHead *read_data_into_datamap(FileData *fd, BHead *bhead, const char *all
while (bhead && bhead->code == DATA) {
void *data;
#if 0
- /* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */
- short* sp = fd->filesdna->structs[bhead->SDNAnr];
- char* tmp = malloc(100);
- allocname = fd->filesdna->types[sp[0]];
- strcpy(tmp, allocname);
- data = read_struct(fd, bhead, tmp);
+ /* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */
+ short* sp = fd->filesdna->structs[bhead->SDNAnr];
+ char* tmp = malloc(100);
+ allocname = fd->filesdna->types[sp[0]];
+ strcpy(tmp, allocname);
+ data = read_struct(fd, bhead, tmp);
#else
data = read_struct(fd, bhead, allocname);
#endif
@@ -9732,7 +9724,7 @@ static bool read_libblock_undo_restore(
}
/* Restore local datablocks. */
- DEBUG_PRINTF("UNDO: read %s (uuid %d) -> ", id->name, id->session_uuid);
+ DEBUG_PRINTF("UNDO: read %s (uuid %u) -> ", id->name, id->session_uuid);
ID *id_old = NULL;
const bool do_partial_undo = (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0;
@@ -10053,6 +10045,7 @@ static void do_versions_after_linking(Main *main, ReportList *reports)
do_versions_after_linking_260(main);
do_versions_after_linking_270(main);
do_versions_after_linking_280(main, reports);
+ do_versions_after_linking_290(main, reports);
do_versions_after_linking_cycles(main);
main->is_locked_for_linking = false;
@@ -10600,7 +10593,7 @@ static BHead *find_previous_lib(FileData *fd, BHead *bhead)
static BHead *find_bhead(FileData *fd, void *old)
{
#if 0
- BHead* bhead;
+ BHead* bhead;
#endif
struct BHeadSort *bhs, bhs_s;
@@ -10620,11 +10613,11 @@ static BHead *find_bhead(FileData *fd, void *old)
}
#if 0
- for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
- if (bhead->old == old) {
- return bhead;
- }
- }
+ for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
+ if (bhead->old == old) {
+ return bhead;
+ }
+ }
#endif
return NULL;
@@ -10755,9 +10748,9 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
/* Commented because this can print way too much. */
#if 0
- if (G.debug & G_DEBUG) {
- printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->name);
- }
+ if (G.debug & G_DEBUG) {
+ printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->name);
+ }
#endif
}
@@ -11637,9 +11630,7 @@ static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd)
static void expand_workspace(FileData *fd, Main *mainvar, WorkSpace *workspace)
{
- ListBase *layouts = BKE_workspace_layouts_get(workspace);
-
- LISTBASE_FOREACH (WorkSpaceLayout *, layout, layouts) {
+ LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
expand_doit(fd, mainvar, BKE_workspace_layout_screen_get(layout));
}
}
@@ -12623,9 +12614,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
/* Does this library have any more linked data-blocks we need to read? */
if (has_linked_ids_to_read(mainptr)) {
#if 0
- printf("Reading linked data-blocks from %s (%s)\n",
- mainptr->curlib->id.name,
- mainptr->curlib->name);
+ printf("Reading linked data-blocks from %s (%s)\n",
+ mainptr->curlib->id.name,
+ mainptr->curlib->name);
#endif
/* Open file if it has not been done yet. */
@@ -12689,4 +12680,164 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
BKE_main_free(main_newid);
}
+void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address)
+{
+ return newdataadr(reader->fd, old_address);
+}
+
+ID *BLO_read_get_new_id_address(BlendLibReader *reader, Library *lib, ID *id)
+{
+ return newlibadr(reader->fd, lib, id);
+}
+
+bool BLO_read_requires_endian_switch(BlendDataReader *reader)
+{
+ return (reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
+}
+
+/**
+ * Updates all ->prev and ->next pointers of the list elements.
+ * Updates the list->first and list->last pointers.
+ * When not NULL, calls the callback on every element.
+ */
+void BLO_read_list(BlendDataReader *reader, ListBase *list, BlendReadListFn callback)
+{
+ if (BLI_listbase_is_empty(list)) {
+ return;
+ }
+
+ BLO_read_data_address(reader, &list->first);
+ if (callback != NULL) {
+ callback(reader, list->first);
+ }
+ Link *ln = list->first;
+ Link *prev = NULL;
+ while (ln) {
+ BLO_read_data_address(reader, &ln->next);
+ if (ln->next != NULL && callback != NULL) {
+ callback(reader, ln->next);
+ }
+ ln->prev = prev;
+ prev = ln;
+ ln = ln->next;
+ }
+ list->last = prev;
+}
+
+void BLO_read_int32_array(BlendDataReader *reader, int array_size, int32_t **ptr_p)
+{
+ BLO_read_data_address(reader, ptr_p);
+ if (BLO_read_requires_endian_switch(reader)) {
+ BLI_endian_switch_int32_array(*ptr_p, array_size);
+ }
+}
+
+void BLO_read_uint32_array(BlendDataReader *reader, int array_size, uint32_t **ptr_p)
+{
+ BLO_read_data_address(reader, ptr_p);
+ if (BLO_read_requires_endian_switch(reader)) {
+ BLI_endian_switch_uint32_array(*ptr_p, array_size);
+ }
+}
+
+void BLO_read_float_array(BlendDataReader *reader, int array_size, float **ptr_p)
+{
+ BLO_read_data_address(reader, ptr_p);
+ if (BLO_read_requires_endian_switch(reader)) {
+ BLI_endian_switch_float_array(*ptr_p, array_size);
+ }
+}
+
+void BLO_read_float3_array(BlendDataReader *reader, int array_size, float **ptr_p)
+{
+ BLO_read_float_array(reader, array_size * 3, ptr_p);
+}
+
+void BLO_read_double_array(BlendDataReader *reader, int array_size, double **ptr_p)
+{
+ BLO_read_data_address(reader, ptr_p);
+ if (BLO_read_requires_endian_switch(reader)) {
+ BLI_endian_switch_double_array(*ptr_p, array_size);
+ }
+}
+
+static void convert_pointer_array_64_to_32(BlendDataReader *reader,
+ uint array_size,
+ const uint64_t *src,
+ uint32_t *dst)
+{
+ /* Match pointer conversion rules from bh4_from_bh8 and cast_pointer. */
+ if (BLO_read_requires_endian_switch(reader)) {
+ for (int i = 0; i < array_size; i++) {
+ uint64_t ptr = src[i];
+ BLI_endian_switch_uint64(&ptr);
+ dst[i] = (uint32_t)(ptr >> 3);
+ }
+ }
+ else {
+ for (int i = 0; i < array_size; i++) {
+ dst[i] = (uint32_t)(src[i] >> 3);
+ }
+ }
+}
+
+static void convert_pointer_array_32_to_64(BlendDataReader *UNUSED(reader),
+ uint array_size,
+ const uint32_t *src,
+ uint64_t *dst)
+{
+ /* Match pointer conversion rules from bh8_from_bh4 and cast_pointer. */
+ for (int i = 0; i < array_size; i++) {
+ dst[i] = src[i];
+ }
+}
+
+void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p)
+{
+ FileData *fd = reader->fd;
+
+ void *orig_array = newdataadr(fd, *ptr_p);
+ if (orig_array == NULL) {
+ *ptr_p = NULL;
+ return;
+ }
+
+ int file_pointer_size = fd->filesdna->pointer_size;
+ int current_pointer_size = fd->memsdna->pointer_size;
+
+ /* Overallocation is fine, but might be better to pass the length as parameter. */
+ int array_size = MEM_allocN_len(orig_array) / file_pointer_size;
+
+ void *final_array = NULL;
+
+ if (file_pointer_size == current_pointer_size) {
+ /* No pointer conversion necessary. */
+ final_array = orig_array;
+ }
+ else if (file_pointer_size == 8 && current_pointer_size == 4) {
+ /* Convert pointers from 64 to 32 bit. */
+ final_array = MEM_malloc_arrayN(array_size, 4, "new pointer array");
+ convert_pointer_array_64_to_32(
+ reader, array_size, (uint64_t *)orig_array, (uint32_t *)final_array);
+ MEM_freeN(orig_array);
+ }
+ else if (file_pointer_size == 4 && current_pointer_size == 8) {
+ /* Convert pointers from 32 to 64 bit. */
+ final_array = MEM_malloc_arrayN(array_size, 8, "new pointer array");
+ convert_pointer_array_32_to_64(
+ reader, array_size, (uint32_t *)orig_array, (uint64_t *)final_array);
+ MEM_freeN(orig_array);
+ }
+ else {
+ BLI_assert(false);
+ }
+
+ *ptr_p = final_array;
+}
+
+void BLO_expand_id(BlendExpander *expander, ID *id)
+{
+ expand_doit(expander->fd, expander->main, id);
+}
+
/** \} */
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index 55abbe703de..f698d642e33 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -205,7 +205,8 @@ void blo_do_versions_cycles(struct FileData *fd, struct Library *lib, struct Mai
void do_versions_after_linking_250(struct Main *bmain);
void do_versions_after_linking_260(struct Main *bmain);
void do_versions_after_linking_270(struct Main *bmain);
-void do_versions_after_linking_280(struct Main *bmain, ReportList *reports);
+void do_versions_after_linking_280(struct Main *bmain, struct ReportList *reports);
+void do_versions_after_linking_290(struct Main *bmain, struct ReportList *reports);
void do_versions_after_linking_cycles(struct Main *bmain);
#endif
diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c
index c7057883f88..62ffbcc874b 100644
--- a/source/blender/blenloader/intern/undofile.c
+++ b/source/blender/blenloader/intern/undofile.c
@@ -41,10 +41,12 @@
#include "DNA_listBase.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
#include "BLO_readfile.h"
#include "BLO_undofile.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
/* keep last */
@@ -70,25 +72,36 @@ void BLO_memfile_free(MemFile *memfile)
/* result is that 'first' is being freed */
void BLO_memfile_merge(MemFile *first, MemFile *second)
{
- MemFileChunk *fc, *sc;
+ /* We use this mapping to store the memory buffers from second memfile chunks which are not owned
+ * by it (i.e. shared with some previous memory steps). */
+ GHash *buffer_to_second_memchunk = BLI_ghash_new(
+ BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- fc = first->chunks.first;
- sc = second->chunks.first;
- while (fc || sc) {
- if (fc && sc) {
- if (sc->is_identical) {
+ /* First, detect all memchunks in second memfile that are not owned by it. */
+ for (MemFileChunk *sc = second->chunks.first; sc != NULL; sc = sc->next) {
+ if (sc->is_identical) {
+ BLI_ghash_insert(buffer_to_second_memchunk, (void *)sc->buf, sc);
+ }
+ }
+
+ /* Now, check all chunks from first memfile (the one we are removing), and if a memchunk owned by
+ * it is also used by the second memfile, transfer the ownership. */
+ for (MemFileChunk *fc = first->chunks.first; fc != NULL; fc = fc->next) {
+ if (!fc->is_identical) {
+ MemFileChunk *sc = BLI_ghash_lookup(buffer_to_second_memchunk, fc->buf);
+ if (sc != NULL) {
+ BLI_assert(sc->is_identical);
sc->is_identical = false;
fc->is_identical = true;
}
- }
- if (fc) {
- fc = fc->next;
- }
- if (sc) {
- sc = sc->next;
+ /* Note that if the second memfile does not use that chunk, we assume that the first one
+ * fully owns it without sharing it with any other memfile, and hence it should be freed with
+ * it. */
}
}
+ BLI_ghash_free(buffer_to_second_memchunk, NULL, NULL);
+
BLO_memfile_free(first);
}
@@ -100,8 +113,52 @@ void BLO_memfile_clear_future(MemFile *memfile)
}
}
-void memfile_chunk_add(MemFile *memfile, const char *buf, uint size, MemFileChunk **compchunk_step)
+void BLO_memfile_write_init(MemFileWriteData *mem_data,
+ MemFile *written_memfile,
+ MemFile *reference_memfile)
{
+ mem_data->written_memfile = written_memfile;
+ mem_data->reference_memfile = reference_memfile;
+ mem_data->reference_current_chunk = reference_memfile ? reference_memfile->chunks.first : NULL;
+
+ /* If we have a reference memfile, we generate a mapping between the session_uuid's of the
+ * IDs stored in that previous undo step, and its first matching memchunk. This will allow
+ * us to easily find the existing undo memory storage of IDs even when some re-ordering in
+ * current Main data-base broke the order matching with the memchunks from previous step.
+ */
+ if (reference_memfile != NULL) {
+ mem_data->id_session_uuid_mapping = BLI_ghash_new(
+ BLI_ghashutil_inthash_p_simple, BLI_ghashutil_intcmp, __func__);
+ uint current_session_uuid = MAIN_ID_SESSION_UUID_UNSET;
+ LISTBASE_FOREACH (MemFileChunk *, mem_chunk, &reference_memfile->chunks) {
+ if (!ELEM(mem_chunk->id_session_uuid, MAIN_ID_SESSION_UUID_UNSET, current_session_uuid)) {
+ current_session_uuid = mem_chunk->id_session_uuid;
+ void **entry;
+ if (!BLI_ghash_ensure_p(mem_data->id_session_uuid_mapping,
+ POINTER_FROM_UINT(current_session_uuid),
+ &entry)) {
+ *entry = mem_chunk;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
+ }
+}
+
+void BLO_memfile_write_finalize(MemFileWriteData *mem_data)
+{
+ if (mem_data->id_session_uuid_mapping != NULL) {
+ BLI_ghash_free(mem_data->id_session_uuid_mapping, NULL, NULL);
+ }
+}
+
+void BLO_memfile_chunk_add(MemFileWriteData *mem_data, const char *buf, uint size)
+{
+ MemFile *memfile = mem_data->written_memfile;
+ MemFileChunk **compchunk_step = &mem_data->reference_current_chunk;
+
MemFileChunk *curchunk = MEM_mallocN(sizeof(MemFileChunk), "MemFileChunk");
curchunk->size = size;
curchunk->buf = NULL;
@@ -110,6 +167,7 @@ void memfile_chunk_add(MemFile *memfile, const char *buf, uint size, MemFileChun
* perform an undo push may make changes after the last undo push that
* will then not be undo. Though it's not entirely clear that is wrong behavior. */
curchunk->is_identical_future = true;
+ curchunk->id_session_uuid = mem_data->current_id_session_uuid;
BLI_addtail(&memfile->chunks, curchunk);
/* we compare compchunk with buf */
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 62cda5d8feb..eaeef0d52c1 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -61,6 +61,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BKE_anim_data.h"
#include "BKE_anim_visualization.h"
#include "BKE_armature.h"
#include "BKE_colortools.h"
@@ -2352,4 +2353,32 @@ void do_versions_after_linking_250(Main *bmain)
}
FOREACH_NODETREE_END;
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 258, 0)) {
+ /* Some very old (original comments claim pre-2.57) versioning that was wrongly done in
+ * lib-linking code... Putting it here just to be sure (this is also checked at runtime anyway
+ * by `action_idcode_patch_check`). */
+ ID *id;
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt != NULL) {
+ /* Fix actions' id-roots (i.e. if they come from a pre 2.57 .blend file). */
+ if ((adt->action) && (adt->action->idroot == 0)) {
+ adt->action->idroot = GS(id->name);
+ }
+ if ((adt->tmpact) && (adt->tmpact->idroot == 0)) {
+ adt->tmpact->idroot = GS(id->name);
+ }
+
+ LISTBASE_FOREACH (NlaTrack *, nla_track, &adt->nla_tracks) {
+ LISTBASE_FOREACH (NlaStrip *, nla_strip, &nla_track->strips) {
+ if ((nla_strip->act) && (nla_strip->act->idroot == 0)) {
+ nla_strip->act->idroot = GS(id->name);
+ }
+ }
+ }
+ }
+ }
+ FOREACH_MAIN_ID_END;
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index e32a40e1ad5..6211c58d7d4 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -257,7 +257,7 @@ static void do_version_workspaces_after_lib_link(Main *bmain)
win->workspace_hook = BKE_workspace_instance_hook_create(bmain);
BKE_workspace_active_set(win->workspace_hook, workspace);
- BKE_workspace_active_layout_set(win->workspace_hook, layout);
+ BKE_workspace_active_layout_set(win->workspace_hook, workspace, layout);
/* Move scene and view layer to window. */
Scene *scene = screen->scene;
@@ -759,7 +759,7 @@ static void do_version_bbone_scale_fcurve_fix(ListBase *curves, FCurve *fcu)
/* Update F-Curve's path. */
if (replace_bbone_scale_rnapath(&fcu->rna_path)) {
/* If matched, duplicate the curve and tweak name. */
- FCurve *second = copy_fcurve(fcu);
+ FCurve *second = BKE_fcurve_copy(fcu);
second->rna_path[strlen(second->rna_path) - 1] = 'y';
@@ -1737,144 +1737,6 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
}
}
- if (!MAIN_VERSION_ATLEAST(bmain, 290, 1)) {
- /* Patch old grease pencil modifiers material filter. */
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
- switch (md->type) {
- case eGpencilModifierType_Array: {
- ArrayGpencilModifierData *gpmd = (ArrayGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Color: {
- ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Hook: {
- HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Lattice: {
- LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Mirror: {
- MirrorGpencilModifierData *gpmd = (MirrorGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Multiply: {
- MultiplyGpencilModifierData *gpmd = (MultiplyGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Noise: {
- NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Offset: {
- OffsetGpencilModifierData *gpmd = (OffsetGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Opacity: {
- OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Simplify: {
- SimplifyGpencilModifierData *gpmd = (SimplifyGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Smooth: {
- SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Subdiv: {
- SubdivGpencilModifierData *gpmd = (SubdivGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Texture: {
- TextureGpencilModifierData *gpmd = (TextureGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- case eGpencilModifierType_Thick: {
- ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
- if (gpmd->materialname[0] != '\0') {
- gpmd->material = BLI_findstring(
- &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
- gpmd->materialname[0] = '\0';
- }
- break;
- }
- default:
- break;
- }
- }
- }
- }
-
/**
* Versioning code until next subversion bump goes here.
*
@@ -3040,8 +2902,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
v3d->overlay.edit_flag |= V3D_OVERLAY_EDIT_FACES | V3D_OVERLAY_EDIT_SEAMS |
V3D_OVERLAY_EDIT_SHARP | V3D_OVERLAY_EDIT_FREESTYLE_EDGE |
V3D_OVERLAY_EDIT_FREESTYLE_FACE | V3D_OVERLAY_EDIT_EDGES |
- V3D_OVERLAY_EDIT_CREASES | V3D_OVERLAY_EDIT_BWEIGHTS |
- V3D_OVERLAY_EDIT_CU_HANDLES | V3D_OVERLAY_EDIT_CU_NORMALS;
+ V3D_OVERLAY_EDIT_CREASES | V3D_OVERLAY_EDIT_BWEIGHTS;
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 207cee5ac50..c4d7e871ea0 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -28,6 +28,7 @@
#include "DNA_genfile.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "BKE_collection.h"
@@ -41,6 +42,161 @@
/* Make preferences read-only, use versioning_userdef.c. */
#define U (*((const UserDef *)&U))
+void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports))
+{
+ if (!MAIN_VERSION_ATLEAST(bmain, 290, 1)) {
+ /* Patch old grease pencil modifiers material filter. */
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
+ switch (md->type) {
+ case eGpencilModifierType_Array: {
+ ArrayGpencilModifierData *gpmd = (ArrayGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Color: {
+ ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Hook: {
+ HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Lattice: {
+ LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Mirror: {
+ MirrorGpencilModifierData *gpmd = (MirrorGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Multiply: {
+ MultiplyGpencilModifierData *gpmd = (MultiplyGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Noise: {
+ NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Offset: {
+ OffsetGpencilModifierData *gpmd = (OffsetGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Opacity: {
+ OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Simplify: {
+ SimplifyGpencilModifierData *gpmd = (SimplifyGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Smooth: {
+ SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Subdiv: {
+ SubdivGpencilModifierData *gpmd = (SubdivGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Texture: {
+ TextureGpencilModifierData *gpmd = (TextureGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ case eGpencilModifierType_Thick: {
+ ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
+ if (gpmd->materialname[0] != '\0') {
+ gpmd->material = BLI_findstring(
+ &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2);
+ gpmd->materialname[0] = '\0';
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Versioning code until next subversion bump goes here.
+ *
+ * \note Be sure to check when bumping the version:
+ * - #blo_do_versions_290 in this file.
+ * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
+ * - "versioning_userdef.c", #do_versions_theme
+ *
+ * \note Keep this message at the bottom of the function.
+ */
+ {
+ /* Keep this block, even when empty. */
+ }
+}
+
void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
UNUSED_VARS(fd);
@@ -88,6 +244,18 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 290, 4)) {
+ /* Clear old deprecated bit-flag from edit weights modifiers, we now use it for something else.
+ */
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
+ if (md->type == eModifierType_WeightVGEdit) {
+ ((WeightVGEditModifierData *)md)->edit_flags &= ~MOD_WVG_EDIT_WEIGHTS_NORMALIZE;
+ }
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
@@ -100,29 +268,29 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
/* Keep this block, even when empty. */
- /* Transition to saving expansion for all of a constraint's subpanels. */
- if (!DNA_struct_elem_find(fd->filesdna, "bSizeLikeConstraint", "short", "ui_expand_flag")) {
+ /* Transition to saving expansion for all of a modifier's subpanels. */
+ if (!DNA_struct_elem_find(fd->filesdna, "ModifierData", "short", "ui_expand_flag")) {
for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
- LISTBASE_FOREACH (bConstraint *, con, &object->constraints) {
- if (con->flag & CONSTRAINT_EXPAND_DEPRECATED) {
- con->ui_expand_flag = 1;
+ LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
+ if (md->mode & eModifierMode_Expanded_DEPRECATED) {
+ md->ui_expand_flag = 1;
}
else {
- con->ui_expand_flag = 0;
+ md->ui_expand_flag = 0;
}
}
}
}
- /* Transition to saving expansion for all of a modifier's subpanels. */
- if (!DNA_struct_elem_find(fd->filesdna, "SolidifyModifierData", "short", "ui_expand_flag")) {
+ /* Transition to saving expansion for all of a constraint's subpanels. */
+ if (!DNA_struct_elem_find(fd->filesdna, "bSizeLikeConstraint", "short", "ui_expand_flag")) {
for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
- LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
- if (md->mode & eModifierMode_Expanded_DEPRECATED) {
- md->ui_expand_flag = 1;
+ LISTBASE_FOREACH (bConstraint *, con, &object->constraints) {
+ if (con->flag & CONSTRAINT_EXPAND_DEPRECATED) {
+ con->ui_expand_flag = 1;
}
else {
- md->ui_expand_flag = 0;
+ con->ui_expand_flag = 0;
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 665771cce1e..91d89254c90 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -251,8 +251,7 @@ static void blo_update_defaults_screen(bScreen *screen,
void BLO_update_defaults_workspace(WorkSpace *workspace, const char *app_template)
{
- ListBase *layouts = BKE_workspace_layouts_get(workspace);
- LISTBASE_FOREACH (WorkSpaceLayout *, layout, layouts) {
+ LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
if (layout->screen) {
blo_update_defaults_screen(layout->screen, app_template, workspace->id.name + 2);
}
@@ -271,7 +270,7 @@ void BLO_update_defaults_workspace(WorkSpace *workspace, const char *app_templat
/* For Sculpting template. */
if (STREQ(workspace->id.name + 2, "Sculpting")) {
- LISTBASE_FOREACH (WorkSpaceLayout *, layout, layouts) {
+ LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
bScreen *screen = layout->screen;
if (screen) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
@@ -466,6 +465,9 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
/* Reset all grease pencil brushes. */
Scene *scene = bmain->scenes.first;
BKE_brush_gpencil_paint_presets(bmain, scene->toolsettings, true);
+ BKE_brush_gpencil_sculpt_presets(bmain, scene->toolsettings, true);
+ BKE_brush_gpencil_vertex_presets(bmain, scene->toolsettings, true);
+ BKE_brush_gpencil_weight_presets(bmain, scene->toolsettings, true);
/* Ensure new Paint modes. */
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_VERTEX_GPENCIL);
@@ -489,8 +491,8 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
- WorkSpaceLayout *layout = BKE_workspace_hook_layout_for_workspace_get(win->workspace_hook,
- workspace);
+ WorkSpaceLayout *layout = BKE_workspace_active_layout_for_workspace_get(
+ win->workspace_hook, workspace);
/* Name all screens by their workspaces (avoids 'Default.###' names). */
/* Default only has one window. */
if (layout->screen) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index a54085b3036..5e78f0c1052 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -162,6 +162,7 @@
#include "BKE_gpencil_modifier.h"
#include "BKE_idtype.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -176,15 +177,13 @@
#include "BLO_blend_defs.h"
#include "BLO_blend_validate.h"
+#include "BLO_read_write.h"
#include "BLO_readfile.h"
#include "BLO_undofile.h"
#include "BLO_writefile.h"
#include "readfile.h"
-/* for SDNA_TYPE_FROM_STRUCT() macro */
-#include "dna_type_offsets.h"
-
#include <errno.h>
/* Make preferences read-only. */
@@ -326,12 +325,7 @@ typedef struct {
bool error;
/** #MemFile writing (used for undo). */
- struct {
- MemFile *current;
- MemFile *compare;
- /** Use to de-duplicate chunks when writing. */
- MemFileChunk *compare_chunk;
- } mem;
+ MemFileWriteData mem;
/** When true, write to #WriteData.current, could also call 'is_undo'. */
bool use_memfile;
@@ -343,6 +337,10 @@ typedef struct {
WriteWrap *ww;
} WriteData;
+typedef struct BlendWriter {
+ WriteData *wd;
+} BlendWriter;
+
static WriteData *writedata_new(WriteWrap *ww)
{
WriteData *wd = MEM_callocN(sizeof(*wd), "writedata");
@@ -370,7 +368,7 @@ static void writedata_do_write(WriteData *wd, const void *mem, int memlen)
/* memory based save */
if (wd->use_memfile) {
- memfile_chunk_add(wd->mem.current, mem, memlen, &wd->mem.compare_chunk);
+ BLO_memfile_chunk_add(&wd->mem, mem, memlen);
}
else {
if (wd->ww->write(wd->ww, mem, memlen) != memlen) {
@@ -471,9 +469,7 @@ static WriteData *mywrite_begin(WriteWrap *ww, MemFile *compare, MemFile *curren
WriteData *wd = writedata_new(ww);
if (current != NULL) {
- wd->mem.current = current;
- wd->mem.compare = compare;
- wd->mem.compare_chunk = compare ? compare->chunks.first : NULL;
+ BLO_memfile_write_init(&wd->mem, current, compare);
wd->use_memfile = true;
}
@@ -493,12 +489,58 @@ static bool mywrite_end(WriteData *wd)
wd->buf_used_len = 0;
}
+ if (wd->use_memfile) {
+ BLO_memfile_write_finalize(&wd->mem);
+ }
+
const bool err = wd->error;
writedata_free(wd);
return err;
}
+/**
+ * Start writing of data related to a single ID.
+ *
+ * Only does something when storing an undo step.
+ */
+static void mywrite_id_begin(WriteData *wd, ID *id)
+{
+ if (wd->use_memfile) {
+ wd->mem.current_id_session_uuid = id->session_uuid;
+
+ /* If current next memchunk does not match the ID we are about to write, try to find the
+ * correct memchunk in the mapping using ID's session_uuid. */
+ if (wd->mem.id_session_uuid_mapping != NULL &&
+ (wd->mem.reference_current_chunk == NULL ||
+ wd->mem.reference_current_chunk->id_session_uuid != id->session_uuid)) {
+ void *ref = BLI_ghash_lookup(wd->mem.id_session_uuid_mapping,
+ POINTER_FROM_UINT(id->session_uuid));
+ if (ref != NULL) {
+ wd->mem.reference_current_chunk = ref;
+ }
+ /* Else, no existing memchunk found, i.e. this is supposed to be a new ID. */
+ }
+ /* Otherwise, we try with the current memchunk in any case, whether it is matching current
+ * ID's session_uuid or not. */
+ }
+}
+
+/**
+ * Start writing of data related to a single ID.
+ *
+ * Only does something when storing an undo step.
+ */
+static void mywrite_id_end(WriteData *wd, ID *UNUSED(id))
+{
+ if (wd->use_memfile) {
+ /* Very important to do it after every ID write now, otherwise we cannot know whether a
+ * specific ID changed or not. */
+ mywrite_flush(wd);
+ wd->mem.current_id_session_uuid = MAIN_ID_SESSION_UUID_UNSET;
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -634,103 +676,109 @@ static void writelist_id(WriteData *wd, int filecode, const char *structname, co
* These functions are used by blender's .blend system for file saving/loading.
* \{ */
-void IDP_WriteProperty_OnlyData(const IDProperty *prop, void *wd);
-void IDP_WriteProperty(const IDProperty *prop, void *wd);
+void IDP_WriteProperty_OnlyData(const IDProperty *prop, BlendWriter *writer);
+void IDP_WriteProperty(const IDProperty *prop, WriteData *wd);
+void IDP_WriteProperty_new_api(const IDProperty *prop, BlendWriter *writer);
-static void IDP_WriteArray(const IDProperty *prop, void *wd)
+static void IDP_WriteArray(const IDProperty *prop, BlendWriter *writer)
{
/*REMEMBER to set totalen to len in the linking code!!*/
if (prop->data.pointer) {
- writedata(wd, DATA, MEM_allocN_len(prop->data.pointer), prop->data.pointer);
+ BLO_write_raw(writer, MEM_allocN_len(prop->data.pointer), prop->data.pointer);
if (prop->subtype == IDP_GROUP) {
IDProperty **array = prop->data.pointer;
int a;
for (a = 0; a < prop->len; a++) {
- IDP_WriteProperty(array[a], wd);
+ IDP_WriteProperty_new_api(array[a], writer);
}
}
}
}
-static void IDP_WriteIDPArray(const IDProperty *prop, void *wd)
+static void IDP_WriteIDPArray(const IDProperty *prop, BlendWriter *writer)
{
/*REMEMBER to set totalen to len in the linking code!!*/
if (prop->data.pointer) {
const IDProperty *array = prop->data.pointer;
int a;
- writestruct(wd, DATA, IDProperty, prop->len, array);
+ BLO_write_struct_array(writer, IDProperty, prop->len, array);
for (a = 0; a < prop->len; a++) {
- IDP_WriteProperty_OnlyData(&array[a], wd);
+ IDP_WriteProperty_OnlyData(&array[a], writer);
}
}
}
-static void IDP_WriteString(const IDProperty *prop, void *wd)
+static void IDP_WriteString(const IDProperty *prop, BlendWriter *writer)
{
/*REMEMBER to set totalen to len in the linking code!!*/
- writedata(wd, DATA, prop->len, prop->data.pointer);
+ BLO_write_raw(writer, prop->len, prop->data.pointer);
}
-static void IDP_WriteGroup(const IDProperty *prop, void *wd)
+static void IDP_WriteGroup(const IDProperty *prop, BlendWriter *writer)
{
IDProperty *loop;
for (loop = prop->data.group.first; loop; loop = loop->next) {
- IDP_WriteProperty(loop, wd);
+ IDP_WriteProperty_new_api(loop, writer);
}
}
/* Functions to read/write ID Properties */
-void IDP_WriteProperty_OnlyData(const IDProperty *prop, void *wd)
+void IDP_WriteProperty_OnlyData(const IDProperty *prop, BlendWriter *writer)
{
switch (prop->type) {
case IDP_GROUP:
- IDP_WriteGroup(prop, wd);
+ IDP_WriteGroup(prop, writer);
break;
case IDP_STRING:
- IDP_WriteString(prop, wd);
+ IDP_WriteString(prop, writer);
break;
case IDP_ARRAY:
- IDP_WriteArray(prop, wd);
+ IDP_WriteArray(prop, writer);
break;
case IDP_IDPARRAY:
- IDP_WriteIDPArray(prop, wd);
+ IDP_WriteIDPArray(prop, writer);
break;
}
}
-void IDP_WriteProperty(const IDProperty *prop, void *wd)
+void IDP_WriteProperty_new_api(const IDProperty *prop, BlendWriter *writer)
{
- writestruct(wd, DATA, IDProperty, 1, prop);
- IDP_WriteProperty_OnlyData(prop, wd);
+ BLO_write_struct(writer, IDProperty, prop);
+ IDP_WriteProperty_OnlyData(prop, writer);
}
-static void write_iddata(WriteData *wd, ID *id)
+void IDP_WriteProperty(const IDProperty *prop, WriteData *wd)
+{
+ BlendWriter writer = {wd};
+ IDP_WriteProperty_new_api(prop, &writer);
+}
+
+static void write_iddata(BlendWriter *writer, ID *id)
{
/* ID_WM's id->properties are considered runtime only, and never written in .blend file. */
if (id->properties && !ELEM(GS(id->name), ID_WM)) {
- IDP_WriteProperty(id->properties, wd);
+ IDP_WriteProperty_new_api(id->properties, writer);
}
if (id->override_library) {
- writestruct(wd, DATA, IDOverrideLibrary, 1, id->override_library);
+ BLO_write_struct(writer, IDOverrideLibrary, id->override_library);
- writelist(wd, DATA, IDOverrideLibraryProperty, &id->override_library->properties);
+ BLO_write_struct_list(writer, IDOverrideLibraryProperty, &id->override_library->properties);
LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &id->override_library->properties) {
- writedata(wd, DATA, strlen(op->rna_path) + 1, op->rna_path);
+ BLO_write_string(writer, op->rna_path);
- writelist(wd, DATA, IDOverrideLibraryPropertyOperation, &op->operations);
+ BLO_write_struct_list(writer, IDOverrideLibraryPropertyOperation, &op->operations);
LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
if (opop->subitem_reference_name) {
- writedata(
- wd, DATA, strlen(opop->subitem_reference_name) + 1, opop->subitem_reference_name);
+ BLO_write_string(writer, opop->subitem_reference_name);
}
if (opop->subitem_local_name) {
- writedata(wd, DATA, strlen(opop->subitem_local_name) + 1, opop->subitem_local_name);
+ BLO_write_string(writer, opop->subitem_local_name);
}
}
}
@@ -761,12 +809,12 @@ static void write_previews(WriteData *wd, const PreviewImage *prv_orig)
}
}
-static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
+static void write_fmodifiers(BlendWriter *writer, ListBase *fmodifiers)
{
FModifier *fcm;
/* Write all modifiers first (for faster reloading) */
- writelist(wd, DATA, FModifier, fmodifiers);
+ BLO_write_struct_list(writer, FModifier, fmodifiers);
/* Modifiers */
for (fcm = fmodifiers->first; fcm; fcm = fcm->next) {
@@ -775,7 +823,7 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
/* Write the specific data */
if (fmi && fcm->data) {
/* firstly, just write the plain fmi->data struct */
- writestruct_id(wd, DATA, fmi->structName, 1, fcm->data);
+ BLO_write_struct_by_name(writer, fmi->structName, fcm->data);
/* do any modifier specific stuff */
switch (fcm->type) {
@@ -784,7 +832,7 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
/* write coefficients array */
if (data->coefficients) {
- writedata(wd, DATA, sizeof(float) * (data->arraysize), data->coefficients);
+ BLO_write_float_array(writer, data->arraysize, data->coefficients);
}
break;
@@ -794,7 +842,7 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
/* write envelope data */
if (data->data) {
- writestruct(wd, DATA, FCM_EnvelopeData, data->totvert, data->data);
+ BLO_write_struct_array(writer, FCM_EnvelopeData, data->totvert, data->data);
}
break;
@@ -804,7 +852,7 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
/* Write ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
- IDP_WriteProperty(data->prop, wd);
+ IDP_WriteProperty_new_api(data->prop, writer);
break;
}
@@ -813,22 +861,22 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
}
}
-static void write_fcurves(WriteData *wd, ListBase *fcurves)
+static void write_fcurves(BlendWriter *writer, ListBase *fcurves)
{
FCurve *fcu;
- writelist(wd, DATA, FCurve, fcurves);
+ BLO_write_struct_list(writer, FCurve, fcurves);
for (fcu = fcurves->first; fcu; fcu = fcu->next) {
/* curve data */
if (fcu->bezt) {
- writestruct(wd, DATA, BezTriple, fcu->totvert, fcu->bezt);
+ BLO_write_struct_array(writer, BezTriple, fcu->totvert, fcu->bezt);
}
if (fcu->fpt) {
- writestruct(wd, DATA, FPoint, fcu->totvert, fcu->fpt);
+ BLO_write_struct_array(writer, FPoint, fcu->totvert, fcu->fpt);
}
if (fcu->rna_path) {
- writedata(wd, DATA, strlen(fcu->rna_path) + 1, fcu->rna_path);
+ BLO_write_string(writer, fcu->rna_path);
}
/* driver data */
@@ -836,14 +884,14 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
ChannelDriver *driver = fcu->driver;
DriverVar *dvar;
- writestruct(wd, DATA, ChannelDriver, 1, driver);
+ BLO_write_struct(writer, ChannelDriver, driver);
/* variables */
- writelist(wd, DATA, DriverVar, &driver->variables);
+ BLO_write_struct_list(writer, DriverVar, &driver->variables);
for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
if (dtar->rna_path) {
- writedata(wd, DATA, strlen(dtar->rna_path) + 1, dtar->rna_path);
+ BLO_write_string(writer, dtar->rna_path);
}
}
DRIVER_TARGETS_LOOPER_END;
@@ -851,24 +899,24 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
}
/* write F-Modifiers */
- write_fmodifiers(wd, &fcu->modifiers);
+ write_fmodifiers(writer, &fcu->modifiers);
}
}
-static void write_action(WriteData *wd, bAction *act, const void *id_address)
+static void write_action(BlendWriter *writer, bAction *act, const void *id_address)
{
- if (act->id.us > 0 || wd->use_memfile) {
- writestruct_at_address(wd, ID_AC, bAction, 1, id_address, act);
- write_iddata(wd, &act->id);
+ if (act->id.us > 0 || BLO_write_is_undo(writer)) {
+ BLO_write_id_struct(writer, bAction, id_address, &act->id);
+ write_iddata(writer, &act->id);
- write_fcurves(wd, &act->curves);
+ write_fcurves(writer, &act->curves);
LISTBASE_FOREACH (bActionGroup *, grp, &act->groups) {
- writestruct(wd, DATA, bActionGroup, 1, grp);
+ BLO_write_struct(writer, bActionGroup, grp);
}
LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) {
- writestruct(wd, DATA, TimeMarker, 1, marker);
+ BLO_write_struct(writer, TimeMarker, marker);
}
}
}
@@ -894,57 +942,57 @@ static void write_keyingsets(WriteData *wd, ListBase *list)
}
}
-static void write_nlastrips(WriteData *wd, ListBase *strips)
+static void write_nlastrips(BlendWriter *writer, ListBase *strips)
{
NlaStrip *strip;
- writelist(wd, DATA, NlaStrip, strips);
+ BLO_write_struct_list(writer, NlaStrip, strips);
for (strip = strips->first; strip; strip = strip->next) {
/* write the strip's F-Curves and modifiers */
- write_fcurves(wd, &strip->fcurves);
- write_fmodifiers(wd, &strip->modifiers);
+ write_fcurves(writer, &strip->fcurves);
+ write_fmodifiers(writer, &strip->modifiers);
/* write the strip's children */
- write_nlastrips(wd, &strip->strips);
+ write_nlastrips(writer, &strip->strips);
}
}
-static void write_nladata(WriteData *wd, ListBase *nlabase)
+static void write_nladata(BlendWriter *writer, ListBase *nlabase)
{
NlaTrack *nlt;
/* write all the tracks */
for (nlt = nlabase->first; nlt; nlt = nlt->next) {
/* write the track first */
- writestruct(wd, DATA, NlaTrack, 1, nlt);
+ BLO_write_struct(writer, NlaTrack, nlt);
/* write the track's strips */
- write_nlastrips(wd, &nlt->strips);
+ write_nlastrips(writer, &nlt->strips);
}
}
-static void write_animdata(WriteData *wd, AnimData *adt)
+static void write_animdata(BlendWriter *writer, AnimData *adt)
{
AnimOverride *aor;
/* firstly, just write the AnimData block */
- writestruct(wd, DATA, AnimData, 1, adt);
+ BLO_write_struct(writer, AnimData, adt);
/* write drivers */
- write_fcurves(wd, &adt->drivers);
+ write_fcurves(writer, &adt->drivers);
/* write overrides */
// FIXME: are these needed?
for (aor = adt->overrides.first; aor; aor = aor->next) {
/* overrides consist of base data + rna_path */
- writestruct(wd, DATA, AnimOverride, 1, aor);
- writedata(wd, DATA, strlen(aor->rna_path) + 1, aor->rna_path);
+ BLO_write_struct(writer, AnimOverride, aor);
+ BLO_write_string(writer, aor->rna_path);
}
// TODO write the remaps (if they are needed)
/* write NLA data */
- write_nladata(wd, &adt->nla_tracks);
+ write_nladata(writer, &adt->nla_tracks);
}
static void write_curvemapping_curves(WriteData *wd, CurveMapping *cumap)
@@ -967,7 +1015,7 @@ static void write_CurveProfile(WriteData *wd, CurveProfile *profile)
writestruct(wd, DATA, CurveProfilePoint, profile->path_len, profile->path);
}
-static void write_node_socket_default_value(WriteData *wd, bNodeSocket *sock)
+static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *sock)
{
if (sock->default_value == NULL) {
return;
@@ -975,28 +1023,28 @@ static void write_node_socket_default_value(WriteData *wd, bNodeSocket *sock)
switch ((eNodeSocketDatatype)sock->type) {
case SOCK_FLOAT:
- writestruct(wd, DATA, bNodeSocketValueFloat, 1, sock->default_value);
+ BLO_write_struct(writer, bNodeSocketValueFloat, sock->default_value);
break;
case SOCK_VECTOR:
- writestruct(wd, DATA, bNodeSocketValueVector, 1, sock->default_value);
+ BLO_write_struct(writer, bNodeSocketValueVector, sock->default_value);
break;
case SOCK_RGBA:
- writestruct(wd, DATA, bNodeSocketValueRGBA, 1, sock->default_value);
+ BLO_write_struct(writer, bNodeSocketValueRGBA, sock->default_value);
break;
case SOCK_BOOLEAN:
- writestruct(wd, DATA, bNodeSocketValueBoolean, 1, sock->default_value);
+ BLO_write_struct(writer, bNodeSocketValueBoolean, sock->default_value);
break;
case SOCK_INT:
- writestruct(wd, DATA, bNodeSocketValueInt, 1, sock->default_value);
+ BLO_write_struct(writer, bNodeSocketValueInt, sock->default_value);
break;
case SOCK_STRING:
- writestruct(wd, DATA, bNodeSocketValueString, 1, sock->default_value);
+ BLO_write_struct(writer, bNodeSocketValueString, sock->default_value);
break;
case SOCK_OBJECT:
- writestruct(wd, DATA, bNodeSocketValueObject, 1, sock->default_value);
+ BLO_write_struct(writer, bNodeSocketValueObject, sock->default_value);
break;
case SOCK_IMAGE:
- writestruct(wd, DATA, bNodeSocketValueImage, 1, sock->default_value);
+ BLO_write_struct(writer, bNodeSocketValueImage, sock->default_value);
break;
case __SOCK_MESH:
case SOCK_CUSTOM:
@@ -1010,30 +1058,30 @@ static void write_node_socket_default_value(WriteData *wd, bNodeSocket *sock)
}
}
-static void write_node_socket(WriteData *wd, bNodeSocket *sock)
+static void write_node_socket(BlendWriter *writer, bNodeSocket *sock)
{
/* actual socket writing */
- writestruct(wd, DATA, bNodeSocket, 1, sock);
+ BLO_write_struct(writer, bNodeSocket, sock);
if (sock->prop) {
- IDP_WriteProperty(sock->prop, wd);
+ IDP_WriteProperty_new_api(sock->prop, writer);
}
- write_node_socket_default_value(wd, sock);
+ write_node_socket_default_value(writer, sock);
}
-static void write_node_socket_interface(WriteData *wd, bNodeSocket *sock)
+static void write_node_socket_interface(BlendWriter *writer, bNodeSocket *sock)
{
/* actual socket writing */
- writestruct(wd, DATA, bNodeSocket, 1, sock);
+ BLO_write_struct(writer, bNodeSocket, sock);
if (sock->prop) {
- IDP_WriteProperty(sock->prop, wd);
+ IDP_WriteProperty_new_api(sock->prop, writer);
}
- write_node_socket_default_value(wd, sock);
+ write_node_socket_default_value(writer, sock);
}
/* this is only direct data, tree itself should have been written */
-static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
+static void write_nodetree_nolib(BlendWriter *writer, bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
@@ -1042,50 +1090,50 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
/* for link_list() speed, we write per list */
if (ntree->adt) {
- write_animdata(wd, ntree->adt);
+ write_animdata(writer, ntree->adt);
}
for (node = ntree->nodes.first; node; node = node->next) {
- writestruct(wd, DATA, bNode, 1, node);
+ BLO_write_struct(writer, bNode, node);
if (node->prop) {
- IDP_WriteProperty(node->prop, wd);
+ IDP_WriteProperty_new_api(node->prop, writer);
}
for (sock = node->inputs.first; sock; sock = sock->next) {
- write_node_socket(wd, sock);
+ write_node_socket(writer, sock);
}
for (sock = node->outputs.first; sock; sock = sock->next) {
- write_node_socket(wd, sock);
+ write_node_socket(writer, sock);
}
for (link = node->internal_links.first; link; link = link->next) {
- writestruct(wd, DATA, bNodeLink, 1, link);
+ BLO_write_struct(writer, bNodeLink, link);
}
if (node->storage) {
/* could be handlerized at some point, now only 1 exception still */
if ((ntree->type == NTREE_SHADER) &&
ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB)) {
- write_curvemapping(wd, node->storage);
+ write_curvemapping(writer->wd, node->storage);
}
else if (ntree->type == NTREE_SHADER && (node->type == SH_NODE_SCRIPT)) {
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
if (nss->bytecode) {
- writedata(wd, DATA, strlen(nss->bytecode) + 1, nss->bytecode);
+ BLO_write_string(writer, nss->bytecode);
}
- writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
+ BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
}
else if ((ntree->type == NTREE_COMPOSIT) && ELEM(node->type,
CMP_NODE_TIME,
CMP_NODE_CURVE_VEC,
CMP_NODE_CURVE_RGB,
CMP_NODE_HUECORRECT)) {
- write_curvemapping(wd, node->storage);
+ write_curvemapping(writer->wd, node->storage);
}
else if ((ntree->type == NTREE_TEXTURE) &&
(node->type == TEX_NODE_CURVE_RGB || node->type == TEX_NODE_CURVE_TIME)) {
- write_curvemapping(wd, node->storage);
+ write_curvemapping(writer->wd, node->storage);
}
else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_MOVIEDISTORTION)) {
/* pass */
@@ -1095,7 +1143,7 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
* Not ideal (there is no ideal solution here), but should do for now. */
NodeGlare *ndg = node->storage;
/* Not in undo case. */
- if (wd->use_memfile == false) {
+ if (!BLO_write_is_undo(writer)) {
switch (ndg->type) {
case 2: /* Grrrr! magic numbers :( */
ndg->angle = ndg->streaks;
@@ -1107,43 +1155,43 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
break;
}
}
- writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
+ BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
}
else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_CRYPTOMATTE)) {
NodeCryptomatte *nc = (NodeCryptomatte *)node->storage;
if (nc->matte_id) {
- writedata(wd, DATA, strlen(nc->matte_id) + 1, nc->matte_id);
+ BLO_write_string(writer, nc->matte_id);
}
- writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
+ BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
}
else {
- writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
+ BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
}
}
if (node->type == CMP_NODE_OUTPUT_FILE) {
/* inputs have own storage data */
for (sock = node->inputs.first; sock; sock = sock->next) {
- writestruct(wd, DATA, NodeImageMultiFileSocket, 1, sock->storage);
+ BLO_write_struct(writer, NodeImageMultiFileSocket, sock->storage);
}
}
if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) {
/* write extra socket info */
for (sock = node->outputs.first; sock; sock = sock->next) {
- writestruct(wd, DATA, NodeImageLayer, 1, sock->storage);
+ BLO_write_struct(writer, NodeImageLayer, sock->storage);
}
}
}
for (link = ntree->links.first; link; link = link->next) {
- writestruct(wd, DATA, bNodeLink, 1, link);
+ BLO_write_struct(writer, bNodeLink, link);
}
for (sock = ntree->inputs.first; sock; sock = sock->next) {
- write_node_socket_interface(wd, sock);
+ write_node_socket_interface(writer, sock);
}
for (sock = ntree->outputs.first; sock; sock = sock->next) {
- write_node_socket_interface(wd, sock);
+ write_node_socket_interface(writer, sock);
}
}
@@ -1396,28 +1444,30 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
}
}
-static void write_particlesettings(WriteData *wd, ParticleSettings *part, const void *id_address)
+static void write_particlesettings(BlendWriter *writer,
+ ParticleSettings *part,
+ const void *id_address)
{
- if (part->id.us > 0 || wd->use_memfile) {
+ if (part->id.us > 0 || BLO_write_is_undo(writer)) {
/* write LibData */
- writestruct_at_address(wd, ID_PA, ParticleSettings, 1, id_address, part);
- write_iddata(wd, &part->id);
+ BLO_write_id_struct(writer, ParticleSettings, id_address, &part->id);
+ write_iddata(writer, &part->id);
if (part->adt) {
- write_animdata(wd, part->adt);
+ write_animdata(writer, part->adt);
}
- writestruct(wd, DATA, PartDeflect, 1, part->pd);
- writestruct(wd, DATA, PartDeflect, 1, part->pd2);
- writestruct(wd, DATA, EffectorWeights, 1, part->effector_weights);
+ BLO_write_struct(writer, PartDeflect, part->pd);
+ BLO_write_struct(writer, PartDeflect, part->pd2);
+ BLO_write_struct(writer, EffectorWeights, part->effector_weights);
if (part->clumpcurve) {
- write_curvemapping(wd, part->clumpcurve);
+ write_curvemapping(writer->wd, part->clumpcurve);
}
if (part->roughcurve) {
- write_curvemapping(wd, part->roughcurve);
+ write_curvemapping(writer->wd, part->roughcurve);
}
if (part->twistcurve) {
- write_curvemapping(wd, part->twistcurve);
+ write_curvemapping(writer->wd, part->twistcurve);
}
LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
@@ -1434,23 +1484,23 @@ static void write_particlesettings(WriteData *wd, ParticleSettings *part, const
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
- writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
+ BLO_write_struct(writer, ParticleDupliWeight, dw);
}
if (part->boids && part->phystype == PART_PHYS_BOIDS) {
- writestruct(wd, DATA, BoidSettings, 1, part->boids);
+ BLO_write_struct(writer, BoidSettings, part->boids);
LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
- write_boid_state(wd, state);
+ write_boid_state(writer->wd, state);
}
}
if (part->fluid && part->phystype == PART_PHYS_FLUID) {
- writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid);
+ BLO_write_struct(writer, SPHFluidSettings, part->fluid);
}
for (int a = 0; a < MAX_MTEX; a++) {
if (part->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, part->mtex[a]);
+ BLO_write_struct(writer, MTex, part->mtex[a]);
}
}
}
@@ -1637,7 +1687,7 @@ static void write_fmaps(WriteData *wd, ListBase *fbase)
}
}
-static void write_modifiers(WriteData *wd, ListBase *modbase)
+static void write_modifiers(BlendWriter *writer, ListBase *modbase)
{
ModifierData *md;
@@ -1651,86 +1701,86 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
return;
}
- writestruct_id(wd, DATA, mti->structName, 1, md);
+ BLO_write_struct_by_name(writer, mti->structName, md);
if (md->type == eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData *)md;
if (hmd->curfalloff) {
- write_curvemapping(wd, hmd->curfalloff);
+ write_curvemapping(writer->wd, hmd->curfalloff);
}
- writedata(wd, DATA, sizeof(int) * hmd->totindex, hmd->indexar);
+ BLO_write_int32_array(writer, hmd->totindex, hmd->indexar);
}
else if (md->type == eModifierType_Cloth) {
ClothModifierData *clmd = (ClothModifierData *)md;
- writestruct(wd, DATA, ClothSimSettings, 1, clmd->sim_parms);
- writestruct(wd, DATA, ClothCollSettings, 1, clmd->coll_parms);
- writestruct(wd, DATA, EffectorWeights, 1, clmd->sim_parms->effector_weights);
- write_pointcaches(wd, &clmd->ptcaches);
+ BLO_write_struct(writer, ClothSimSettings, clmd->sim_parms);
+ BLO_write_struct(writer, ClothCollSettings, clmd->coll_parms);
+ BLO_write_struct(writer, EffectorWeights, clmd->sim_parms->effector_weights);
+ write_pointcaches(writer->wd, &clmd->ptcaches);
}
else if (md->type == eModifierType_Fluid) {
FluidModifierData *mmd = (FluidModifierData *)md;
if (mmd->type & MOD_FLUID_TYPE_DOMAIN) {
- writestruct(wd, DATA, FluidDomainSettings, 1, mmd->domain);
+ BLO_write_struct(writer, FluidDomainSettings, mmd->domain);
if (mmd->domain) {
- write_pointcaches(wd, &(mmd->domain->ptcaches[0]));
+ write_pointcaches(writer->wd, &(mmd->domain->ptcaches[0]));
/* create fake pointcache so that old blender versions can read it */
mmd->domain->point_cache[1] = BKE_ptcache_add(&mmd->domain->ptcaches[1]);
mmd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE | PTCACHE_FAKE_SMOKE;
mmd->domain->point_cache[1]->step = 1;
- write_pointcaches(wd, &(mmd->domain->ptcaches[1]));
+ write_pointcaches(writer->wd, &(mmd->domain->ptcaches[1]));
if (mmd->domain->coba) {
- writestruct(wd, DATA, ColorBand, 1, mmd->domain->coba);
+ BLO_write_struct(writer, ColorBand, mmd->domain->coba);
}
/* cleanup the fake pointcache */
BKE_ptcache_free_list(&mmd->domain->ptcaches[1]);
mmd->domain->point_cache[1] = NULL;
- writestruct(wd, DATA, EffectorWeights, 1, mmd->domain->effector_weights);
+ BLO_write_struct(writer, EffectorWeights, mmd->domain->effector_weights);
}
}
else if (mmd->type & MOD_FLUID_TYPE_FLOW) {
- writestruct(wd, DATA, FluidFlowSettings, 1, mmd->flow);
+ BLO_write_struct(writer, FluidFlowSettings, mmd->flow);
}
else if (mmd->type & MOD_FLUID_TYPE_EFFEC) {
- writestruct(wd, DATA, FluidEffectorSettings, 1, mmd->effector);
+ BLO_write_struct(writer, FluidEffectorSettings, mmd->effector);
}
}
else if (md->type == eModifierType_Fluidsim) {
FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
- writestruct(wd, DATA, FluidsimSettings, 1, fluidmd->fss);
+ BLO_write_struct(writer, FluidsimSettings, fluidmd->fss);
}
else if (md->type == eModifierType_DynamicPaint) {
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
if (pmd->canvas) {
DynamicPaintSurface *surface;
- writestruct(wd, DATA, DynamicPaintCanvasSettings, 1, pmd->canvas);
+ BLO_write_struct(writer, DynamicPaintCanvasSettings, pmd->canvas);
/* write surfaces */
for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
- writestruct(wd, DATA, DynamicPaintSurface, 1, surface);
+ BLO_write_struct(writer, DynamicPaintSurface, surface);
}
/* write caches and effector weights */
for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
- write_pointcaches(wd, &(surface->ptcaches));
+ write_pointcaches(writer->wd, &(surface->ptcaches));
- writestruct(wd, DATA, EffectorWeights, 1, surface->effector_weights);
+ BLO_write_struct(writer, EffectorWeights, surface->effector_weights);
}
}
if (pmd->brush) {
- writestruct(wd, DATA, DynamicPaintBrushSettings, 1, pmd->brush);
- writestruct(wd, DATA, ColorBand, 1, pmd->brush->paint_ramp);
- writestruct(wd, DATA, ColorBand, 1, pmd->brush->vel_ramp);
+ BLO_write_struct(writer, DynamicPaintBrushSettings, pmd->brush);
+ BLO_write_struct(writer, ColorBand, pmd->brush->paint_ramp);
+ BLO_write_struct(writer, ColorBand, pmd->brush->vel_ramp);
}
}
else if (md->type == eModifierType_Collision) {
@@ -1748,63 +1798,59 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
MeshDeformModifierData *mmd = (MeshDeformModifierData *)md;
int size = mmd->dyngridsize;
- writestruct(wd, DATA, MDefInfluence, mmd->totinfluence, mmd->bindinfluences);
- writedata(wd, DATA, sizeof(int) * (mmd->totvert + 1), mmd->bindoffsets);
- writedata(wd, DATA, sizeof(float) * 3 * mmd->totcagevert, mmd->bindcagecos);
- writestruct(wd, DATA, MDefCell, size * size * size, mmd->dyngrid);
- writestruct(wd, DATA, MDefInfluence, mmd->totinfluence, mmd->dyninfluences);
- writedata(wd, DATA, sizeof(int) * mmd->totvert, mmd->dynverts);
+ BLO_write_struct_array(writer, MDefInfluence, mmd->totinfluence, mmd->bindinfluences);
+ BLO_write_int32_array(writer, mmd->totvert + 1, mmd->bindoffsets);
+ BLO_write_float3_array(writer, mmd->totcagevert, mmd->bindcagecos);
+ BLO_write_struct_array(writer, MDefCell, size * size * size, mmd->dyngrid);
+ BLO_write_struct_array(writer, MDefInfluence, mmd->totinfluence, mmd->dyninfluences);
+ BLO_write_int32_array(writer, mmd->totvert, mmd->dynverts);
}
else if (md->type == eModifierType_Warp) {
WarpModifierData *tmd = (WarpModifierData *)md;
if (tmd->curfalloff) {
- write_curvemapping(wd, tmd->curfalloff);
+ write_curvemapping(writer->wd, tmd->curfalloff);
}
}
else if (md->type == eModifierType_WeightVGEdit) {
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md;
if (wmd->cmap_curve) {
- write_curvemapping(wd, wmd->cmap_curve);
+ write_curvemapping(writer->wd, wmd->cmap_curve);
}
}
else if (md->type == eModifierType_LaplacianDeform) {
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md;
- writedata(wd, DATA, sizeof(float) * lmd->total_verts * 3, lmd->vertexco);
+ BLO_write_float3_array(writer, lmd->total_verts, lmd->vertexco);
}
else if (md->type == eModifierType_CorrectiveSmooth) {
CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
if (csmd->bind_coords) {
- writedata(wd, DATA, sizeof(float[3]) * csmd->bind_coords_num, csmd->bind_coords);
+ BLO_write_float3_array(writer, csmd->bind_coords_num, (float *)csmd->bind_coords);
}
}
else if (md->type == eModifierType_SurfaceDeform) {
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
- writestruct(wd, DATA, SDefVert, smd->numverts, smd->verts);
+ BLO_write_struct_array(writer, SDefVert, smd->numverts, smd->verts);
if (smd->verts) {
for (int i = 0; i < smd->numverts; i++) {
- writestruct(wd, DATA, SDefBind, smd->verts[i].numbinds, smd->verts[i].binds);
+ BLO_write_struct_array(writer, SDefBind, smd->verts[i].numbinds, smd->verts[i].binds);
if (smd->verts[i].binds) {
for (int j = 0; j < smd->verts[i].numbinds; j++) {
- writedata(wd,
- DATA,
- sizeof(int) * smd->verts[i].binds[j].numverts,
- smd->verts[i].binds[j].vert_inds);
+ BLO_write_uint32_array(
+ writer, smd->verts[i].binds[j].numverts, smd->verts[i].binds[j].vert_inds);
if (smd->verts[i].binds[j].mode == MOD_SDEF_MODE_CENTROID ||
smd->verts[i].binds[j].mode == MOD_SDEF_MODE_LOOPTRI) {
- writedata(wd, DATA, sizeof(float) * 3, smd->verts[i].binds[j].vert_weights);
+ BLO_write_float3_array(writer, 1, smd->verts[i].binds[j].vert_weights);
}
else {
- writedata(wd,
- DATA,
- sizeof(float) * smd->verts[i].binds[j].numverts,
- smd->verts[i].binds[j].vert_weights);
+ BLO_write_float_array(
+ writer, smd->verts[i].binds[j].numverts, smd->verts[i].binds[j].vert_weights);
}
}
}
@@ -1814,13 +1860,13 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
else if (md->type == eModifierType_Bevel) {
BevelModifierData *bmd = (BevelModifierData *)md;
if (bmd->custom_profile) {
- write_CurveProfile(wd, bmd->custom_profile);
+ write_CurveProfile(writer->wd, bmd->custom_profile);
}
}
}
}
-static void write_gpencil_modifiers(WriteData *wd, ListBase *modbase)
+static void write_gpencil_modifiers(BlendWriter *writer, ListBase *modbase)
{
GpencilModifierData *md;
@@ -1834,54 +1880,54 @@ static void write_gpencil_modifiers(WriteData *wd, ListBase *modbase)
return;
}
- writestruct_id(wd, DATA, mti->struct_name, 1, md);
+ BLO_write_struct_by_name(writer, mti->struct_name, md);
if (md->type == eGpencilModifierType_Thick) {
ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
if (gpmd->curve_thickness) {
- write_curvemapping(wd, gpmd->curve_thickness);
+ write_curvemapping(writer->wd, gpmd->curve_thickness);
}
}
else if (md->type == eGpencilModifierType_Noise) {
NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md;
if (gpmd->curve_intensity) {
- write_curvemapping(wd, gpmd->curve_intensity);
+ write_curvemapping(writer->wd, gpmd->curve_intensity);
}
}
else if (md->type == eGpencilModifierType_Hook) {
HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md;
if (gpmd->curfalloff) {
- write_curvemapping(wd, gpmd->curfalloff);
+ write_curvemapping(writer->wd, gpmd->curfalloff);
}
}
else if (md->type == eGpencilModifierType_Tint) {
TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
if (gpmd->colorband) {
- writestruct(wd, DATA, ColorBand, 1, gpmd->colorband);
+ BLO_write_struct(writer, ColorBand, gpmd->colorband);
}
if (gpmd->curve_intensity) {
- write_curvemapping(wd, gpmd->curve_intensity);
+ write_curvemapping(writer->wd, gpmd->curve_intensity);
}
}
else if (md->type == eGpencilModifierType_Smooth) {
SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md;
if (gpmd->curve_intensity) {
- write_curvemapping(wd, gpmd->curve_intensity);
+ write_curvemapping(writer->wd, gpmd->curve_intensity);
}
}
else if (md->type == eGpencilModifierType_Color) {
ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md;
if (gpmd->curve_intensity) {
- write_curvemapping(wd, gpmd->curve_intensity);
+ write_curvemapping(writer->wd, gpmd->curve_intensity);
}
}
else if (md->type == eGpencilModifierType_Opacity) {
OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md;
if (gpmd->curve_intensity) {
- write_curvemapping(wd, gpmd->curve_intensity);
+ write_curvemapping(writer->wd, gpmd->curve_intensity);
}
}
}
@@ -1905,24 +1951,23 @@ static void write_shaderfxs(WriteData *wd, ListBase *fxbase)
}
}
-static void write_object(WriteData *wd, Object *ob, const void *id_address)
+static void write_object(BlendWriter *writer, Object *ob, const void *id_address)
{
- if (ob->id.us > 0 || wd->use_memfile) {
+ if (ob->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
BKE_object_runtime_reset(ob);
/* write LibData */
- writestruct_at_address(wd, ID_OB, Object, 1, id_address, ob);
- write_iddata(wd, &ob->id);
+ BLO_write_id_struct(writer, Object, id_address, &ob->id);
+ write_iddata(writer, &ob->id);
if (ob->adt) {
- write_animdata(wd, ob->adt);
+ write_animdata(writer, ob->adt);
}
/* direct data */
- writedata(wd, DATA, sizeof(void *) * ob->totcol, ob->mat);
- writedata(wd, DATA, sizeof(char) * ob->totcol, ob->matbits);
- /* write_effects(wd, &ob->effect); */ /* not used anymore */
+ BLO_write_pointer_array(writer, ob->totcol, ob->mat);
+ BLO_write_raw(writer, sizeof(char) * ob->totcol, ob->matbits);
if (ob->type == OB_ARMATURE) {
bArmature *arm = ob->data;
@@ -1932,108 +1977,108 @@ static void write_object(WriteData *wd, Object *ob, const void *id_address)
}
}
- write_pose(wd, ob->pose);
- write_defgroups(wd, &ob->defbase);
- write_fmaps(wd, &ob->fmaps);
- write_constraints(wd, &ob->constraints);
- write_motionpath(wd, ob->mpath);
+ write_pose(writer->wd, ob->pose);
+ write_defgroups(writer->wd, &ob->defbase);
+ write_fmaps(writer->wd, &ob->fmaps);
+ write_constraints(writer->wd, &ob->constraints);
+ write_motionpath(writer->wd, ob->mpath);
- writestruct(wd, DATA, PartDeflect, 1, ob->pd);
+ BLO_write_struct(writer, PartDeflect, ob->pd);
if (ob->soft) {
/* Set deprecated pointers to prevent crashes of older Blenders */
ob->soft->pointcache = ob->soft->shared->pointcache;
ob->soft->ptcaches = ob->soft->shared->ptcaches;
- writestruct(wd, DATA, SoftBody, 1, ob->soft);
- writestruct(wd, DATA, SoftBody_Shared, 1, ob->soft->shared);
- write_pointcaches(wd, &(ob->soft->shared->ptcaches));
- writestruct(wd, DATA, EffectorWeights, 1, ob->soft->effector_weights);
+ BLO_write_struct(writer, SoftBody, ob->soft);
+ BLO_write_struct(writer, SoftBody_Shared, ob->soft->shared);
+ write_pointcaches(writer->wd, &(ob->soft->shared->ptcaches));
+ BLO_write_struct(writer, EffectorWeights, ob->soft->effector_weights);
}
if (ob->rigidbody_object) {
/* TODO: if any extra data is added to handle duplis, will need separate function then */
- writestruct(wd, DATA, RigidBodyOb, 1, ob->rigidbody_object);
+ BLO_write_struct(writer, RigidBodyOb, ob->rigidbody_object);
}
if (ob->rigidbody_constraint) {
- writestruct(wd, DATA, RigidBodyCon, 1, ob->rigidbody_constraint);
+ BLO_write_struct(writer, RigidBodyCon, ob->rigidbody_constraint);
}
if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
- writestruct(wd, DATA, ImageUser, 1, ob->iuser);
+ BLO_write_struct(writer, ImageUser, ob->iuser);
}
- write_particlesystems(wd, &ob->particlesystem);
- write_modifiers(wd, &ob->modifiers);
- write_gpencil_modifiers(wd, &ob->greasepencil_modifiers);
- write_shaderfxs(wd, &ob->shader_fx);
+ write_particlesystems(writer->wd, &ob->particlesystem);
+ write_modifiers(writer, &ob->modifiers);
+ write_gpencil_modifiers(writer, &ob->greasepencil_modifiers);
+ write_shaderfxs(writer->wd, &ob->shader_fx);
- writelist(wd, DATA, LinkData, &ob->pc_ids);
- writelist(wd, DATA, LodLevel, &ob->lodlevels);
+ BLO_write_struct_list(writer, LinkData, &ob->pc_ids);
+ BLO_write_struct_list(writer, LodLevel, &ob->lodlevels);
- write_previews(wd, ob->preview);
+ write_previews(writer->wd, ob->preview);
}
}
-static void write_vfont(WriteData *wd, VFont *vf, const void *id_address)
+static void write_vfont(BlendWriter *writer, VFont *vf, const void *id_address)
{
- if (vf->id.us > 0 || wd->use_memfile) {
+ if (vf->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
vf->data = NULL;
vf->temp_pf = NULL;
/* write LibData */
- writestruct_at_address(wd, ID_VF, VFont, 1, id_address, vf);
- write_iddata(wd, &vf->id);
+ BLO_write_id_struct(writer, VFont, id_address, &vf->id);
+ write_iddata(writer, &vf->id);
/* direct data */
if (vf->packedfile) {
PackedFile *pf = vf->packedfile;
- writestruct(wd, DATA, PackedFile, 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
+ BLO_write_struct(writer, PackedFile, pf);
+ BLO_write_raw(writer, pf->size, pf->data);
}
}
}
-static void write_key(WriteData *wd, Key *key, const void *id_address)
+static void write_key(BlendWriter *writer, Key *key, const void *id_address)
{
- if (key->id.us > 0 || wd->use_memfile) {
+ if (key->id.us > 0 || BLO_write_is_undo(writer)) {
/* write LibData */
- writestruct_at_address(wd, ID_KE, Key, 1, id_address, key);
- write_iddata(wd, &key->id);
+ BLO_write_id_struct(writer, Key, id_address, &key->id);
+ write_iddata(writer, &key->id);
if (key->adt) {
- write_animdata(wd, key->adt);
+ write_animdata(writer, key->adt);
}
/* direct data */
LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
- writestruct(wd, DATA, KeyBlock, 1, kb);
+ BLO_write_struct(writer, KeyBlock, kb);
if (kb->data) {
- writedata(wd, DATA, kb->totelem * key->elemsize, kb->data);
+ BLO_write_raw(writer, kb->totelem * key->elemsize, kb->data);
}
}
}
}
-static void write_camera(WriteData *wd, Camera *cam, const void *id_address)
+static void write_camera(BlendWriter *writer, Camera *cam, const void *id_address)
{
- if (cam->id.us > 0 || wd->use_memfile) {
+ if (cam->id.us > 0 || BLO_write_is_undo(writer)) {
/* write LibData */
- writestruct_at_address(wd, ID_CA, Camera, 1, id_address, cam);
- write_iddata(wd, &cam->id);
+ BLO_write_id_struct(writer, Camera, id_address, &cam->id);
+ write_iddata(writer, &cam->id);
if (cam->adt) {
- write_animdata(wd, cam->adt);
+ write_animdata(writer, cam->adt);
}
LISTBASE_FOREACH (CameraBGImage *, bgpic, &cam->bg_images) {
- writestruct(wd, DATA, CameraBGImage, 1, bgpic);
+ BLO_write_struct(writer, CameraBGImage, bgpic);
}
}
}
-static void write_mball(WriteData *wd, MetaBall *mb, const void *id_address)
+static void write_mball(BlendWriter *writer, MetaBall *mb, const void *id_address)
{
- if (mb->id.us > 0 || wd->use_memfile) {
+ if (mb->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
BLI_listbase_clear(&mb->disp);
mb->editelems = NULL;
@@ -2043,60 +2088,61 @@ static void write_mball(WriteData *wd, MetaBall *mb, const void *id_address)
mb->batch_cache = NULL;
/* write LibData */
- writestruct_at_address(wd, ID_MB, MetaBall, 1, id_address, mb);
- write_iddata(wd, &mb->id);
+ BLO_write_id_struct(writer, MetaBall, id_address, &mb->id);
+ write_iddata(writer, &mb->id);
/* direct data */
- writedata(wd, DATA, sizeof(void *) * mb->totcol, mb->mat);
+ BLO_write_pointer_array(writer, mb->totcol, mb->mat);
if (mb->adt) {
- write_animdata(wd, mb->adt);
+ write_animdata(writer, mb->adt);
}
LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
- writestruct(wd, DATA, MetaElem, 1, ml);
+ BLO_write_struct(writer, MetaElem, ml);
}
}
}
-static void write_curve(WriteData *wd, Curve *cu, const void *id_address)
+static void write_curve(BlendWriter *writer, Curve *cu, const void *id_address)
{
- if (cu->id.us > 0 || wd->use_memfile) {
+ if (cu->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
cu->editnurb = NULL;
cu->editfont = NULL;
cu->batch_cache = NULL;
/* write LibData */
- writestruct_at_address(wd, ID_CU, Curve, 1, id_address, cu);
- write_iddata(wd, &cu->id);
+ BLO_write_id_struct(writer, Curve, id_address, &cu->id);
+ write_iddata(writer, &cu->id);
/* direct data */
- writedata(wd, DATA, sizeof(void *) * cu->totcol, cu->mat);
+ BLO_write_pointer_array(writer, cu->totcol, cu->mat);
if (cu->adt) {
- write_animdata(wd, cu->adt);
+ write_animdata(writer, cu->adt);
}
if (cu->vfont) {
- writedata(wd, DATA, cu->len + 1, cu->str);
- writestruct(wd, DATA, CharInfo, cu->len_wchar + 1, cu->strinfo);
- writestruct(wd, DATA, TextBox, cu->totbox, cu->tb);
+ BLO_write_raw(writer, cu->len + 1, cu->str);
+ BLO_write_struct_array(writer, CharInfo, cu->len_wchar + 1, cu->strinfo);
+ BLO_write_struct_array(writer, TextBox, cu->totbox, cu->tb);
}
else {
/* is also the order of reading */
LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
- writestruct(wd, DATA, Nurb, 1, nu);
+ BLO_write_struct(writer, Nurb, nu);
}
LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
if (nu->type == CU_BEZIER) {
- writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt);
+ BLO_write_struct_array(writer, BezTriple, nu->pntsu, nu->bezt);
}
else {
- writestruct(wd, DATA, BPoint, nu->pntsu * nu->pntsv, nu->bp);
+
+ BLO_write_struct_array(writer, BPoint, nu->pntsu * nu->pntsv, nu->bp);
if (nu->knotsu) {
- writedata(wd, DATA, KNOTSU(nu) * sizeof(float), nu->knotsu);
+ BLO_write_float_array(writer, KNOTSU(nu), nu->knotsu);
}
if (nu->knotsv) {
- writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv);
+ BLO_write_float_array(writer, KNOTSV(nu), nu->knotsv);
}
}
}
@@ -2104,60 +2150,60 @@ static void write_curve(WriteData *wd, Curve *cu, const void *id_address)
}
}
-static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist)
+static void write_dverts(BlendWriter *writer, int count, MDeformVert *dvlist)
{
if (dvlist) {
/* Write the dvert list */
- writestruct(wd, DATA, MDeformVert, count, dvlist);
+ BLO_write_struct_array(writer, MDeformVert, count, dvlist);
/* Write deformation data for each dvert */
for (int i = 0; i < count; i++) {
if (dvlist[i].dw) {
- writestruct(wd, DATA, MDeformWeight, dvlist[i].totweight, dvlist[i].dw);
+ BLO_write_struct_array(writer, MDeformWeight, dvlist[i].totweight, dvlist[i].dw);
}
}
}
}
-static void write_mdisps(WriteData *wd, int count, MDisps *mdlist, int external)
+static void write_mdisps(BlendWriter *writer, int count, MDisps *mdlist, int external)
{
if (mdlist) {
int i;
- writestruct(wd, DATA, MDisps, count, mdlist);
+ BLO_write_struct_array(writer, MDisps, count, mdlist);
for (i = 0; i < count; i++) {
MDisps *md = &mdlist[i];
if (md->disps) {
if (!external) {
- writedata(wd, DATA, sizeof(float) * 3 * md->totdisp, md->disps);
+ BLO_write_float3_array(writer, md->totdisp, &md->disps[0][0]);
}
}
if (md->hidden) {
- writedata(wd, DATA, BLI_BITMAP_SIZE(md->totdisp), md->hidden);
+ BLO_write_raw(writer, BLI_BITMAP_SIZE(md->totdisp), md->hidden);
}
}
}
}
-static void write_grid_paint_mask(WriteData *wd, int count, GridPaintMask *grid_paint_mask)
+static void write_grid_paint_mask(BlendWriter *writer, int count, GridPaintMask *grid_paint_mask)
{
if (grid_paint_mask) {
int i;
- writestruct(wd, DATA, GridPaintMask, count, grid_paint_mask);
+ BLO_write_struct_array(writer, GridPaintMask, count, grid_paint_mask);
for (i = 0; i < count; i++) {
GridPaintMask *gpm = &grid_paint_mask[i];
if (gpm->data) {
const int gridsize = BKE_ccg_gridsize(gpm->level);
- writedata(wd, DATA, sizeof(*gpm->data) * gridsize * gridsize, gpm->data);
+ BLO_write_raw(writer, sizeof(*gpm->data) * gridsize * gridsize, gpm->data);
}
}
}
}
-static void write_customdata(WriteData *wd,
+static void write_customdata(BlendWriter *writer,
ID *id,
int count,
CustomData *data,
@@ -2167,11 +2213,11 @@ static void write_customdata(WriteData *wd,
int i;
/* write external customdata (not for undo) */
- if (data->external && (wd->use_memfile == false)) {
+ if (data->external && !BLO_write_is_undo(writer)) {
CustomData_external_write(data, id, cddata_mask, count, 0);
}
- writestruct_at_address(wd, DATA, CustomDataLayer, data->totlayer, data->layers, layers);
+ writestruct_at_address(writer->wd, DATA, CustomDataLayer, data->totlayer, data->layers, layers);
for (i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &layers[i];
@@ -2180,33 +2226,33 @@ static void write_customdata(WriteData *wd,
if (layer->type == CD_MDEFORMVERT) {
/* layer types that allocate own memory need special handling */
- write_dverts(wd, count, layer->data);
+ write_dverts(writer, count, layer->data);
}
else if (layer->type == CD_MDISPS) {
- write_mdisps(wd, count, layer->data, layer->flag & CD_FLAG_EXTERNAL);
+ write_mdisps(writer, count, layer->data, layer->flag & CD_FLAG_EXTERNAL);
}
else if (layer->type == CD_PAINT_MASK) {
const float *layer_data = layer->data;
- writedata(wd, DATA, sizeof(*layer_data) * count, layer_data);
+ BLO_write_raw(writer, sizeof(*layer_data) * count, layer_data);
}
else if (layer->type == CD_SCULPT_FACE_SETS) {
const float *layer_data = layer->data;
- writedata(wd, DATA, sizeof(*layer_data) * count, layer_data);
+ BLO_write_raw(writer, sizeof(*layer_data) * count, layer_data);
}
else if (layer->type == CD_GRID_PAINT_MASK) {
- write_grid_paint_mask(wd, count, layer->data);
+ write_grid_paint_mask(writer, count, layer->data);
}
else if (layer->type == CD_FACEMAP) {
const int *layer_data = layer->data;
- writedata(wd, DATA, sizeof(*layer_data) * count, layer_data);
+ BLO_write_raw(writer, sizeof(*layer_data) * count, layer_data);
}
else {
CustomData_file_write_info(layer->type, &structname, &structnum);
if (structnum) {
datasize = structnum * count;
- writestruct_id(wd, DATA, structname, datasize, layer->data);
+ BLO_write_struct_array_by_name(writer, structname, datasize, layer->data);
}
- else if (!wd->use_memfile) { /* Do not warn on undo. */
+ else if (!BLO_write_is_undo(writer)) { /* Do not warn on undo. */
printf("%s error: layer '%s':%d - can't be written to file\n",
__func__,
structname,
@@ -2216,13 +2262,13 @@ static void write_customdata(WriteData *wd,
}
if (data->external) {
- writestruct(wd, DATA, CustomDataExternal, 1, data->external);
+ BLO_write_struct(writer, CustomDataExternal, data->external);
}
}
-static void write_mesh(WriteData *wd, Mesh *mesh, const void *id_address)
+static void write_mesh(BlendWriter *writer, Mesh *mesh, const void *id_address)
{
- if (mesh->id.us > 0 || wd->use_memfile) {
+ if (mesh->id.us > 0 || BLO_write_is_undo(writer)) {
/* cache only - don't write */
mesh->mface = NULL;
mesh->totface = 0;
@@ -2244,23 +2290,23 @@ static void write_mesh(WriteData *wd, Mesh *mesh, const void *id_address)
CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
- writestruct_at_address(wd, ID_ME, Mesh, 1, id_address, mesh);
- write_iddata(wd, &mesh->id);
+ BLO_write_id_struct(writer, Mesh, id_address, &mesh->id);
+ write_iddata(writer, &mesh->id);
/* direct data */
if (mesh->adt) {
- write_animdata(wd, mesh->adt);
+ write_animdata(writer, mesh->adt);
}
- writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat);
- writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect);
+ BLO_write_pointer_array(writer, mesh->totcol, mesh->mat);
+ BLO_write_raw(writer, sizeof(MSelect) * mesh->totselect, mesh->mselect);
- write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, CD_MASK_MESH.vmask);
- write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, CD_MASK_MESH.emask);
+ write_customdata(writer, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, CD_MASK_MESH.vmask);
+ write_customdata(writer, &mesh->id, mesh->totedge, &mesh->edata, elayers, CD_MASK_MESH.emask);
/* fdata is really a dummy - written so slots align */
- write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, CD_MASK_MESH.fmask);
- write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, CD_MASK_MESH.lmask);
- write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, CD_MASK_MESH.pmask);
+ write_customdata(writer, &mesh->id, mesh->totface, &mesh->fdata, flayers, CD_MASK_MESH.fmask);
+ write_customdata(writer, &mesh->id, mesh->totloop, &mesh->ldata, llayers, CD_MASK_MESH.lmask);
+ write_customdata(writer, &mesh->id, mesh->totpoly, &mesh->pdata, players, CD_MASK_MESH.pmask);
/* free temporary data */
if (vlayers && vlayers != vlayers_buff) {
@@ -2281,32 +2327,32 @@ static void write_mesh(WriteData *wd, Mesh *mesh, const void *id_address)
}
}
-static void write_lattice(WriteData *wd, Lattice *lt, const void *id_address)
+static void write_lattice(BlendWriter *writer, Lattice *lt, const void *id_address)
{
- if (lt->id.us > 0 || wd->use_memfile) {
+ if (lt->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
lt->editlatt = NULL;
lt->batch_cache = NULL;
/* write LibData */
- writestruct_at_address(wd, ID_LT, Lattice, 1, id_address, lt);
- write_iddata(wd, &lt->id);
+ BLO_write_id_struct(writer, Lattice, id_address, &lt->id);
+ write_iddata(writer, &lt->id);
/* write animdata */
if (lt->adt) {
- write_animdata(wd, lt->adt);
+ write_animdata(writer, lt->adt);
}
/* direct data */
- writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
+ BLO_write_struct_array(writer, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
- write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
+ write_dverts(writer, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
}
}
-static void write_image(WriteData *wd, Image *ima, const void *id_address)
+static void write_image(BlendWriter *writer, Image *ima, const void *id_address)
{
- if (ima->id.us > 0 || wd->use_memfile) {
+ if (ima->id.us > 0 || BLO_write_is_undo(writer)) {
ImagePackedFile *imapf;
/* Some trickery to keep forward compatibility of packed images. */
@@ -2317,135 +2363,135 @@ static void write_image(WriteData *wd, Image *ima, const void *id_address)
}
/* write LibData */
- writestruct_at_address(wd, ID_IM, Image, 1, id_address, ima);
- write_iddata(wd, &ima->id);
+ BLO_write_id_struct(writer, Image, id_address, &ima->id);
+ write_iddata(writer, &ima->id);
for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
- writestruct(wd, DATA, ImagePackedFile, 1, imapf);
+ BLO_write_struct(writer, ImagePackedFile, imapf);
if (imapf->packedfile) {
PackedFile *pf = imapf->packedfile;
- writestruct(wd, DATA, PackedFile, 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
+ BLO_write_struct(writer, PackedFile, pf);
+ BLO_write_raw(writer, pf->size, pf->data);
}
}
- write_previews(wd, ima->preview);
+ write_previews(writer->wd, ima->preview);
LISTBASE_FOREACH (ImageView *, iv, &ima->views) {
- writestruct(wd, DATA, ImageView, 1, iv);
+ BLO_write_struct(writer, ImageView, iv);
}
- writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format);
+ BLO_write_struct(writer, Stereo3dFormat, ima->stereo3d_format);
- writelist(wd, DATA, ImageTile, &ima->tiles);
+ BLO_write_struct_list(writer, ImageTile, &ima->tiles);
ima->packedfile = NULL;
- writelist(wd, DATA, RenderSlot, &ima->renderslots);
+ BLO_write_struct_list(writer, RenderSlot, &ima->renderslots);
}
}
-static void write_texture(WriteData *wd, Tex *tex, const void *id_address)
+static void write_texture(BlendWriter *writer, Tex *tex, const void *id_address)
{
- if (tex->id.us > 0 || wd->use_memfile) {
+ if (tex->id.us > 0 || BLO_write_is_undo(writer)) {
/* write LibData */
- writestruct_at_address(wd, ID_TE, Tex, 1, id_address, tex);
- write_iddata(wd, &tex->id);
+ BLO_write_id_struct(writer, Tex, id_address, &tex->id);
+ write_iddata(writer, &tex->id);
if (tex->adt) {
- write_animdata(wd, tex->adt);
+ write_animdata(writer, tex->adt);
}
/* direct data */
if (tex->coba) {
- writestruct(wd, DATA, ColorBand, 1, tex->coba);
+ BLO_write_struct(writer, ColorBand, tex->coba);
}
/* nodetree is integral part of texture, no libdata */
if (tex->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, tex->nodetree);
- write_nodetree_nolib(wd, tex->nodetree);
+ BLO_write_struct(writer, bNodeTree, tex->nodetree);
+ write_nodetree_nolib(writer, tex->nodetree);
}
- write_previews(wd, tex->preview);
+ write_previews(writer->wd, tex->preview);
}
}
-static void write_material(WriteData *wd, Material *ma, const void *id_address)
+static void write_material(BlendWriter *writer, Material *ma, const void *id_address)
{
- if (ma->id.us > 0 || wd->use_memfile) {
+ if (ma->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
ma->texpaintslot = NULL;
BLI_listbase_clear(&ma->gpumaterial);
/* write LibData */
- writestruct_at_address(wd, ID_MA, Material, 1, id_address, ma);
- write_iddata(wd, &ma->id);
+ BLO_write_id_struct(writer, Material, id_address, &ma->id);
+ write_iddata(writer, &ma->id);
if (ma->adt) {
- write_animdata(wd, ma->adt);
+ write_animdata(writer, ma->adt);
}
/* nodetree is integral part of material, no libdata */
if (ma->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, ma->nodetree);
- write_nodetree_nolib(wd, ma->nodetree);
+ BLO_write_struct(writer, bNodeTree, ma->nodetree);
+ write_nodetree_nolib(writer, ma->nodetree);
}
- write_previews(wd, ma->preview);
+ write_previews(writer->wd, ma->preview);
/* grease pencil settings */
if (ma->gp_style) {
- writestruct(wd, DATA, MaterialGPencilStyle, 1, ma->gp_style);
+ BLO_write_struct(writer, MaterialGPencilStyle, ma->gp_style);
}
}
}
-static void write_world(WriteData *wd, World *wrld, const void *id_address)
+static void write_world(BlendWriter *writer, World *wrld, const void *id_address)
{
- if (wrld->id.us > 0 || wd->use_memfile) {
+ if (wrld->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
BLI_listbase_clear(&wrld->gpumaterial);
/* write LibData */
- writestruct_at_address(wd, ID_WO, World, 1, id_address, wrld);
- write_iddata(wd, &wrld->id);
+ BLO_write_id_struct(writer, World, id_address, &wrld->id);
+ write_iddata(writer, &wrld->id);
if (wrld->adt) {
- write_animdata(wd, wrld->adt);
+ write_animdata(writer, wrld->adt);
}
/* nodetree is integral part of world, no libdata */
if (wrld->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, wrld->nodetree);
- write_nodetree_nolib(wd, wrld->nodetree);
+ BLO_write_struct(writer, bNodeTree, wrld->nodetree);
+ write_nodetree_nolib(writer, wrld->nodetree);
}
- write_previews(wd, wrld->preview);
+ write_previews(writer->wd, wrld->preview);
}
}
-static void write_light(WriteData *wd, Light *la, const void *id_address)
+static void write_light(BlendWriter *writer, Light *la, const void *id_address)
{
- if (la->id.us > 0 || wd->use_memfile) {
+ if (la->id.us > 0 || BLO_write_is_undo(writer)) {
/* write LibData */
- writestruct_at_address(wd, ID_LA, Light, 1, id_address, la);
- write_iddata(wd, &la->id);
+ BLO_write_id_struct(writer, Light, id_address, &la->id);
+ write_iddata(writer, &la->id);
if (la->adt) {
- write_animdata(wd, la->adt);
+ write_animdata(writer, la->adt);
}
if (la->curfalloff) {
- write_curvemapping(wd, la->curfalloff);
+ write_curvemapping(writer->wd, la->curfalloff);
}
/* Node-tree is integral part of lights, no libdata. */
if (la->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, la->nodetree);
- write_nodetree_nolib(wd, la->nodetree);
+ BLO_write_struct(writer, bNodeTree, la->nodetree);
+ write_nodetree_nolib(writer, la->nodetree);
}
- write_previews(wd, la->preview);
+ write_previews(writer->wd, la->preview);
}
}
@@ -2463,9 +2509,9 @@ static void write_collection_nolib(WriteData *wd, Collection *collection)
}
}
-static void write_collection(WriteData *wd, Collection *collection, const void *id_address)
+static void write_collection(BlendWriter *writer, Collection *collection, const void *id_address)
{
- if (collection->id.us > 0 || wd->use_memfile) {
+ if (collection->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
collection->tag = 0;
@@ -2473,10 +2519,10 @@ static void write_collection(WriteData *wd, Collection *collection, const void *
BLI_listbase_clear(&collection->parents);
/* write LibData */
- writestruct_at_address(wd, ID_GR, Collection, 1, id_address, collection);
- write_iddata(wd, &collection->id);
+ BLO_write_id_struct(writer, Collection, id_address, &collection->id);
+ write_iddata(writer, &collection->id);
- write_collection_nolib(wd, collection);
+ write_collection_nolib(writer->wd, collection);
}
}
@@ -2587,82 +2633,82 @@ static void write_lightcache(WriteData *wd, LightCache *cache)
writestruct(wd, DATA, LightProbeCache, cache->cube_len, cache->cube_data);
}
-static void write_scene(WriteData *wd, Scene *sce, const void *id_address)
+static void write_scene(BlendWriter *writer, Scene *sce, const void *id_address)
{
- if (wd->use_memfile) {
+ if (BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
/* XXX This UI data should not be stored in Scene at all... */
memset(&sce->cursor, 0, sizeof(sce->cursor));
}
/* write LibData */
- writestruct_at_address(wd, ID_SCE, Scene, 1, id_address, sce);
- write_iddata(wd, &sce->id);
+ BLO_write_id_struct(writer, Scene, id_address, &sce->id);
+ write_iddata(writer, &sce->id);
if (sce->adt) {
- write_animdata(wd, sce->adt);
+ write_animdata(writer, sce->adt);
}
- write_keyingsets(wd, &sce->keyingsets);
+ write_keyingsets(writer->wd, &sce->keyingsets);
/* direct data */
ToolSettings *tos = sce->toolsettings;
- writestruct(wd, DATA, ToolSettings, 1, tos);
+ BLO_write_struct(writer, ToolSettings, tos);
if (tos->vpaint) {
- writestruct(wd, DATA, VPaint, 1, tos->vpaint);
- write_paint(wd, &tos->vpaint->paint);
+ BLO_write_struct(writer, VPaint, tos->vpaint);
+ write_paint(writer->wd, &tos->vpaint->paint);
}
if (tos->wpaint) {
- writestruct(wd, DATA, VPaint, 1, tos->wpaint);
- write_paint(wd, &tos->wpaint->paint);
+ BLO_write_struct(writer, VPaint, tos->wpaint);
+ write_paint(writer->wd, &tos->wpaint->paint);
}
if (tos->sculpt) {
- writestruct(wd, DATA, Sculpt, 1, tos->sculpt);
- write_paint(wd, &tos->sculpt->paint);
+ BLO_write_struct(writer, Sculpt, tos->sculpt);
+ write_paint(writer->wd, &tos->sculpt->paint);
}
if (tos->uvsculpt) {
- writestruct(wd, DATA, UvSculpt, 1, tos->uvsculpt);
- write_paint(wd, &tos->uvsculpt->paint);
+ BLO_write_struct(writer, UvSculpt, tos->uvsculpt);
+ write_paint(writer->wd, &tos->uvsculpt->paint);
}
if (tos->gp_paint) {
- writestruct(wd, DATA, GpPaint, 1, tos->gp_paint);
- write_paint(wd, &tos->gp_paint->paint);
+ BLO_write_struct(writer, GpPaint, tos->gp_paint);
+ write_paint(writer->wd, &tos->gp_paint->paint);
}
if (tos->gp_vertexpaint) {
- writestruct(wd, DATA, GpVertexPaint, 1, tos->gp_vertexpaint);
- write_paint(wd, &tos->gp_vertexpaint->paint);
+ BLO_write_struct(writer, GpVertexPaint, tos->gp_vertexpaint);
+ write_paint(writer->wd, &tos->gp_vertexpaint->paint);
}
if (tos->gp_sculptpaint) {
- writestruct(wd, DATA, GpSculptPaint, 1, tos->gp_sculptpaint);
- write_paint(wd, &tos->gp_sculptpaint->paint);
+ BLO_write_struct(writer, GpSculptPaint, tos->gp_sculptpaint);
+ write_paint(writer->wd, &tos->gp_sculptpaint->paint);
}
if (tos->gp_weightpaint) {
- writestruct(wd, DATA, GpWeightPaint, 1, tos->gp_weightpaint);
- write_paint(wd, &tos->gp_weightpaint->paint);
+ BLO_write_struct(writer, GpWeightPaint, tos->gp_weightpaint);
+ write_paint(writer->wd, &tos->gp_weightpaint->paint);
}
/* write grease-pencil custom ipo curve to file */
if (tos->gp_interpolate.custom_ipo) {
- write_curvemapping(wd, tos->gp_interpolate.custom_ipo);
+ write_curvemapping(writer->wd, tos->gp_interpolate.custom_ipo);
}
/* write grease-pencil multiframe falloff curve to file */
if (tos->gp_sculpt.cur_falloff) {
- write_curvemapping(wd, tos->gp_sculpt.cur_falloff);
+ write_curvemapping(writer->wd, tos->gp_sculpt.cur_falloff);
}
/* write grease-pencil primitive curve to file */
if (tos->gp_sculpt.cur_primitive) {
- write_curvemapping(wd, tos->gp_sculpt.cur_primitive);
+ write_curvemapping(writer->wd, tos->gp_sculpt.cur_primitive);
}
/* Write the curve profile to the file. */
if (tos->custom_bevel_profile_preset) {
- write_CurveProfile(wd, tos->custom_bevel_profile_preset);
+ write_CurveProfile(writer->wd, tos->custom_bevel_profile_preset);
}
- write_paint(wd, &tos->imapaint.paint);
+ write_paint(writer->wd, &tos->imapaint.paint);
Editing *ed = sce->ed;
if (ed) {
Sequence *seq;
- writestruct(wd, DATA, Editing, 1, ed);
+ BLO_write_struct(writer, Editing, ed);
/* reset write flags too */
@@ -2670,7 +2716,7 @@ static void write_scene(WriteData *wd, Scene *sce, const void *id_address)
if (seq->strip) {
seq->strip->done = false;
}
- writestruct(wd, DATA, Sequence, 1, seq);
+ BLO_write_struct(writer, Sequence, seq);
}
SEQ_END;
@@ -2681,147 +2727,146 @@ static void write_scene(WriteData *wd, Scene *sce, const void *id_address)
if (seq->effectdata) {
switch (seq->type) {
case SEQ_TYPE_COLOR:
- writestruct(wd, DATA, SolidColorVars, 1, seq->effectdata);
+ BLO_write_struct(writer, SolidColorVars, seq->effectdata);
break;
case SEQ_TYPE_SPEED:
- writestruct(wd, DATA, SpeedControlVars, 1, seq->effectdata);
+ BLO_write_struct(writer, SpeedControlVars, seq->effectdata);
break;
case SEQ_TYPE_WIPE:
- writestruct(wd, DATA, WipeVars, 1, seq->effectdata);
+ BLO_write_struct(writer, WipeVars, seq->effectdata);
break;
case SEQ_TYPE_GLOW:
- writestruct(wd, DATA, GlowVars, 1, seq->effectdata);
+ BLO_write_struct(writer, GlowVars, seq->effectdata);
break;
case SEQ_TYPE_TRANSFORM:
- writestruct(wd, DATA, TransformVars, 1, seq->effectdata);
+ BLO_write_struct(writer, TransformVars, seq->effectdata);
break;
case SEQ_TYPE_GAUSSIAN_BLUR:
- writestruct(wd, DATA, GaussianBlurVars, 1, seq->effectdata);
+ BLO_write_struct(writer, GaussianBlurVars, seq->effectdata);
break;
case SEQ_TYPE_TEXT:
- writestruct(wd, DATA, TextVars, 1, seq->effectdata);
+ BLO_write_struct(writer, TextVars, seq->effectdata);
break;
case SEQ_TYPE_COLORMIX:
- writestruct(wd, DATA, ColorMixVars, 1, seq->effectdata);
+ BLO_write_struct(writer, ColorMixVars, seq->effectdata);
break;
}
}
- writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format);
+ BLO_write_struct(writer, Stereo3dFormat, seq->stereo3d_format);
Strip *strip = seq->strip;
- writestruct(wd, DATA, Strip, 1, strip);
+ BLO_write_struct(writer, Strip, strip);
if (strip->crop) {
- writestruct(wd, DATA, StripCrop, 1, strip->crop);
+ BLO_write_struct(writer, StripCrop, strip->crop);
}
if (strip->transform) {
- writestruct(wd, DATA, StripTransform, 1, strip->transform);
+ BLO_write_struct(writer, StripTransform, strip->transform);
}
if (strip->proxy) {
- writestruct(wd, DATA, StripProxy, 1, strip->proxy);
+ BLO_write_struct(writer, StripProxy, strip->proxy);
}
if (seq->type == SEQ_TYPE_IMAGE) {
- writestruct(wd,
- DATA,
- StripElem,
- MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem),
- strip->stripdata);
+ BLO_write_struct_array(writer,
+ StripElem,
+ MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem),
+ strip->stripdata);
}
else if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
- writestruct(wd, DATA, StripElem, 1, strip->stripdata);
+ BLO_write_struct(writer, StripElem, strip->stripdata);
}
strip->done = true;
}
if (seq->prop) {
- IDP_WriteProperty(seq->prop, wd);
+ IDP_WriteProperty_new_api(seq->prop, writer);
}
- write_sequence_modifiers(wd, &seq->modifiers);
+ write_sequence_modifiers(writer->wd, &seq->modifiers);
}
SEQ_END;
/* new; meta stack too, even when its nasty restore code */
LISTBASE_FOREACH (MetaStack *, ms, &ed->metastack) {
- writestruct(wd, DATA, MetaStack, 1, ms);
+ BLO_write_struct(writer, MetaStack, ms);
}
}
if (sce->r.avicodecdata) {
- writestruct(wd, DATA, AviCodecData, 1, sce->r.avicodecdata);
+ BLO_write_struct(writer, AviCodecData, sce->r.avicodecdata);
if (sce->r.avicodecdata->lpFormat) {
- writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
+ BLO_write_raw(writer, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
}
if (sce->r.avicodecdata->lpParms) {
- writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms);
+ BLO_write_raw(writer, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms);
}
}
if (sce->r.ffcodecdata.properties) {
- IDP_WriteProperty(sce->r.ffcodecdata.properties, wd);
+ IDP_WriteProperty_new_api(sce->r.ffcodecdata.properties, writer);
}
/* writing dynamic list of TimeMarkers to the blend file */
LISTBASE_FOREACH (TimeMarker *, marker, &sce->markers) {
- writestruct(wd, DATA, TimeMarker, 1, marker);
+ BLO_write_struct(writer, TimeMarker, marker);
}
/* writing dynamic list of TransformOrientations to the blend file */
LISTBASE_FOREACH (TransformOrientation *, ts, &sce->transform_spaces) {
- writestruct(wd, DATA, TransformOrientation, 1, ts);
+ BLO_write_struct(writer, TransformOrientation, ts);
}
/* writing MultiView to the blend file */
LISTBASE_FOREACH (SceneRenderView *, srv, &sce->r.views) {
- writestruct(wd, DATA, SceneRenderView, 1, srv);
+ BLO_write_struct(writer, SceneRenderView, srv);
}
if (sce->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, sce->nodetree);
- write_nodetree_nolib(wd, sce->nodetree);
+ BLO_write_struct(writer, bNodeTree, sce->nodetree);
+ write_nodetree_nolib(writer, sce->nodetree);
}
- write_view_settings(wd, &sce->view_settings);
+ write_view_settings(writer->wd, &sce->view_settings);
/* writing RigidBodyWorld data to the blend file */
if (sce->rigidbody_world) {
/* Set deprecated pointers to prevent crashes of older Blenders */
sce->rigidbody_world->pointcache = sce->rigidbody_world->shared->pointcache;
sce->rigidbody_world->ptcaches = sce->rigidbody_world->shared->ptcaches;
- writestruct(wd, DATA, RigidBodyWorld, 1, sce->rigidbody_world);
+ BLO_write_struct(writer, RigidBodyWorld, sce->rigidbody_world);
- writestruct(wd, DATA, RigidBodyWorld_Shared, 1, sce->rigidbody_world->shared);
- writestruct(wd, DATA, EffectorWeights, 1, sce->rigidbody_world->effector_weights);
- write_pointcaches(wd, &(sce->rigidbody_world->shared->ptcaches));
+ BLO_write_struct(writer, RigidBodyWorld_Shared, sce->rigidbody_world->shared);
+ BLO_write_struct(writer, EffectorWeights, sce->rigidbody_world->effector_weights);
+ write_pointcaches(writer->wd, &(sce->rigidbody_world->shared->ptcaches));
}
- write_previews(wd, sce->preview);
- write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
+ write_previews(writer->wd, sce->preview);
+ write_curvemapping_curves(writer->wd, &sce->r.mblur_shutter_curve);
LISTBASE_FOREACH (ViewLayer *, view_layer, &sce->view_layers) {
- write_view_layer(wd, view_layer);
+ write_view_layer(writer->wd, view_layer);
}
if (sce->master_collection) {
- writestruct(wd, DATA, Collection, 1, sce->master_collection);
- write_collection_nolib(wd, sce->master_collection);
+ BLO_write_struct(writer, Collection, sce->master_collection);
+ write_collection_nolib(writer->wd, sce->master_collection);
}
/* Eevee Lightcache */
- if (sce->eevee.light_cache_data && !wd->use_memfile) {
- writestruct(wd, DATA, LightCache, 1, sce->eevee.light_cache_data);
- write_lightcache(wd, sce->eevee.light_cache_data);
+ if (sce->eevee.light_cache_data && !BLO_write_is_undo(writer)) {
+ BLO_write_struct(writer, LightCache, sce->eevee.light_cache_data);
+ write_lightcache(writer->wd, sce->eevee.light_cache_data);
}
- write_view3dshading(wd, &sce->display.shading);
+ write_view3dshading(writer->wd, &sce->display.shading);
/* Freed on doversion. */
BLI_assert(sce->layer_properties == NULL);
}
-static void write_gpencil(WriteData *wd, bGPdata *gpd, const void *id_address)
+static void write_gpencil(BlendWriter *writer, bGPdata *gpd, const void *id_address)
{
- if (gpd->id.us > 0 || wd->use_memfile) {
+ if (gpd->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed data-blocks. */
/* XXX not sure why the whole run-time data is not cleared in reading code,
* for now mimicking it here. */
@@ -2831,29 +2876,29 @@ static void write_gpencil(WriteData *wd, bGPdata *gpd, const void *id_address)
gpd->runtime.tot_cp_points = 0;
/* write gpd data block to file */
- writestruct_at_address(wd, ID_GD, bGPdata, 1, id_address, gpd);
- write_iddata(wd, &gpd->id);
+ BLO_write_id_struct(writer, bGPdata, id_address, &gpd->id);
+ write_iddata(writer, &gpd->id);
if (gpd->adt) {
- write_animdata(wd, gpd->adt);
+ write_animdata(writer, gpd->adt);
}
- writedata(wd, DATA, sizeof(void *) * gpd->totcol, gpd->mat);
+ BLO_write_pointer_array(writer, gpd->totcol, gpd->mat);
/* write grease-pencil layers to file */
- writelist(wd, DATA, bGPDlayer, &gpd->layers);
+ BLO_write_struct_list(writer, bGPDlayer, &gpd->layers);
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* Write mask list. */
- writelist(wd, DATA, bGPDlayer_Mask, &gpl->mask_layers);
+ BLO_write_struct_list(writer, bGPDlayer_Mask, &gpl->mask_layers);
/* write this layer's frames to file */
- writelist(wd, DATA, bGPDframe, &gpl->frames);
+ BLO_write_struct_list(writer, bGPDframe, &gpl->frames);
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* write strokes */
- writelist(wd, DATA, bGPDstroke, &gpf->strokes);
+ BLO_write_struct_list(writer, bGPDstroke, &gpf->strokes);
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
- writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points);
- writestruct(wd, DATA, bGPDtriangle, gps->tot_triangles, gps->triangles);
- write_dverts(wd, gps->totpoints, gps->dvert);
+ BLO_write_struct_array(writer, bGPDspoint, gps->totpoints, gps->points);
+ BLO_write_struct_array(writer, bGPDtriangle, gps->tot_triangles, gps->triangles);
+ write_dverts(writer, gps->totpoints, gps->dvert);
}
}
}
@@ -3105,11 +3150,11 @@ static void write_area_map(WriteData *wd, ScrAreaMap *area_map)
}
}
-static void write_windowmanager(WriteData *wd, wmWindowManager *wm, const void *id_address)
+static void write_windowmanager(BlendWriter *writer, wmWindowManager *wm, const void *id_address)
{
- writestruct_at_address(wd, ID_WM, wmWindowManager, 1, id_address, wm);
- write_iddata(wd, &wm->id);
- write_wm_xr_data(wd, &wm->xr);
+ BLO_write_id_struct(writer, wmWindowManager, id_address, &wm->id);
+ write_iddata(writer, &wm->id);
+ write_wm_xr_data(writer->wd, &wm->xr);
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
#ifndef WITH_GLOBAL_AREA_WRITING
@@ -3121,12 +3166,12 @@ static void write_windowmanager(WriteData *wd, wmWindowManager *wm, const void *
/* update deprecated screen member (for so loading in 2.7x uses the correct screen) */
win->screen = BKE_workspace_active_screen_get(win->workspace_hook);
- writestruct(wd, DATA, wmWindow, 1, win);
- writestruct(wd, DATA, WorkSpaceInstanceHook, 1, win->workspace_hook);
- writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
+ BLO_write_struct(writer, wmWindow, win);
+ BLO_write_struct(writer, WorkSpaceInstanceHook, win->workspace_hook);
+ BLO_write_struct(writer, Stereo3dFormat, win->stereo3d_format);
#ifdef WITH_GLOBAL_AREA_WRITING
- write_area_map(wd, &win->global_areas);
+ write_area_map(writer->wd, &win->global_areas);
#else
win->global_areas = global_areas;
#endif
@@ -3136,19 +3181,19 @@ static void write_windowmanager(WriteData *wd, wmWindowManager *wm, const void *
}
}
-static void write_screen(WriteData *wd, bScreen *screen, const void *id_address)
+static void write_screen(BlendWriter *writer, bScreen *screen, const void *id_address)
{
/* Screens are reference counted, only saved if used by a workspace. */
- if (screen->id.us > 0 || wd->use_memfile) {
+ if (screen->id.us > 0 || BLO_write_is_undo(writer)) {
/* write LibData */
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
- writestruct_at_address(wd, ID_SCRN, bScreen, 1, id_address, screen);
- write_iddata(wd, &screen->id);
+ writestruct_at_address(writer->wd, ID_SCRN, bScreen, 1, id_address, screen);
+ write_iddata(writer, &screen->id);
- write_previews(wd, screen->preview);
+ write_previews(writer->wd, screen->preview);
/* direct data */
- write_area_map(wd, AREAMAP_FROM_SCREEN(screen));
+ write_area_map(writer->wd, AREAMAP_FROM_SCREEN(screen));
}
}
@@ -3172,9 +3217,9 @@ static void write_bone(WriteData *wd, Bone *bone)
}
}
-static void write_armature(WriteData *wd, bArmature *arm, const void *id_address)
+static void write_armature(BlendWriter *writer, bArmature *arm, const void *id_address)
{
- if (arm->id.us > 0 || wd->use_memfile) {
+ if (arm->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
arm->bonehash = NULL;
arm->edbo = NULL;
@@ -3182,21 +3227,21 @@ static void write_armature(WriteData *wd, bArmature *arm, const void *id_address
arm->needs_flush_to_id = 0;
arm->act_edbone = NULL;
- writestruct_at_address(wd, ID_AR, bArmature, 1, id_address, arm);
- write_iddata(wd, &arm->id);
+ BLO_write_id_struct(writer, bArmature, id_address, &arm->id);
+ write_iddata(writer, &arm->id);
if (arm->adt) {
- write_animdata(wd, arm->adt);
+ write_animdata(writer, arm->adt);
}
/* Direct data */
LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
- write_bone(wd, bone);
+ write_bone(writer->wd, bone);
}
}
}
-static void write_text(WriteData *wd, Text *text, const void *id_address)
+static void write_text(BlendWriter *writer, Text *text, const void *id_address)
{
/* Note: we are clearing local temp data here, *not* the flag in the actual 'real' ID. */
if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) {
@@ -3207,41 +3252,41 @@ static void write_text(WriteData *wd, Text *text, const void *id_address)
text->compiled = NULL;
/* write LibData */
- writestruct_at_address(wd, ID_TXT, Text, 1, id_address, text);
- write_iddata(wd, &text->id);
+ BLO_write_id_struct(writer, Text, id_address, &text->id);
+ write_iddata(writer, &text->id);
if (text->name) {
- writedata(wd, DATA, strlen(text->name) + 1, text->name);
+ BLO_write_string(writer, text->name);
}
if (!(text->flags & TXT_ISEXT)) {
/* now write the text data, in two steps for optimization in the readfunction */
LISTBASE_FOREACH (TextLine *, tmp, &text->lines) {
- writestruct(wd, DATA, TextLine, 1, tmp);
+ BLO_write_struct(writer, TextLine, tmp);
}
LISTBASE_FOREACH (TextLine *, tmp, &text->lines) {
- writedata(wd, DATA, tmp->len + 1, tmp->line);
+ BLO_write_raw(writer, tmp->len + 1, tmp->line);
}
}
}
-static void write_speaker(WriteData *wd, Speaker *spk, const void *id_address)
+static void write_speaker(BlendWriter *writer, Speaker *spk, const void *id_address)
{
- if (spk->id.us > 0 || wd->use_memfile) {
+ if (spk->id.us > 0 || BLO_write_is_undo(writer)) {
/* write LibData */
- writestruct_at_address(wd, ID_SPK, Speaker, 1, id_address, spk);
- write_iddata(wd, &spk->id);
+ BLO_write_id_struct(writer, Speaker, id_address, &spk->id);
+ write_iddata(writer, &spk->id);
if (spk->adt) {
- write_animdata(wd, spk->adt);
+ write_animdata(writer, spk->adt);
}
}
}
-static void write_sound(WriteData *wd, bSound *sound, const void *id_address)
+static void write_sound(BlendWriter *writer, bSound *sound, const void *id_address)
{
- if (sound->id.us > 0 || wd->use_memfile) {
+ if (sound->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
sound->tags = 0;
sound->handle = NULL;
@@ -3249,33 +3294,33 @@ static void write_sound(WriteData *wd, bSound *sound, const void *id_address)
sound->spinlock = NULL;
/* write LibData */
- writestruct_at_address(wd, ID_SO, bSound, 1, id_address, sound);
- write_iddata(wd, &sound->id);
+ BLO_write_id_struct(writer, bSound, id_address, &sound->id);
+ write_iddata(writer, &sound->id);
if (sound->packedfile) {
PackedFile *pf = sound->packedfile;
- writestruct(wd, DATA, PackedFile, 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
+ BLO_write_struct(writer, PackedFile, pf);
+ BLO_write_raw(writer, pf->size, pf->data);
}
}
}
-static void write_probe(WriteData *wd, LightProbe *prb, const void *id_address)
+static void write_probe(BlendWriter *writer, LightProbe *prb, const void *id_address)
{
- if (prb->id.us > 0 || wd->use_memfile) {
+ if (prb->id.us > 0 || BLO_write_is_undo(writer)) {
/* write LibData */
- writestruct_at_address(wd, ID_LP, LightProbe, 1, id_address, prb);
- write_iddata(wd, &prb->id);
+ BLO_write_id_struct(writer, LightProbe, id_address, &prb->id);
+ write_iddata(writer, &prb->id);
if (prb->adt) {
- write_animdata(wd, prb->adt);
+ write_animdata(writer, prb->adt);
}
}
}
-static void write_nodetree(WriteData *wd, bNodeTree *ntree, const void *id_address)
+static void write_nodetree(BlendWriter *writer, bNodeTree *ntree, const void *id_address)
{
- if (ntree->id.us > 0 || wd->use_memfile) {
+ if (ntree->id.us > 0 || BLO_write_is_undo(writer)) {
/* 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;
@@ -3284,82 +3329,82 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree, const void *id_addre
ntree->progress = NULL;
ntree->execdata = NULL;
- writestruct_at_address(wd, ID_NT, bNodeTree, 1, id_address, ntree);
+ BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id);
/* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot
* be linked, etc., so we write actual id data here only, for 'real' ID trees. */
- write_iddata(wd, &ntree->id);
+ write_iddata(writer, &ntree->id);
- write_nodetree_nolib(wd, ntree);
+ write_nodetree_nolib(writer, ntree);
}
}
-static void write_brush(WriteData *wd, Brush *brush, const void *id_address)
+static void write_brush(BlendWriter *writer, Brush *brush, const void *id_address)
{
- if (brush->id.us > 0 || wd->use_memfile) {
- writestruct_at_address(wd, ID_BR, Brush, 1, id_address, brush);
- write_iddata(wd, &brush->id);
+ if (brush->id.us > 0 || BLO_write_is_undo(writer)) {
+ BLO_write_id_struct(writer, Brush, id_address, &brush->id);
+ write_iddata(writer, &brush->id);
if (brush->curve) {
- write_curvemapping(wd, brush->curve);
+ write_curvemapping(writer->wd, brush->curve);
}
if (brush->gpencil_settings) {
- writestruct(wd, DATA, BrushGpencilSettings, 1, brush->gpencil_settings);
+ BLO_write_struct(writer, BrushGpencilSettings, brush->gpencil_settings);
if (brush->gpencil_settings->curve_sensitivity) {
- write_curvemapping(wd, brush->gpencil_settings->curve_sensitivity);
+ write_curvemapping(writer->wd, brush->gpencil_settings->curve_sensitivity);
}
if (brush->gpencil_settings->curve_strength) {
- write_curvemapping(wd, brush->gpencil_settings->curve_strength);
+ write_curvemapping(writer->wd, brush->gpencil_settings->curve_strength);
}
if (brush->gpencil_settings->curve_jitter) {
- write_curvemapping(wd, brush->gpencil_settings->curve_jitter);
+ write_curvemapping(writer->wd, brush->gpencil_settings->curve_jitter);
}
if (brush->gpencil_settings->curve_rand_pressure) {
- write_curvemapping(wd, brush->gpencil_settings->curve_rand_pressure);
+ write_curvemapping(writer->wd, brush->gpencil_settings->curve_rand_pressure);
}
if (brush->gpencil_settings->curve_rand_strength) {
- write_curvemapping(wd, brush->gpencil_settings->curve_rand_strength);
+ write_curvemapping(writer->wd, brush->gpencil_settings->curve_rand_strength);
}
if (brush->gpencil_settings->curve_rand_uv) {
- write_curvemapping(wd, brush->gpencil_settings->curve_rand_uv);
+ write_curvemapping(writer->wd, brush->gpencil_settings->curve_rand_uv);
}
if (brush->gpencil_settings->curve_rand_hue) {
- write_curvemapping(wd, brush->gpencil_settings->curve_rand_hue);
+ write_curvemapping(writer->wd, brush->gpencil_settings->curve_rand_hue);
}
if (brush->gpencil_settings->curve_rand_saturation) {
- write_curvemapping(wd, brush->gpencil_settings->curve_rand_saturation);
+ write_curvemapping(writer->wd, brush->gpencil_settings->curve_rand_saturation);
}
if (brush->gpencil_settings->curve_rand_value) {
- write_curvemapping(wd, brush->gpencil_settings->curve_rand_value);
+ write_curvemapping(writer->wd, brush->gpencil_settings->curve_rand_value);
}
}
if (brush->gradient) {
- writestruct(wd, DATA, ColorBand, 1, brush->gradient);
+ BLO_write_struct(writer, ColorBand, brush->gradient);
}
}
}
-static void write_palette(WriteData *wd, Palette *palette, const void *id_address)
+static void write_palette(BlendWriter *writer, Palette *palette, const void *id_address)
{
- if (palette->id.us > 0 || wd->use_memfile) {
+ if (palette->id.us > 0 || BLO_write_is_undo(writer)) {
PaletteColor *color;
- writestruct_at_address(wd, ID_PAL, Palette, 1, id_address, palette);
- write_iddata(wd, &palette->id);
+ BLO_write_id_struct(writer, Palette, id_address, &palette->id);
+ write_iddata(writer, &palette->id);
for (color = palette->colors.first; color; color = color->next) {
- writestruct(wd, DATA, PaletteColor, 1, color);
+ BLO_write_struct(writer, PaletteColor, color);
}
}
}
-static void write_paintcurve(WriteData *wd, PaintCurve *pc, const void *id_address)
+static void write_paintcurve(BlendWriter *writer, PaintCurve *pc, const void *id_address)
{
- if (pc->id.us > 0 || wd->use_memfile) {
- writestruct_at_address(wd, ID_PC, PaintCurve, 1, id_address, pc);
- write_iddata(wd, &pc->id);
+ if (pc->id.us > 0 || BLO_write_is_undo(writer)) {
+ BLO_write_id_struct(writer, PaintCurve, id_address, &pc->id);
+ write_iddata(writer, &pc->id);
- writestruct(wd, DATA, PaintCurvePoint, pc->tot_points, pc->points);
+ BLO_write_struct_array(writer, PaintCurvePoint, pc->tot_points, pc->points);
}
}
@@ -3402,9 +3447,9 @@ static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction
}
}
-static void write_movieclip(WriteData *wd, MovieClip *clip, const void *id_address)
+static void write_movieclip(BlendWriter *writer, MovieClip *clip, const void *id_address)
{
- if (clip->id.us > 0 || wd->use_memfile) {
+ if (clip->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
clip->anim = NULL;
clip->tracking_context = NULL;
@@ -3413,47 +3458,47 @@ static void write_movieclip(WriteData *wd, MovieClip *clip, const void *id_addre
MovieTracking *tracking = &clip->tracking;
MovieTrackingObject *object;
- writestruct_at_address(wd, ID_MC, MovieClip, 1, id_address, clip);
- write_iddata(wd, &clip->id);
+ BLO_write_id_struct(writer, MovieClip, id_address, &clip->id);
+ write_iddata(writer, &clip->id);
if (clip->adt) {
- write_animdata(wd, clip->adt);
+ write_animdata(writer, clip->adt);
}
- write_movieTracks(wd, &tracking->tracks);
- write_moviePlaneTracks(wd, &tracking->plane_tracks);
- write_movieReconstruction(wd, &tracking->reconstruction);
+ write_movieTracks(writer->wd, &tracking->tracks);
+ write_moviePlaneTracks(writer->wd, &tracking->plane_tracks);
+ write_movieReconstruction(writer->wd, &tracking->reconstruction);
object = tracking->objects.first;
while (object) {
- writestruct(wd, DATA, MovieTrackingObject, 1, object);
+ BLO_write_struct(writer, MovieTrackingObject, object);
- write_movieTracks(wd, &object->tracks);
- write_moviePlaneTracks(wd, &object->plane_tracks);
- write_movieReconstruction(wd, &object->reconstruction);
+ write_movieTracks(writer->wd, &object->tracks);
+ write_moviePlaneTracks(writer->wd, &object->plane_tracks);
+ write_movieReconstruction(writer->wd, &object->reconstruction);
object = object->next;
}
}
}
-static void write_mask(WriteData *wd, Mask *mask, const void *id_address)
+static void write_mask(BlendWriter *writer, Mask *mask, const void *id_address)
{
- if (mask->id.us > 0 || wd->use_memfile) {
+ if (mask->id.us > 0 || BLO_write_is_undo(writer)) {
MaskLayer *masklay;
- writestruct_at_address(wd, ID_MSK, Mask, 1, id_address, mask);
- write_iddata(wd, &mask->id);
+ BLO_write_id_struct(writer, Mask, id_address, &mask->id);
+ write_iddata(writer, &mask->id);
if (mask->adt) {
- write_animdata(wd, mask->adt);
+ write_animdata(writer, mask->adt);
}
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
MaskLayerShape *masklay_shape;
- writestruct(wd, DATA, MaskLayer, 1, masklay);
+ BLO_write_struct(writer, MaskLayer, masklay);
for (spline = masklay->splines.first; spline; spline = spline->next) {
int i;
@@ -3461,8 +3506,8 @@ static void write_mask(WriteData *wd, Mask *mask, const void *id_address)
void *points_deform = spline->points_deform;
spline->points_deform = NULL;
- writestruct(wd, DATA, MaskSpline, 1, spline);
- writestruct(wd, DATA, MaskSplinePoint, spline->tot_point, spline->points);
+ BLO_write_struct(writer, MaskSpline, spline);
+ BLO_write_struct_array(writer, MaskSplinePoint, spline->tot_point, spline->points);
spline->points_deform = points_deform;
@@ -3470,18 +3515,16 @@ static void write_mask(WriteData *wd, Mask *mask, const void *id_address)
MaskSplinePoint *point = &spline->points[i];
if (point->tot_uw) {
- writestruct(wd, DATA, MaskSplinePointUW, point->tot_uw, point->uw);
+ BLO_write_struct_array(writer, MaskSplinePointUW, point->tot_uw, point->uw);
}
}
}
for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
masklay_shape = masklay_shape->next) {
- writestruct(wd, DATA, MaskLayerShape, 1, masklay_shape);
- writedata(wd,
- DATA,
- masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE,
- masklay_shape->data);
+ BLO_write_struct(writer, MaskLayerShape, masklay_shape);
+ BLO_write_float_array(
+ writer, masklay_shape->tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE, masklay_shape->data);
}
}
}
@@ -3744,84 +3787,84 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier
}
}
-static void write_linestyle(WriteData *wd, FreestyleLineStyle *linestyle, const void *id_address)
+static void write_linestyle(BlendWriter *writer,
+ FreestyleLineStyle *linestyle,
+ const void *id_address)
{
- if (linestyle->id.us > 0 || wd->use_memfile) {
- writestruct_at_address(wd, ID_LS, FreestyleLineStyle, 1, id_address, linestyle);
- write_iddata(wd, &linestyle->id);
+ if (linestyle->id.us > 0 || BLO_write_is_undo(writer)) {
+ BLO_write_id_struct(writer, FreestyleLineStyle, id_address, &linestyle->id);
+ write_iddata(writer, &linestyle->id);
if (linestyle->adt) {
- write_animdata(wd, linestyle->adt);
+ write_animdata(writer, linestyle->adt);
}
- write_linestyle_color_modifiers(wd, &linestyle->color_modifiers);
- write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers);
- write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers);
- write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers);
+ write_linestyle_color_modifiers(writer->wd, &linestyle->color_modifiers);
+ write_linestyle_alpha_modifiers(writer->wd, &linestyle->alpha_modifiers);
+ write_linestyle_thickness_modifiers(writer->wd, &linestyle->thickness_modifiers);
+ write_linestyle_geometry_modifiers(writer->wd, &linestyle->geometry_modifiers);
for (int a = 0; a < MAX_MTEX; a++) {
if (linestyle->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]);
+ BLO_write_struct(writer, MTex, linestyle->mtex[a]);
}
}
if (linestyle->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, linestyle->nodetree);
- write_nodetree_nolib(wd, linestyle->nodetree);
+ BLO_write_struct(writer, bNodeTree, linestyle->nodetree);
+ write_nodetree_nolib(writer, linestyle->nodetree);
}
}
}
-static void write_cachefile(WriteData *wd, CacheFile *cache_file, const void *id_address)
+static void write_cachefile(BlendWriter *writer, CacheFile *cache_file, const void *id_address)
{
- if (cache_file->id.us > 0 || wd->use_memfile) {
+ if (cache_file->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
BLI_listbase_clear(&cache_file->object_paths);
cache_file->handle = NULL;
memset(cache_file->handle_filepath, 0, sizeof(cache_file->handle_filepath));
cache_file->handle_readers = NULL;
- writestruct_at_address(wd, ID_CF, CacheFile, 1, id_address, cache_file);
+ BLO_write_id_struct(writer, CacheFile, id_address, &cache_file->id);
if (cache_file->adt) {
- write_animdata(wd, cache_file->adt);
+ write_animdata(writer, cache_file->adt);
}
}
}
-static void write_workspace(WriteData *wd, WorkSpace *workspace, const void *id_address)
+static void write_workspace(BlendWriter *writer, WorkSpace *workspace, const void *id_address)
{
- ListBase *layouts = BKE_workspace_layouts_get(workspace);
-
- writestruct_at_address(wd, ID_WS, WorkSpace, 1, id_address, workspace);
- write_iddata(wd, &workspace->id);
- writelist(wd, DATA, WorkSpaceLayout, layouts);
- writelist(wd, DATA, WorkSpaceDataRelation, &workspace->hook_layout_relations);
- writelist(wd, DATA, wmOwnerID, &workspace->owner_ids);
- writelist(wd, DATA, bToolRef, &workspace->tools);
+ BLO_write_id_struct(writer, WorkSpace, id_address, &workspace->id);
+ write_iddata(writer, &workspace->id);
+ BLO_write_struct_list(writer, WorkSpaceLayout, &workspace->layouts);
+ BLO_write_struct_list(writer, WorkSpaceDataRelation, &workspace->hook_layout_relations);
+ BLO_write_struct_list(writer, wmOwnerID, &workspace->owner_ids);
+ BLO_write_struct_list(writer, bToolRef, &workspace->tools);
LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
if (tref->properties) {
- IDP_WriteProperty(tref->properties, wd);
+ IDP_WriteProperty_new_api(tref->properties, writer);
}
}
}
-static void write_hair(WriteData *wd, Hair *hair, const void *id_address)
+static void write_hair(BlendWriter *writer, Hair *hair, const void *id_address)
{
- if (hair->id.us > 0 || wd->use_memfile) {
+ if (hair->id.us > 0 || BLO_write_is_undo(writer)) {
CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
CustomDataLayer *clayers = NULL, clayers_buff[CD_TEMP_CHUNK_SIZE];
CustomData_file_write_prepare(&hair->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
CustomData_file_write_prepare(&hair->cdata, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
/* Write LibData */
- writestruct_at_address(wd, ID_HA, Hair, 1, id_address, hair);
- write_iddata(wd, &hair->id);
+ BLO_write_id_struct(writer, Hair, id_address, &hair->id);
+ write_iddata(writer, &hair->id);
/* Direct data */
- write_customdata(wd, &hair->id, hair->totpoint, &hair->pdata, players, CD_MASK_ALL);
- write_customdata(wd, &hair->id, hair->totcurve, &hair->cdata, clayers, CD_MASK_ALL);
- writedata(wd, DATA, sizeof(void *) * hair->totcol, hair->mat);
+ write_customdata(writer, &hair->id, hair->totpoint, &hair->pdata, players, CD_MASK_ALL);
+ write_customdata(writer, &hair->id, hair->totcurve, &hair->cdata, clayers, CD_MASK_ALL);
+ BLO_write_pointer_array(writer, hair->totcol, hair->mat);
if (hair->adt) {
- write_animdata(wd, hair->adt);
+ write_animdata(writer, hair->adt);
}
/* Remove temporary data. */
@@ -3834,23 +3877,23 @@ static void write_hair(WriteData *wd, Hair *hair, const void *id_address)
}
}
-static void write_pointcloud(WriteData *wd, PointCloud *pointcloud, const void *id_address)
+static void write_pointcloud(BlendWriter *writer, PointCloud *pointcloud, const void *id_address)
{
- if (pointcloud->id.us > 0 || wd->use_memfile) {
+ if (pointcloud->id.us > 0 || BLO_write_is_undo(writer)) {
CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
CustomData_file_write_prepare(
&pointcloud->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
/* Write LibData */
- writestruct_at_address(wd, ID_PT, PointCloud, 1, id_address, pointcloud);
- write_iddata(wd, &pointcloud->id);
+ BLO_write_id_struct(writer, PointCloud, id_address, &pointcloud->id);
+ write_iddata(writer, &pointcloud->id);
/* Direct data */
write_customdata(
- wd, &pointcloud->id, pointcloud->totpoint, &pointcloud->pdata, players, CD_MASK_ALL);
- writedata(wd, DATA, sizeof(void *) * pointcloud->totcol, pointcloud->mat);
+ writer, &pointcloud->id, pointcloud->totpoint, &pointcloud->pdata, players, CD_MASK_ALL);
+ BLO_write_pointer_array(writer, pointcloud->totcol, pointcloud->mat);
if (pointcloud->adt) {
- write_animdata(wd, pointcloud->adt);
+ write_animdata(writer, pointcloud->adt);
}
/* Remove temporary data. */
@@ -3860,44 +3903,44 @@ static void write_pointcloud(WriteData *wd, PointCloud *pointcloud, const void *
}
}
-static void write_volume(WriteData *wd, Volume *volume, const void *id_address)
+static void write_volume(BlendWriter *writer, Volume *volume, const void *id_address)
{
- if (volume->id.us > 0 || wd->use_memfile) {
+ if (volume->id.us > 0 || BLO_write_is_undo(writer)) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
volume->runtime.grids = 0;
/* write LibData */
- writestruct_at_address(wd, ID_VO, Volume, 1, id_address, volume);
- write_iddata(wd, &volume->id);
+ BLO_write_id_struct(writer, Volume, id_address, &volume->id);
+ write_iddata(writer, &volume->id);
/* direct data */
- writedata(wd, DATA, sizeof(void *) * volume->totcol, volume->mat);
+ BLO_write_pointer_array(writer, volume->totcol, volume->mat);
if (volume->adt) {
- write_animdata(wd, volume->adt);
+ write_animdata(writer, volume->adt);
}
if (volume->packedfile) {
PackedFile *pf = volume->packedfile;
- writestruct(wd, DATA, PackedFile, 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
+ BLO_write_struct(writer, PackedFile, pf);
+ BLO_write_raw(writer, pf->size, pf->data);
}
}
}
-static void write_simulation(WriteData *wd, Simulation *simulation)
+static void write_simulation(BlendWriter *writer, Simulation *simulation, const void *id_address)
{
- if (simulation->id.us > 0 || wd->use_memfile) {
- writestruct(wd, ID_SIM, Simulation, 1, simulation);
- write_iddata(wd, &simulation->id);
+ if (simulation->id.us > 0 || BLO_write_is_undo(writer)) {
+ BLO_write_id_struct(writer, Simulation, id_address, &simulation->id);
+ write_iddata(writer, &simulation->id);
if (simulation->adt) {
- write_animdata(wd, simulation->adt);
+ write_animdata(writer, simulation->adt);
}
/* nodetree is integral part of simulation, no libdata */
if (simulation->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, simulation->nodetree);
- write_nodetree_nolib(wd, simulation->nodetree);
+ BLO_write_struct(writer, bNodeTree, simulation->nodetree);
+ write_nodetree_nolib(writer, simulation->nodetree);
}
}
}
@@ -3917,6 +3960,11 @@ static void write_libraries(WriteData *wd, Main *main)
if (main->curlib && main->curlib->packedfile) {
found_one = true;
}
+ else if (wd->use_memfile) {
+ /* When writing undo step we always write all existing libraries, makes reading undo step
+ * much easier when dealing with purely indirectly used libraries. */
+ found_one = true;
+ }
else {
found_one = false;
while (!found_one && tot--) {
@@ -3938,8 +3986,9 @@ static void write_libraries(WriteData *wd, Main *main)
if (found_one) {
/* Not overridable. */
+ BlendWriter writer = {wd};
writestruct(wd, ID_LI, Library, 1, main->curlib);
- write_iddata(wd, &main->curlib->id);
+ write_iddata(&writer, &main->curlib->id);
if (main->curlib->packedfile) {
PackedFile *pf = main->curlib->packedfile;
@@ -4004,12 +4053,12 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
fg.globalf = G.f;
BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename));
- sprintf(subvstr, "%4d", BLENDER_SUBVERSION);
+ sprintf(subvstr, "%4d", BLENDER_FILE_SUBVERSION);
memcpy(fg.subvstr, subvstr, 4);
- fg.subversion = BLENDER_SUBVERSION;
- fg.minversion = BLENDER_MINVERSION;
- fg.minsubversion = BLENDER_MINSUBVERSION;
+ fg.subversion = BLENDER_FILE_SUBVERSION;
+ fg.minversion = BLENDER_FILE_MIN_VERSION;
+ fg.minsubversion = BLENDER_FILE_MIN_SUBVERSION;
#ifdef WITH_BUILDINFO
{
extern unsigned long build_commit_timestamp;
@@ -4063,7 +4112,7 @@ static bool write_file_handle(Main *mainvar,
"BLENDER%c%c%.3d",
(sizeof(void *) == 8) ? '-' : '_',
(ENDIAN_ORDER == B_ENDIAN) ? 'V' : 'v',
- BLENDER_VERSION);
+ BLENDER_FILE_VERSION);
mywrite(wd, buf, 12);
@@ -4135,124 +4184,133 @@ static bool write_file_handle(Main *mainvar,
}
}
+ mywrite_id_begin(wd, id);
+
memcpy(id_buffer, id, idtype_struct_size);
((ID *)id_buffer)->tag = 0;
+ /* Those listbase data change every time we add/remove an ID, and also often when renaming
+ * one (due to re-sorting). This avoids generating a lot of false 'is changed' detections
+ * between undo steps. */
+ ((ID *)id_buffer)->prev = NULL;
+ ((ID *)id_buffer)->next = NULL;
+
+ BlendWriter writer = {wd};
switch ((ID_Type)GS(id->name)) {
case ID_WM:
- write_windowmanager(wd, (wmWindowManager *)id_buffer, id);
+ write_windowmanager(&writer, (wmWindowManager *)id_buffer, id);
break;
case ID_WS:
- write_workspace(wd, (WorkSpace *)id_buffer, id);
+ write_workspace(&writer, (WorkSpace *)id_buffer, id);
break;
case ID_SCR:
- write_screen(wd, (bScreen *)id_buffer, id);
+ write_screen(&writer, (bScreen *)id_buffer, id);
break;
case ID_MC:
- write_movieclip(wd, (MovieClip *)id_buffer, id);
+ write_movieclip(&writer, (MovieClip *)id_buffer, id);
break;
case ID_MSK:
- write_mask(wd, (Mask *)id_buffer, id);
+ write_mask(&writer, (Mask *)id_buffer, id);
break;
case ID_SCE:
- write_scene(wd, (Scene *)id_buffer, id);
+ write_scene(&writer, (Scene *)id_buffer, id);
break;
case ID_CU:
- write_curve(wd, (Curve *)id_buffer, id);
+ write_curve(&writer, (Curve *)id_buffer, id);
break;
case ID_MB:
- write_mball(wd, (MetaBall *)id_buffer, id);
+ write_mball(&writer, (MetaBall *)id_buffer, id);
break;
case ID_IM:
- write_image(wd, (Image *)id_buffer, id);
+ write_image(&writer, (Image *)id_buffer, id);
break;
case ID_CA:
- write_camera(wd, (Camera *)id_buffer, id);
+ write_camera(&writer, (Camera *)id_buffer, id);
break;
case ID_LA:
- write_light(wd, (Light *)id_buffer, id);
+ write_light(&writer, (Light *)id_buffer, id);
break;
case ID_LT:
- write_lattice(wd, (Lattice *)id_buffer, id);
+ write_lattice(&writer, (Lattice *)id_buffer, id);
break;
case ID_VF:
- write_vfont(wd, (VFont *)id_buffer, id);
+ write_vfont(&writer, (VFont *)id_buffer, id);
break;
case ID_KE:
- write_key(wd, (Key *)id_buffer, id);
+ write_key(&writer, (Key *)id_buffer, id);
break;
case ID_WO:
- write_world(wd, (World *)id_buffer, id);
+ write_world(&writer, (World *)id_buffer, id);
break;
case ID_TXT:
- write_text(wd, (Text *)id_buffer, id);
+ write_text(&writer, (Text *)id_buffer, id);
break;
case ID_SPK:
- write_speaker(wd, (Speaker *)id_buffer, id);
+ write_speaker(&writer, (Speaker *)id_buffer, id);
break;
case ID_LP:
- write_probe(wd, (LightProbe *)id_buffer, id);
+ write_probe(&writer, (LightProbe *)id_buffer, id);
break;
case ID_SO:
- write_sound(wd, (bSound *)id_buffer, id);
+ write_sound(&writer, (bSound *)id_buffer, id);
break;
case ID_GR:
- write_collection(wd, (Collection *)id_buffer, id);
+ write_collection(&writer, (Collection *)id_buffer, id);
break;
case ID_AR:
- write_armature(wd, (bArmature *)id_buffer, id);
+ write_armature(&writer, (bArmature *)id_buffer, id);
break;
case ID_AC:
- write_action(wd, (bAction *)id_buffer, id);
+ write_action(&writer, (bAction *)id_buffer, id);
break;
case ID_OB:
- write_object(wd, (Object *)id_buffer, id);
+ write_object(&writer, (Object *)id_buffer, id);
break;
case ID_MA:
- write_material(wd, (Material *)id_buffer, id);
+ write_material(&writer, (Material *)id_buffer, id);
break;
case ID_TE:
- write_texture(wd, (Tex *)id_buffer, id);
+ write_texture(&writer, (Tex *)id_buffer, id);
break;
case ID_ME:
- write_mesh(wd, (Mesh *)id_buffer, id);
+ write_mesh(&writer, (Mesh *)id_buffer, id);
break;
case ID_PA:
- write_particlesettings(wd, (ParticleSettings *)id_buffer, id);
+ write_particlesettings(&writer, (ParticleSettings *)id_buffer, id);
break;
case ID_NT:
- write_nodetree(wd, (bNodeTree *)id_buffer, id);
+ write_nodetree(&writer, (bNodeTree *)id_buffer, id);
break;
case ID_BR:
- write_brush(wd, (Brush *)id_buffer, id);
+ write_brush(&writer, (Brush *)id_buffer, id);
break;
case ID_PAL:
- write_palette(wd, (Palette *)id_buffer, id);
+ write_palette(&writer, (Palette *)id_buffer, id);
break;
case ID_PC:
- write_paintcurve(wd, (PaintCurve *)id_buffer, id);
+ write_paintcurve(&writer, (PaintCurve *)id_buffer, id);
break;
case ID_GD:
- write_gpencil(wd, (bGPdata *)id_buffer, id);
+ write_gpencil(&writer, (bGPdata *)id_buffer, id);
break;
case ID_LS:
- write_linestyle(wd, (FreestyleLineStyle *)id_buffer, id);
+ write_linestyle(&writer, (FreestyleLineStyle *)id_buffer, id);
break;
case ID_CF:
- write_cachefile(wd, (CacheFile *)id_buffer, id);
+ write_cachefile(&writer, (CacheFile *)id_buffer, id);
break;
case ID_HA:
- write_hair(wd, (Hair *)id_buffer, id);
+ write_hair(&writer, (Hair *)id_buffer, id);
break;
case ID_PT:
- write_pointcloud(wd, (PointCloud *)id_buffer, id);
+ write_pointcloud(&writer, (PointCloud *)id_buffer, id);
break;
case ID_VO:
- write_volume(wd, (Volume *)id_buffer, id);
+ write_volume(&writer, (Volume *)id_buffer, id);
break;
case ID_SIM:
- write_simulation(wd, (Simulation *)id);
+ write_simulation(&writer, (Simulation *)id_buffer, id);
break;
case ID_LI:
/* Do nothing, handled below - and should never be reached. */
@@ -4271,11 +4329,7 @@ static bool write_file_handle(Main *mainvar,
BKE_lib_override_library_operations_store_end(override_storage, id);
}
- if (wd->use_memfile) {
- /* Very important to do it after every ID write now, otherwise we cannot know whether a
- * specific ID changed or not. */
- mywrite_flush(wd);
- }
+ mywrite_id_end(wd, id);
}
if (id_buffer != id_buffer_static) {
@@ -4490,4 +4544,103 @@ bool BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, int w
return (err == 0);
}
+void BLO_write_raw(BlendWriter *writer, int size_in_bytes, const void *data_ptr)
+{
+ writedata(writer->wd, DATA, size_in_bytes, data_ptr);
+}
+
+void BLO_write_struct_by_name(BlendWriter *writer, const char *struct_name, const void *data_ptr)
+{
+ int struct_id = BLO_get_struct_id_by_name(writer, struct_name);
+ BLO_write_struct_by_id(writer, struct_id, data_ptr);
+}
+
+void BLO_write_struct_array_by_name(BlendWriter *writer,
+ const char *struct_name,
+ int array_size,
+ const void *data_ptr)
+{
+ int struct_id = BLO_get_struct_id_by_name(writer, struct_name);
+ BLO_write_struct_array_by_id(writer, struct_id, array_size, data_ptr);
+}
+
+void BLO_write_struct_by_id(BlendWriter *writer, int struct_id, const void *data_ptr)
+{
+ writestruct_nr(writer->wd, DATA, struct_id, 1, data_ptr);
+}
+
+void BLO_write_struct_array_by_id(BlendWriter *writer,
+ int struct_id,
+ int array_size,
+ const void *data_ptr)
+{
+ writestruct_nr(writer->wd, DATA, struct_id, array_size, data_ptr);
+}
+
+void BLO_write_struct_list_by_id(BlendWriter *writer, int struct_id, ListBase *list)
+{
+ writelist_nr(writer->wd, DATA, struct_id, list);
+}
+
+void BLO_write_struct_list_by_name(BlendWriter *writer, const char *struct_name, ListBase *list)
+{
+ BLO_write_struct_list_by_id(writer, BLO_get_struct_id_by_name(writer, struct_name), list);
+}
+
+void blo_write_id_struct(BlendWriter *writer, int struct_id, const void *id_address, const ID *id)
+{
+ writestruct_at_address_nr(writer->wd, GS(id->name), struct_id, 1, id_address, id);
+}
+
+int BLO_get_struct_id_by_name(BlendWriter *writer, const char *struct_name)
+{
+ int struct_id = DNA_struct_find_nr(writer->wd->sdna, struct_name);
+ BLI_assert(struct_id >= 0);
+ return struct_id;
+}
+
+void BLO_write_int32_array(BlendWriter *writer, int size, const int32_t *data_ptr)
+{
+ BLO_write_raw(writer, sizeof(int32_t) * size, data_ptr);
+}
+
+void BLO_write_uint32_array(BlendWriter *writer, int size, const uint32_t *data_ptr)
+{
+ BLO_write_raw(writer, sizeof(uint32_t) * size, data_ptr);
+}
+
+void BLO_write_float_array(BlendWriter *writer, int size, const float *data_ptr)
+{
+ BLO_write_raw(writer, sizeof(float) * size, data_ptr);
+}
+
+void BLO_write_pointer_array(BlendWriter *writer, int size, const void *data_ptr)
+{
+ BLO_write_raw(writer, sizeof(void *) * size, data_ptr);
+}
+
+void BLO_write_float3_array(BlendWriter *writer, int size, const float *data_ptr)
+{
+ BLO_write_raw(writer, sizeof(float) * 3 * size, data_ptr);
+}
+
+/**
+ * Write a null terminated string.
+ */
+void BLO_write_string(BlendWriter *writer, const char *str)
+{
+ if (str != NULL) {
+ BLO_write_raw(writer, strlen(str) + 1, str);
+ }
+}
+
+/**
+ * Sometimes different data is written depending on whether the file is saved to disk or used for
+ * undo. This function returns true when the current file-writing is done for undo.
+ */
+bool BLO_write_is_undo(BlendWriter *writer)
+{
+ return writer->wd->use_memfile;
+}
+
/** \} */
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 35c33837d64..7a389c63abd 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -56,7 +56,7 @@ set(SRC
operators/bmo_hull.c
operators/bmo_inset.c
operators/bmo_join_triangles.c
- operators/bmo_mesh_conv.c
+ operators/bmo_mesh_convert.c
operators/bmo_mirror.c
operators/bmo_normals.c
operators/bmo_offset_edgeloops.c
@@ -97,8 +97,8 @@ set(SRC
intern/bmesh_marking.h
intern/bmesh_mesh.c
intern/bmesh_mesh.h
- intern/bmesh_mesh_conv.c
- intern/bmesh_mesh_conv.h
+ intern/bmesh_mesh_convert.c
+ intern/bmesh_mesh_convert.h
intern/bmesh_mesh_duplicate.c
intern/bmesh_mesh_duplicate.h
intern/bmesh_mesh_validate.c
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index 9b5072e8e16..c0791e6fdbc 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -215,7 +215,7 @@ extern "C" {
#include "intern/bmesh_log.h"
#include "intern/bmesh_marking.h"
#include "intern/bmesh_mesh.h"
-#include "intern/bmesh_mesh_conv.h"
+#include "intern/bmesh_mesh_convert.h"
#include "intern/bmesh_mesh_duplicate.h"
#include "intern/bmesh_mesh_validate.h"
#include "intern/bmesh_mods.h"
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 1bf419f4461..177599656b6 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -1021,7 +1021,7 @@ void BM_select_history_validate(BMesh *bm)
bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
{
BMEditSelection *ese_last = bm->selected.last;
- BMFace *efa = BM_mesh_active_face_get(bm, false, false);
+ BMFace *efa = BM_mesh_active_face_get(bm, false, true);
ese->next = ese->prev = NULL;
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_convert.c
index de32d7881b0..b8508f7e12c 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_convert.c
@@ -893,6 +893,10 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey);
cd_shape_offset = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, j);
+ if (cd_shape_offset < 0) {
+ /* The target Mesh has more shapekeys than the BMesh. */
+ continue;
+ }
fp = newkey = MEM_callocN(me->key->elemsize * bm->totvert, "currkey->data");
oldkey = currkey->data;
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_convert.h
index 1ad43558c60..1ad43558c60 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_convert.h
diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c
index 64950411fed..e000b253000 100644
--- a/source/blender/bmesh/intern/bmesh_query.c
+++ b/source/blender/bmesh/intern/bmesh_query.c
@@ -1568,6 +1568,41 @@ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq,
}
/**
+ * A version of BM_loop_calc_face_normal_safe_ex which takes vertex coordinates.
+ */
+float BM_loop_calc_face_normal_safe_vcos_ex(const BMLoop *l,
+ const float normal_fallback[3],
+ float const (*vertexCos)[3],
+ const float epsilon_sq,
+ float r_normal[3])
+{
+ const int i_prev = BM_elem_index_get(l->prev->v);
+ const int i_next = BM_elem_index_get(l->next->v);
+ const int i = BM_elem_index_get(l->v);
+
+ float v1[3], v2[3], v_tmp[3];
+ sub_v3_v3v3(v1, vertexCos[i_prev], vertexCos[i]);
+ sub_v3_v3v3(v2, vertexCos[i_next], vertexCos[i]);
+
+ const float fac = ((v2[0] == 0.0f) ?
+ ((v2[1] == 0.0f) ? ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) :
+ v1[1] / v2[1]) :
+ v1[0] / v2[0]);
+
+ mul_v3_v3fl(v_tmp, v2, fac);
+ sub_v3_v3(v_tmp, v1);
+ if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) {
+ /* Not co-linear, we can compute cross-product and normalize it into normal. */
+ cross_v3_v3v3(r_normal, v1, v2);
+ return normalize_v3(r_normal);
+ }
+ else {
+ copy_v3_v3(r_normal, normal_fallback);
+ return 0.0f;
+ }
+}
+
+/**
* #BM_loop_calc_face_normal_safe_ex with pre-defined sane epsilon.
*
* Since this doesn't scale based on triangle size, fixed value works well.
@@ -1577,6 +1612,15 @@ float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal);
}
+float BM_loop_calc_face_normal_safe_vcos(const BMLoop *l,
+ const float normal_fallback[3],
+ float const (*vertexCos)[3],
+ float r_normal[3])
+
+{
+ return BM_loop_calc_face_normal_safe_vcos_ex(l, normal_fallback, vertexCos, 1e-5f, r_normal);
+}
+
/**
* \brief BM_loop_calc_face_normal
*
diff --git a/source/blender/bmesh/intern/bmesh_query.h b/source/blender/bmesh/intern/bmesh_query.h
index aaf8191c5db..7e07059d4d8 100644
--- a/source/blender/bmesh/intern/bmesh_query.h
+++ b/source/blender/bmesh/intern/bmesh_query.h
@@ -142,6 +142,16 @@ float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(
float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3])
ATTR_NONNULL();
+float BM_loop_calc_face_normal_safe_vcos_ex(const BMLoop *l,
+ const float normal_fallback[3],
+ float const (*vertexCos)[3],
+ const float epsilon_sq,
+ float r_normal[3]) ATTR_NONNULL();
+float BM_loop_calc_face_normal_safe_vcos(const BMLoop *l,
+ const float normal_fallback[3],
+ float const (*vertexCos)[3],
+ float r_normal[3]) ATTR_NONNULL();
+
void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]);
void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]);
diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_convert.c
index e480db64f9d..e480db64f9d 100644
--- a/source/blender/bmesh/operators/bmo_mesh_conv.c
+++ b/source/blender/bmesh/operators/bmo_mesh_convert.c
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index 64687ac154c..d661859c8e3 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -1393,16 +1393,15 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
BMVert *v1, *v2, *lastv1 = NULL, *lastv2 = NULL, *cent1, *cent2, *firstv1, *firstv2;
BMFace *f;
float vec[3], mat[4][4], phi, phid;
- float dia1 = BMO_slot_float_get(op->slots_in, "diameter1");
- float dia2 = BMO_slot_float_get(op->slots_in, "diameter2");
- float depth = BMO_slot_float_get(op->slots_in, "depth");
+ const float dia1 = BMO_slot_float_get(op->slots_in, "diameter1");
+ const float dia2 = BMO_slot_float_get(op->slots_in, "diameter2");
+ const float depth_half = 0.5f * BMO_slot_float_get(op->slots_in, "depth");
int segs = BMO_slot_int_get(op->slots_in, "segments");
const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
- int a;
if (!segs) {
return;
@@ -1413,16 +1412,15 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
phid = 2.0f * (float)M_PI / segs;
phi = 0;
- depth *= 0.5f;
if (cap_ends) {
vec[0] = vec[1] = 0.0f;
- vec[2] = -depth;
+ vec[2] = -depth_half;
mul_m4_v3(mat, vec);
cent1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
vec[0] = vec[1] = 0.0f;
- vec[2] = depth;
+ vec[2] = depth_half;
mul_m4_v3(mat, vec);
cent2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
@@ -1431,23 +1429,26 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
BMO_vert_flag_enable(bm, cent2, VERT_MARK);
}
- for (a = 0; a < segs; a++, phi += phid) {
+ const int side_faces_len = segs - 1;
+ BMFace **side_faces = MEM_mallocN(sizeof(*side_faces) * side_faces_len, __func__);
+
+ for (int i = 0; i < segs; i++, phi += phid) {
vec[0] = dia1 * sinf(phi);
vec[1] = dia1 * cosf(phi);
- vec[2] = -depth;
+ vec[2] = -depth_half;
mul_m4_v3(mat, vec);
v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
vec[0] = dia2 * sinf(phi);
vec[1] = dia2 * cosf(phi);
- vec[2] = depth;
+ vec[2] = depth_half;
mul_m4_v3(mat, vec);
v2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_vert_flag_enable(bm, v1, VERT_MARK);
BMO_vert_flag_enable(bm, v2, VERT_MARK);
- if (a) {
+ if (i) {
if (cap_ends) {
f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, BM_CREATE_NOP);
if (calc_uvs) {
@@ -1466,6 +1467,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
if (calc_uvs) {
BMO_face_flag_enable(bm, f, FACE_MARK);
}
+ side_faces[i - 1] = f;
}
else {
firstv1 = v1;
@@ -1476,10 +1478,6 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
lastv2 = v2;
}
- if (!a) {
- return;
- }
-
if (cap_ends) {
f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, BM_CREATE_NOP);
if (calc_uvs) {
@@ -1503,11 +1501,38 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
BM_mesh_calc_uvs_cone(bm, mat, dia2, dia1, segs, cap_ends, FACE_MARK, cd_loop_uv_offset);
}
+ /* Collapse vertices at the first end. */
+ if (dia1 == 0.0f) {
+ if (cap_ends) {
+ BM_vert_kill(bm, cent1);
+ }
+ for (int i = 0; i < side_faces_len; i++) {
+ f = side_faces[i];
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ BM_edge_collapse(bm, l->prev->e, l->prev->v, true, true);
+ }
+ }
+
+ /* Collapse vertices at the second end. */
+ if (dia2 == 0.0f) {
+ if (cap_ends) {
+ BM_vert_kill(bm, cent2);
+ }
+ for (int i = 0; i < side_faces_len; i++) {
+ f = side_faces[i];
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ BM_edge_collapse(bm, l->next->e, l->next->v, true, true);
+ }
+ }
+
if (!cap_tris) {
BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW);
}
- BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.0000005 * depth);
+ if (side_faces != NULL) {
+ MEM_freeN(side_faces);
+ }
+
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c
index 0331ca476dd..713a68969e5 100644
--- a/source/blender/bmesh/tools/bmesh_path.c
+++ b/source/blender/bmesh/tools/bmesh_path.c
@@ -225,7 +225,7 @@ static void edgetag_add_adjacent(HeapSimple *heap,
/* unlike vert/face, stepping faces disables scanning connected edges
* and only steps over faces (selecting a ring of edges instead of a loop) */
- if (params->use_step_face == false) {
+ if (params->use_step_face == false || e_a->l == NULL) {
BMIter viter;
BMVert *v;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index eddc58a8d98..9230fa19c32 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -83,6 +83,7 @@
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
+#include "BKE_light.h"
#include "BKE_mask.h"
#include "BKE_material.h"
#include "BKE_mball.h"
@@ -1441,6 +1442,12 @@ void DepsgraphNodeBuilder::build_light(Light *lamp)
build_parameters(&lamp->id);
/* light's nodetree */
build_nodetree(lamp->nodetree);
+
+ Light *lamp_cow = get_cow_datablock(lamp);
+ add_operation_node(&lamp->id,
+ NodeType::SHADING,
+ OperationCode::LIGHT_UPDATE,
+ function_bind(BKE_light_eval, _1, lamp_cow));
}
void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
@@ -1574,6 +1581,7 @@ void DepsgraphNodeBuilder::build_texture(Tex *texture)
return;
}
/* Texture itself. */
+ add_id_node(&texture->id);
build_idproperties(texture->id.properties);
build_animdata(&texture->id);
build_parameters(&texture->id);
@@ -1759,10 +1767,13 @@ void DepsgraphNodeBuilder::build_simulation(Simulation *simulation)
build_animdata(&simulation->id);
build_parameters(&simulation->id);
+ Simulation *simulation_cow = get_cow_datablock(simulation);
+ Scene *scene_cow = get_cow_datablock(scene_);
+
add_operation_node(&simulation->id,
NodeType::SIMULATION,
OperationCode::SIMULATION_EVAL,
- function_bind(BKE_simulation_data_update, _1, get_cow_datablock(scene_)));
+ function_bind(BKE_simulation_data_update, _1, scene_cow, simulation_cow));
}
void DepsgraphNodeBuilder::build_scene_sequencer(Scene *scene)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h
index c3c90e5aae4..df8b295f5bb 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h
@@ -28,7 +28,7 @@
namespace DEG {
struct RootPChanMap {
- /* ctor and dtor - Create and free the internal map respectively. */
+ /* Constructor and destructor - Create and free the internal map respectively. */
RootPChanMap();
~RootPChanMap();
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index ae90ad8a281..f5a131a1731 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -1500,7 +1500,10 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
}
}
if (property_entry_key.prop != nullptr && RNA_property_is_idprop(property_entry_key.prop)) {
- RNAPathKey property_exit_key(id, rna_path, RNAPointerSource::EXIT);
+ RNAPathKey property_exit_key(property_entry_key.id,
+ property_entry_key.ptr,
+ property_entry_key.prop,
+ RNAPointerSource::EXIT);
OperationKey parameters_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
add_relation(property_exit_key, parameters_key, "Driven Property -> Properties");
}
@@ -2245,14 +2248,20 @@ void DepsgraphRelationBuilder::build_light(Light *lamp)
build_idproperties(lamp->id.properties);
build_animdata(&lamp->id);
build_parameters(&lamp->id);
+
+ ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
+
/* light's nodetree */
if (lamp->nodetree != nullptr) {
build_nodetree(lamp->nodetree);
- ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
ComponentKey nodetree_key(&lamp->nodetree->id, NodeType::SHADING);
add_relation(nodetree_key, lamp_parameters_key, "NTree->Light Parameters");
build_nested_nodetree(&lamp->id, lamp->nodetree);
}
+
+ /* For allowing drivers on lamp properties. */
+ ComponentKey shading_key(&lamp->id, NodeType::SHADING);
+ add_relation(lamp_parameters_key, shading_key, "Light Shading Parameters");
}
void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
@@ -2422,6 +2431,11 @@ void DepsgraphRelationBuilder::build_texture(Tex *texture)
ComponentKey animation_key(&texture->id, NodeType::ANIMATION);
add_relation(animation_key, texture_key, "Datablock Animation");
}
+
+ if (BKE_image_user_id_has_animation(&texture->id)) {
+ ComponentKey image_animation_key(&texture->id, NodeType::IMAGE_ANIMATION);
+ add_relation(image_animation_key, texture_key, "Datablock Image Animation");
+ }
}
void DepsgraphRelationBuilder::build_image(Image *image)
@@ -2878,6 +2892,9 @@ void DepsgraphRelationBuilder::build_driver_relations(IDNode *id_node)
DriverGroupMap driver_groups;
LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
+ if (fcu->rna_path == nullptr) {
+ continue;
+ }
// Get the RNA path except the part after the last dot.
char *last_dot = strrchr(fcu->rna_path, '.');
string rna_prefix;
@@ -2928,7 +2945,7 @@ void DepsgraphRelationBuilder::build_driver_relations(IDNode *id_node)
}
}
}
-}
+} // namespace DEG
/* **** ID traversal callbacks functions **** */
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc
index 2381076161f..91bd0117f6c 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc
@@ -172,6 +172,8 @@ const char *operationCodeAsString(OperationCode opcode)
return "SHADING";
case OperationCode::MATERIAL_UPDATE:
return "MATERIAL_UPDATE";
+ case OperationCode::LIGHT_UPDATE:
+ return "LIGHT_UPDATE";
case OperationCode::WORLD_UPDATE:
return "WORLD_UPDATE";
/* Movie clip. */
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h
index 865a25d2124..6b14e6af02f 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.h
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.h
@@ -170,6 +170,7 @@ enum class OperationCode {
/* Shading. ------------------------------------------------------------- */
SHADING,
MATERIAL_UPDATE,
+ LIGHT_UPDATE,
WORLD_UPDATE,
/* Batch caches. -------------------------------------------------------- */
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 0214a8e1887..a26c150cb51 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -34,6 +34,7 @@ set(INC
../imbuf
../makesdna
../makesrna
+ ../nodes
../render/extern/include
../render/intern/include
../windowmanager
@@ -303,8 +304,8 @@ data_to_c_simple(engines/select/shaders/selection_id_3D_vert.glsl SRC)
data_to_c_simple(engines/select/shaders/selection_id_frag.glsl SRC)
data_to_c_simple(engines/basic/shaders/conservative_depth_geom.glsl SRC)
-data_to_c_simple(engines/basic/shaders/conservative_depth_vert.glsl SRC)
-data_to_c_simple(engines/basic/shaders/conservative_depth_frag.glsl SRC)
+data_to_c_simple(engines/basic/shaders/depth_vert.glsl SRC)
+data_to_c_simple(engines/basic/shaders/depth_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/antialiasing_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/antialiasing_vert.glsl SRC)
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index 6658fea7825..bbc3c407f14 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -37,8 +37,8 @@
#define BASIC_ENGINE "BLENDER_BASIC"
-extern char datatoc_conservative_depth_frag_glsl[];
-extern char datatoc_conservative_depth_vert_glsl[];
+extern char datatoc_depth_frag_glsl[];
+extern char datatoc_depth_vert_glsl[];
extern char datatoc_conservative_depth_geom_glsl[];
extern char datatoc_common_view_lib_glsl[];
@@ -91,22 +91,28 @@ static void basic_engine_init(void *UNUSED(vedata))
/* Depth prepass */
if (!sh_data->depth) {
- sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg);
-
const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+
+ sh_data->depth = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_depth_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, NULL},
+ });
+
sh_data->depth_conservative = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg->lib,
datatoc_common_view_lib_glsl,
- datatoc_conservative_depth_vert_glsl,
+ datatoc_depth_vert_glsl,
NULL},
.geom = (const char *[]){sh_cfg->lib,
datatoc_common_view_lib_glsl,
datatoc_conservative_depth_geom_glsl,
NULL},
- .frag = (const char *[]){datatoc_common_view_lib_glsl,
- datatoc_conservative_depth_frag_glsl,
- NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, "#define CONSERVATIVE_RASTER\n", NULL},
});
}
}
@@ -233,6 +239,7 @@ static void basic_engine_free(void)
{
for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) {
BASIC_Shaders *sh_data = &e_data.sh_data[i];
+ DRW_SHADER_FREE_SAFE(sh_data->depth);
DRW_SHADER_FREE_SAFE(sh_data->depth_conservative);
}
}
diff --git a/source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl b/source/blender/draw/engines/basic/shaders/depth_frag.glsl
index ff4a015c335..ff4a015c335 100644
--- a/source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl
+++ b/source/blender/draw/engines/basic/shaders/depth_frag.glsl
diff --git a/source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl b/source/blender/draw/engines/basic/shaders/depth_vert.glsl
index c55a3211ff2..318d0acef6f 100644
--- a/source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl
+++ b/source/blender/draw/engines/basic/shaders/depth_vert.glsl
@@ -1,12 +1,16 @@
+#ifdef CONSERVATIVE_RASTER
RESOURCE_ID_VARYING
+#endif
in vec3 pos;
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
+#ifdef CONSERVATIVE_RASTER
PASS_RESOURCE_ID
+#endif
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 6874947de55..a19af77124f 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -24,6 +24,8 @@
#include "DRW_render.h"
+#include "BLI_memblock.h"
+
#include "eevee_lightcache.h"
#include "eevee_private.h"
@@ -54,8 +56,17 @@ void EEVEE_view_layer_data_free(void *storage)
DRW_UBO_FREE_SAFE(sldata->grid_ubo);
DRW_UBO_FREE_SAFE(sldata->planar_ubo);
DRW_UBO_FREE_SAFE(sldata->common_ubo);
- for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) {
- DRW_UBO_FREE_SAFE(sldata->renderpass_ubo[i]);
+
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.combined);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.diff_color);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.diff_light);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.spec_color);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.spec_light);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.emit);
+
+ if (sldata->material_cache) {
+ BLI_memblock_destroy(sldata->material_cache, NULL);
+ sldata->material_cache = NULL;
}
}
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 ec6770e4549..4a3cc36ddef 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -31,6 +31,8 @@
#include "BKE_camera.h"
+#include "BLI_string_utils.h"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -48,24 +50,28 @@ static struct {
extern char datatoc_effect_dof_vert_glsl[];
extern char datatoc_effect_dof_frag_glsl[];
+extern char datatoc_common_view_lib_glsl[];
+
static void eevee_create_shader_depth_of_field(const bool use_alpha)
{
+ char *frag = BLI_string_joinN(datatoc_common_view_lib_glsl, datatoc_effect_dof_frag_glsl);
e_data.dof_downsample_sh[use_alpha] = DRW_shader_create_fullscreen(
- datatoc_effect_dof_frag_glsl,
+ frag,
use_alpha ? "#define USE_ALPHA_DOF\n"
"#define STEP_DOWNSAMPLE\n" :
"#define STEP_DOWNSAMPLE\n");
e_data.dof_scatter_sh[use_alpha] = DRW_shader_create(datatoc_effect_dof_vert_glsl,
NULL,
- datatoc_effect_dof_frag_glsl,
+ frag,
use_alpha ? "#define USE_ALPHA_DOF\n"
"#define STEP_SCATTER\n" :
"#define STEP_SCATTER\n");
- e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen(datatoc_effect_dof_frag_glsl,
+ e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen(frag,
use_alpha ?
"#define USE_ALPHA_DOF\n"
"#define STEP_RESOLVE\n" :
"#define STEP_RESOLVE\n");
+ MEM_freeN(frag);
}
int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 05b18da4374..ab846fe0f11 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -333,8 +333,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
grp = DRW_shgroup_create(EEVEE_shaders_velocity_resolve_sh_get(), psl->velocity_resolve);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_mat4(grp, "currPersinv", effects->velocity_curr_persinv);
DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat);
DRW_shgroup_call(grp, quad, NULL);
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index a1112eb92df..b698574f9d7 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -88,7 +88,7 @@ static void eevee_engine_init(void *ved)
* `EEVEE_effects_init` needs to go second for TAA. */
EEVEE_renderpasses_init(vedata);
EEVEE_effects_init(sldata, vedata, camera, false);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
}
@@ -230,7 +230,7 @@ static void eevee_draw_scene(void *vedata)
BLI_halton_3d(primes, offset, samp, r);
EEVEE_update_noise(psl, fbl, r);
EEVEE_volumes_set_jitter(sldata, samp - 1);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
}
/* Copy previous persmat to UBO data */
copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat);
@@ -274,8 +274,7 @@ static void eevee_draw_scene(void *vedata)
/* Depth prepass */
DRW_stats_group_start("Prepass");
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
DRW_stats_group_end();
/* Create minmax texture */
@@ -289,9 +288,9 @@ static void eevee_draw_scene(void *vedata)
/* Shading pass */
DRW_stats_group_start("Shading");
if (DRW_state_draw_background()) {
- DRW_draw_pass(psl->background_pass);
+ DRW_draw_pass(psl->background_ps);
}
- EEVEE_materials_draw_opaque(sldata, psl);
+ DRW_draw_pass(psl->material_ps);
EEVEE_subsurface_data_render(sldata, vedata);
DRW_stats_group_end();
@@ -306,9 +305,8 @@ static void eevee_draw_scene(void *vedata)
/* Opaque refraction */
DRW_stats_group_start("Opaque Refraction");
- DRW_draw_pass(psl->refract_depth_pass);
- DRW_draw_pass(psl->refract_depth_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->depth_refract_ps);
+ DRW_draw_pass(psl->material_refract_ps);
DRW_stats_group_end();
/* Volumetrics Resolve Opaque */
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 614c749b9aa..4cdd166f09c 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -379,9 +379,7 @@ static bool eevee_lightcache_static_load(LightCache *lcache)
0,
false,
NULL);
- GPU_texture_bind(lcache->grid_tx.tex, 0);
GPU_texture_filter_mode(lcache->grid_tx.tex, true);
- GPU_texture_unbind(lcache->grid_tx.tex);
}
if (lcache->cube_tx.tex == NULL) {
@@ -406,13 +404,11 @@ static bool eevee_lightcache_static_load(LightCache *lcache)
NULL);
}
- GPU_texture_bind(lcache->cube_tx.tex, 0);
- GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true);
for (int mip = 0; mip < lcache->mips_len; mip++) {
GPU_texture_add_mipmap(
lcache->cube_tx.tex, GPU_DATA_10_11_11_REV, mip + 1, lcache->cube_mips[mip].data);
}
- GPU_texture_unbind(lcache->cube_tx.tex);
+ GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true);
}
return true;
}
@@ -822,7 +818,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
DRW_render_viewport_size_set(viewport_size);
EEVEE_effects_init(sldata, vedata, NULL, true);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 9816632c0c3..83b2a9bb6d4 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -248,8 +248,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_instances(grp, NULL, geom, 6);
@@ -271,8 +270,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call(grp, geom, NULL);
@@ -293,8 +291,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
DRW_shgroup_uniform_texture(grp, "probeDepth", rt_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call(grp, geom, NULL);
@@ -337,51 +334,29 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
Scene *scene = draw_ctx->scene;
World *wo = scene->world;
- const float *col = G_draw.block.colorBackground;
-
/* LookDev */
EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->probe_background, wo, pinfo);
- /* END */
+
if (!grp && wo) {
- col = &wo->horr;
-
- if (wo->use_nodes && wo->nodetree) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float queue_col[3] = {0.5f, 0.5f, 0.5f};
- struct GPUMaterial *gpumat = EEVEE_material_world_lightprobe_get(scene, wo);
-
- eGPUMaterialStatus status = GPU_material_status(gpumat);
-
- switch (status) {
- case GPU_MAT_SUCCESS:
- grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
- DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
- /* TODO (fclem): remove those (need to clean the GLSL files). */
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_call(grp, geom, NULL);
- break;
- case GPU_MAT_QUEUED:
- stl->g_data->queued_shaders_count++;
- col = queue_col;
- break;
- default:
- col = error_col;
- break;
- }
- }
+ struct GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_PROBE);
+
+ grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
+ DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
+ /* TODO (fclem): remove those (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_call(grp, geom, NULL);
}
/* Fallback if shader fails or if not using nodetree. */
if (grp == NULL) {
grp = DRW_shgroup_create(EEVEE_shaders_probe_default_sh_get(), psl->probe_background);
- DRW_shgroup_uniform_vec3(grp, "color", col, 1);
+ DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1);
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
DRW_shgroup_call(grp, geom, NULL);
}
@@ -402,14 +377,13 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_uniform_texture_ref(grp, "probeCubes", &lcache->cube_tx.tex);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
+ DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2);
DRW_shgroup_uniform_float_copy(
grp, "sphere_size", scene_eval->eevee.gi_cubemap_draw_size * 0.5f);
/* TODO (fclem) get rid of those UBO. */
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, cube_len * 2);
}
@@ -427,7 +401,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_uniform_vec3(shgrp, "increment_x", egrid->increment_x, 1);
DRW_shgroup_uniform_vec3(shgrp, "increment_y", egrid->increment_y, 1);
DRW_shgroup_uniform_vec3(shgrp, "increment_z", egrid->increment_z, 1);
- DRW_shgroup_uniform_vec3(shgrp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
+ DRW_shgroup_uniform_vec3(shgrp, "screen_vecs", DRW_viewport_screenvecs_get(), 2);
DRW_shgroup_uniform_texture_ref(shgrp, "irradianceGrid", &lcache->grid_tx.tex);
DRW_shgroup_uniform_float_copy(
shgrp, "sphere_size", scene_eval->eevee.gi_irradiance_draw_size * 0.5f);
@@ -436,8 +410,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(shgrp, "renderpass_block", sldata->renderpass_ubo.combined);
int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2;
DRW_shgroup_call_procedural_triangles(shgrp, NULL, tri_count);
}
@@ -455,8 +428,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_display_sh_get(),
psl->probe_display);
DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
stl->g_data->planar_display_shgrp = DRW_shgroup_call_buffer_instance(
grp, e_data.format_probe_display_planar, DRW_cache_quad_get());
@@ -923,12 +895,10 @@ static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_dat
GPU_framebuffer_bind(face_fb[face]);
GPU_framebuffer_clear_depth(face_fb[face], 1.0f);
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
DRW_draw_pass(psl->probe_background);
- EEVEE_materials_draw_opaque(sldata, psl);
- DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
- DRW_draw_pass(psl->sss_pass_cull);
+ DRW_draw_pass(psl->material_ps);
+ DRW_draw_pass(psl->material_sss_ps); /* Only output standard pass */
DRW_draw_pass(psl->transparent_pass);
}
@@ -987,10 +957,8 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
/* Slight modification: we handle refraction as normal
* shading and don't do SSRefraction. */
- DRW_draw_pass(psl->depth_pass_clip);
- DRW_draw_pass(psl->depth_pass_clip_cull);
- DRW_draw_pass(psl->refract_depth_pass_clip);
- DRW_draw_pass(psl->refract_depth_pass_clip_cull);
+ DRW_draw_pass(psl->depth_ps);
+ DRW_draw_pass(psl->depth_refract_ps);
DRW_draw_pass(psl->probe_background);
EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer);
@@ -999,10 +967,9 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
GPU_framebuffer_bind(fbl->planarref_fb);
/* Shading pass */
- EEVEE_materials_draw_opaque(sldata, psl);
- DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
- DRW_draw_pass(psl->sss_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->material_ps);
+ DRW_draw_pass(psl->material_sss_ps); /* Only output standard pass */
+ DRW_draw_pass(psl->material_refract_ps);
/* Transparent */
if (DRW_state_is_image_render()) {
diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c
index b33be750d80..18365d69514 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -34,6 +34,8 @@
#include "ED_screen.h"
+#include "GPU_material.h"
+
#include "UI_resources.h"
#include "eevee_lightcache.h"
@@ -56,6 +58,43 @@ static void eevee_lookdev_lightcache_delete(EEVEE_Data *vedata)
g_data->studiolight_rot_z = 0.0f;
}
+static void eevee_lookdev_hdri_preview_init(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ DRWShadingGroup *grp;
+
+ struct GPUBatch *sphere = DRW_cache_sphere_get();
+ int mat_options = VAR_MAT_MESH | VAR_MAT_LOOKDEV;
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
+ DRW_STATE_CULL_BACK;
+
+ {
+ Material *ma = EEVEE_material_default_diffuse_get();
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state);
+ grp = DRW_shgroup_create(sh, psl->lookdev_diffuse_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
+ DRW_shgroup_add_material_resources(grp, gpumat);
+ DRW_shgroup_call(grp, sphere, NULL);
+ }
+ {
+ Material *ma = EEVEE_material_default_glossy_get();
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRW_PASS_CREATE(psl->lookdev_glossy_pass, state);
+ grp = DRW_shgroup_create(sh, psl->lookdev_glossy_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
+ DRW_shgroup_add_material_resources(grp, gpumat);
+ DRW_shgroup_call(grp, sphere, NULL);
+ }
+}
+
void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
DRWShadingGroup **r_grp,
@@ -106,6 +145,8 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
effects->anchor[1] = rect->ymin;
EEVEE_temporal_sampling_reset(vedata);
}
+
+ eevee_lookdev_hdri_preview_init(vedata, sldata);
}
if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) {
@@ -176,8 +217,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
}
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
diff --git a/source/blender/draw/engines/eevee/eevee_lut_gen.c b/source/blender/draw/engines/eevee/eevee_lut_gen.c
new file mode 100644
index 00000000000..5f20d6fbfb8
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_lut_gen.c
@@ -0,0 +1,198 @@
+/*
+ * 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 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ *
+ * EEVEE LUT generation:
+ *
+ * Routine to generate the LUT used by eevee stored in eevee_lut.h
+ * Theses functions are not to be used in the final executable.
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_alloca.h"
+#include "BLI_rand.h"
+#include "BLI_string_utils.h"
+
+extern char datatoc_bsdf_lut_frag_glsl[];
+extern char datatoc_btdf_lut_frag_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_bsdf_sampling_lib_glsl[];
+extern char datatoc_lightprobe_geom_glsl[];
+extern char datatoc_lightprobe_vert_glsl[];
+
+static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
+{
+ struct GPUTexture *tex;
+ struct GPUFrameBuffer *fb = NULL;
+ static float samples_len = 8192.0f;
+ static float inv_samples_len = 1.0f / 8192.0f;
+
+ char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl);
+
+ struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl,
+ datatoc_lightprobe_geom_glsl,
+ datatoc_bsdf_lut_frag_glsl,
+ lib_str,
+ "#define HAMMERSLEY_SIZE 8192\n"
+ "#define BRDF_LUT_SIZE 64\n"
+ "#define NOISE_SIZE 64\n");
+
+ DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
+ DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
+
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call(grp, geom, NULL);
+
+ float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
+
+ tex = DRW_texture_create_2d(w, h, GPU_RG16F, DRW_TEX_FILTER, (float *)texels);
+
+ DRWFboTexture tex_filter = {&tex, GPU_RG16F, DRW_TEX_FILTER};
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+
+ GPU_framebuffer_bind(fb);
+ DRW_draw_pass(pass);
+
+ float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data);
+
+ printf("{");
+ for (int i = 0; i < w * h * 3; i += 3) {
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, \n", data[i], data[i + 1]);
+ }
+ printf("}");
+
+ MEM_freeN(texels);
+ MEM_freeN(data);
+
+ return tex;
+}
+
+static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
+{
+ struct GPUTexture *tex;
+ struct GPUTexture *hammersley = create_hammersley_sample_texture(8192);
+ struct GPUFrameBuffer *fb = NULL;
+ static float samples_len = 8192.0f;
+ static float a2 = 0.0f;
+ static float inv_samples_len = 1.0f / 8192.0f;
+
+ char *frag_str = BLI_string_joinN(
+ datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl);
+
+ struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str,
+ "#define HAMMERSLEY_SIZE 8192\n"
+ "#define BRDF_LUT_SIZE 64\n"
+ "#define NOISE_SIZE 64\n"
+ "#define LUT_SIZE 64\n");
+
+ MEM_freeN(frag_str);
+
+ DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_float(grp, "a2", &a2, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley);
+ DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
+
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call(grp, geom, NULL);
+
+ float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
+
+ tex = DRW_texture_create_2d(w, h, GPU_R16F, DRW_TEX_FILTER, (float *)texels);
+
+ DRWFboTexture tex_filter = {&tex, GPU_R16F, DRW_TEX_FILTER};
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+
+ GPU_framebuffer_bind(fb);
+
+ float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
+
+ float inc = 1.0f / 31.0f;
+ float roughness = 1e-8f - inc;
+ FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w");
+ fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n");
+ do {
+ roughness += inc;
+ CLAMP(roughness, 1e-4f, 1.0f);
+ a2 = powf(roughness, 4.0f);
+ DRW_draw_pass(pass);
+
+ GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data);
+
+#if 1
+ fprintf(f, "\t{\n\t\t");
+ for (int i = 0; i < w * h * 3; i += 3) {
+ fprintf(f, "%ff,", data[i]);
+ if (((i / 3) + 1) % 12 == 0) {
+ fprintf(f, "\n\t\t");
+ }
+ else {
+ fprintf(f, " ");
+ }
+ }
+ fprintf(f, "\n\t},\n");
+#else
+ for (int i = 0; i < w * h * 3; i += 3) {
+ if (data[i] < 0.01) {
+ printf(" ");
+ }
+ else if (data[i] < 0.3) {
+ printf(".");
+ }
+ else if (data[i] < 0.6) {
+ printf("+");
+ }
+ else if (data[i] < 0.9) {
+ printf("%%");
+ }
+ else {
+ printf("#");
+ }
+ if ((i / 3 + 1) % 64 == 0) {
+ printf("\n");
+ }
+ }
+#endif
+
+ } while (roughness < 1.0f);
+ fprintf(f, "\n};\n");
+
+ fclose(f);
+
+ MEM_freeN(texels);
+ MEM_freeN(data);
+
+ return tex;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 03cdb02a48a..cfc70baaf01 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -23,10 +23,10 @@
#include "DRW_render.h"
#include "BLI_alloca.h"
-#include "BLI_dynstr.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_math_bits.h"
+#include "BLI_memblock.h"
#include "BLI_rand.h"
#include "BLI_string_utils.h"
@@ -48,29 +48,11 @@
/* *********** STATIC *********** */
static struct {
- char *frag_shader_lib;
- char *vert_shader_str;
- char *vert_shadow_shader_str;
- char *vert_background_shader_str;
- char *vert_volume_shader_str;
- char *geom_volume_shader_str;
- char *volume_shader_lib;
-
- struct GPUShader *default_prepass_sh;
- struct GPUShader *default_prepass_clip_sh;
- struct GPUShader *default_hair_prepass_sh;
- struct GPUShader *default_hair_prepass_clip_sh;
- struct GPUShader *default_lit[VAR_MAT_MAX];
- struct GPUShader *default_background;
- struct GPUShader *update_noise_sh;
-
/* 64*64 array texture containing all LUTs and other utilitarian arrays.
* Packing enables us to same precious textures slots. */
struct GPUTexture *util_tex;
struct GPUTexture *noise_tex;
- uint sss_count;
-
float noise_offsets[3];
} e_data = {NULL}; /* Engine data */
@@ -82,8 +64,6 @@ extern char datatoc_prepass_vert_glsl[];
extern char datatoc_default_frag_glsl[];
extern char datatoc_default_world_frag_glsl[];
extern char datatoc_ltc_lib_glsl[];
-extern char datatoc_bsdf_lut_frag_glsl[];
-extern char datatoc_btdf_lut_frag_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
@@ -107,320 +87,45 @@ extern char datatoc_volumetric_frag_glsl[];
extern char datatoc_volumetric_lib_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
-#define DEFAULT_RENDER_PASS_FLAG 0xefffffff
-
-/* Iterator for render passes. This iteration will only do the material based render passes. it
- * will ignore `EEVEE_RENDER_PASS_ENVIRONMENT`.
- *
- * parameters:
- * - `render_passes_` is a bitflag for render_passes that needs to be iterated over.
- * - `render_pass_index_` is a parameter name where the index of the render_pass will be available
- * during iteration. This index can be used to select the right pass in the `psl`.
- * - `render_pass_` is the bitflag of the render_pass of the current iteration.
- *
- * The `render_pass_index_` parameter needs to be the same for the `RENDER_PASS_ITER_BEGIN` and
- * `RENDER_PASS_ITER_END`.
- */
-#define RENDER_PASS_ITER_BEGIN(render_passes_, render_pass_index_, render_pass_) \
- const eViewLayerEEVEEPassType __filtered_##render_pass_index_ = render_passes_ & \
- EEVEE_RENDERPASSES_MATERIAL & \
- ~EEVEE_RENDER_PASS_ENVIRONMENT; \
- if (__filtered_##render_pass_index_ != 0) { \
- int render_pass_index_ = 1; \
- for (int bit_##render_pass_ = 0; bit_##render_pass_ < EEVEE_RENDER_PASS_MAX_BIT; \
- bit_##render_pass_++) { \
- eViewLayerEEVEEPassType render_pass_ = (1 << bit_##render_pass_); \
- if ((__filtered_##render_pass_index_ & render_pass_) != 0) {
-#define RENDER_PASS_ITER_END(render_pass_index_) \
- render_pass_index_ += 1; \
- } \
- } \
- } \
- ((void)0)
+typedef struct EeveeMaterialCache {
+ struct DRWShadingGroup *depth_grp;
+ struct DRWShadingGroup *shading_grp;
+ struct DRWShadingGroup *shadow_grp;
+ struct GPUMaterial *shading_gpumat;
+ /* Meh, Used by hair to ensure draw order when calling DRW_shgroup_create_sub.
+ * Pointers to ghash values. */
+ struct DRWShadingGroup **depth_grp_p;
+ struct DRWShadingGroup **shading_grp_p;
+ struct DRWShadingGroup **shadow_grp_p;
+} EeveeMaterialCache;
/* *********** FUNCTIONS *********** */
-#if 0 /* Used only to generate the LUT values */
-static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
-{
- struct GPUTexture *tex;
- struct GPUFrameBuffer *fb = NULL;
- static float samples_len = 8192.0f;
- static float inv_samples_len = 1.0f / 8192.0f;
-
- char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl);
-
- struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl,
- datatoc_lightprobe_geom_glsl,
- datatoc_bsdf_lut_frag_glsl,
- lib_str,
- "#define HAMMERSLEY_SIZE 8192\n"
- "#define BRDF_LUT_SIZE 64\n"
- "#define NOISE_SIZE 64\n");
-
- DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
- DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
- DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
-
- struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call(grp, geom, NULL);
-
- float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
-
- tex = DRW_texture_create_2d(w, h, GPU_RG16F, DRW_TEX_FILTER, (float *)texels);
-
- DRWFboTexture tex_filter = {&tex, GPU_RG16F, DRW_TEX_FILTER};
- GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
-
- GPU_framebuffer_bind(fb);
- DRW_draw_pass(pass);
-
- float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data);
-
- printf("{");
- for (int i = 0; i < w * h * 3; i += 3) {
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, \n", data[i], data[i + 1]);
- }
- printf("}");
-
- MEM_freeN(texels);
- MEM_freeN(data);
-
- return tex;
-}
-
-static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
-{
- struct GPUTexture *tex;
- struct GPUTexture *hammersley = create_hammersley_sample_texture(8192);
- struct GPUFrameBuffer *fb = NULL;
- static float samples_len = 8192.0f;
- static float a2 = 0.0f;
- static float inv_samples_len = 1.0f / 8192.0f;
-
- char *frag_str = BLI_string_joinN(
- datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl);
-
- struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str,
- "#define HAMMERSLEY_SIZE 8192\n"
- "#define BRDF_LUT_SIZE 64\n"
- "#define NOISE_SIZE 64\n"
- "#define LUT_SIZE 64\n");
-
- MEM_freeN(frag_str);
-
- DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_float(grp, "a2", &a2, 1);
- DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
- DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley);
- DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
-
- struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call(grp, geom, NULL);
-
- float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
-
- tex = DRW_texture_create_2d(w, h, GPU_R16F, DRW_TEX_FILTER, (float *)texels);
-
- DRWFboTexture tex_filter = {&tex, GPU_R16F, DRW_TEX_FILTER};
- GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
-
- GPU_framebuffer_bind(fb);
-
- float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
-
- float inc = 1.0f / 31.0f;
- float roughness = 1e-8f - inc;
- FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w");
- fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n");
- do {
- roughness += inc;
- CLAMP(roughness, 1e-4f, 1.0f);
- a2 = powf(roughness, 4.0f);
- DRW_draw_pass(pass);
-
- GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data);
-
-# if 1
- fprintf(f, "\t{\n\t\t");
- for (int i = 0; i < w * h * 3; i += 3) {
- fprintf(f, "%ff,", data[i]);
- if (((i / 3) + 1) % 12 == 0) {
- fprintf(f, "\n\t\t");
- }
- else {
- fprintf(f, " ");
- }
- }
- fprintf(f, "\n\t},\n");
-# else
- for (int i = 0; i < w * h * 3; i += 3) {
- if (data[i] < 0.01) {
- printf(" ");
- }
- else if (data[i] < 0.3) {
- printf(".");
- }
- else if (data[i] < 0.6) {
- printf("+");
- }
- else if (data[i] < 0.9) {
- printf("%%");
- }
- else {
- printf("#");
- }
- if ((i / 3 + 1) % 64 == 0) {
- printf("\n");
- }
- }
-# endif
-
- } while (roughness < 1.0f);
- fprintf(f, "\n};\n");
-
- fclose(f);
-
- MEM_freeN(texels);
- MEM_freeN(data);
-
- return tex;
-}
-#endif
/* XXX TODO define all shared resources in a shared place without duplication */
struct GPUTexture *EEVEE_materials_get_util_tex(void)
{
return e_data.util_tex;
}
-static char *eevee_get_defines(int options)
-{
- char *str = NULL;
-
- DynStr *ds = BLI_dynstr_new();
- BLI_dynstr_append(ds, SHADER_DEFINES);
-
- if ((options & VAR_MAT_MESH) != 0) {
- BLI_dynstr_append(ds, "#define MESH_SHADER\n");
- }
- if ((options & VAR_MAT_HAIR) != 0) {
- BLI_dynstr_append(ds, "#define HAIR_SHADER\n");
- }
- if ((options & VAR_MAT_PROBE) != 0) {
- BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n");
- }
- if ((options & VAR_MAT_CLIP) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_CLIP\n");
- }
- if ((options & VAR_MAT_SHADOW) != 0) {
- BLI_dynstr_append(ds, "#define SHADOW_SHADER\n");
- }
- if ((options & VAR_MAT_HASH) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_HASH\n");
- }
- if ((options & VAR_MAT_BLEND) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND\n");
- }
- if ((options & VAR_MAT_MULT) != 0) {
- BLI_dynstr_append(ds, "#define USE_MULTIPLY\n");
- }
- if ((options & VAR_MAT_REFRACT) != 0) {
- BLI_dynstr_append(ds, "#define USE_REFRACTION\n");
- }
- if ((options & VAR_MAT_LOOKDEV) != 0) {
- BLI_dynstr_append(ds, "#define LOOKDEV\n");
- }
- if ((options & VAR_MAT_HOLDOUT) != 0) {
- BLI_dynstr_append(ds, "#define HOLDOUT\n");
- }
-
- str = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
-
- return str;
-}
-
-static char *eevee_get_volume_defines(int options)
-{
- char *str = NULL;
-
- DynStr *ds = BLI_dynstr_new();
- BLI_dynstr_append(ds, SHADER_DEFINES);
- BLI_dynstr_append(ds, "#define VOLUMETRICS\n");
-
- if ((options & VAR_MAT_VOLUME) != 0) {
- BLI_dynstr_append(ds, "#define MESH_SHADER\n");
- }
-
- str = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
-
- return str;
-}
-
-/* Get the default render pass ubo. This is a ubo that enables all bsdf render passes. */
-struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata)
-{
- return sldata->renderpass_ubo[0];
-}
-
-/* Get the render pass ubo for rendering the given render_pass. */
-static struct GPUUniformBuffer *get_render_pass_ubo(EEVEE_ViewLayerData *sldata,
- eViewLayerEEVEEPassType render_pass)
-{
- int index;
- switch (render_pass) {
- case EEVEE_RENDER_PASS_DIFFUSE_COLOR:
- index = 1;
- break;
- case EEVEE_RENDER_PASS_DIFFUSE_LIGHT:
- index = 2;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_COLOR:
- index = 3;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_LIGHT:
- index = 4;
- break;
- case EEVEE_RENDER_PASS_EMIT:
- index = 5;
- break;
- default:
- index = 0;
- break;
- }
- return sldata->renderpass_ubo[index];
-}
/**
* ssr_id can be null to disable ssr contribution.
*/
-static void add_standard_uniforms(DRWShadingGroup *shgrp,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- int *ssr_id,
- float *refract_depth,
- bool use_diffuse,
- bool use_glossy,
- bool use_refract,
- bool use_ssrefraction,
- bool use_alpha_blend,
- eViewLayerEEVEEPassType render_pass)
+void EEVEE_material_bind_resources(DRWShadingGroup *shgrp,
+ GPUMaterial *gpumat,
+ EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ int *ssr_id,
+ float *refract_depth,
+ bool use_ssrefraction,
+ bool use_alpha_blend)
{
+ bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE);
+ bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY);
+ bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT);
+
LightCache *lcache = vedata->stl->g_data->light_cache;
EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
@@ -428,11 +133,11 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(shgrp, "renderpass_block", get_render_pass_ubo(sldata, render_pass));
+ DRW_shgroup_uniform_block_ref(shgrp, "renderpass_block", &pd->renderpass_ubo);
DRW_shgroup_uniform_int_copy(shgrp, "outputSssId", 1);
+ DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
if (use_diffuse || use_glossy || use_refract) {
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
DRW_shgroup_uniform_texture_ref(shgrp, "shadowCubeTexture", &sldata->shadow_cube_pool);
DRW_shgroup_uniform_texture_ref(shgrp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
DRW_shgroup_uniform_texture_ref(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
@@ -463,36 +168,6 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
}
}
-/* Add the uniforms for the background shader to `shgrp`. */
-static void add_background_uniforms(DRWShadingGroup *shgrp,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata)
-{
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- DRW_shgroup_uniform_float(shgrp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
- /* TODO (fclem): remove those (need to clean the GLSL files). */
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
-}
-
-static void create_default_shader(int options)
-{
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_default_frag_glsl);
-
- char *defines = eevee_get_defines(options);
-
- e_data.default_lit[options] = DRW_shader_create(e_data.vert_shader_str, NULL, frag_str, defines);
-
- MEM_freeN(defines);
- MEM_freeN(frag_str);
-}
-
static void eevee_init_noise_texture(void)
{
e_data.noise_tex = DRW_texture_create_2d(64, 64, GPU_RGBA16F, 0, (float *)blue_noise);
@@ -559,8 +234,6 @@ void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const d
e_data.noise_offsets[1] = offsets[1];
e_data.noise_offsets[2] = offsets[2];
- /* Attach & detach because we don't currently support multiple FB per texture,
- * and this would be the case for multiple viewport. */
GPU_framebuffer_bind(fbl->update_noise_fb);
DRW_draw_pass(psl->update_noise_pass);
}
@@ -606,94 +279,15 @@ void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_vi
}
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
EEVEE_StorageList *stl,
EEVEE_FramebufferList *fbl)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
EEVEE_PrivateData *g_data = stl->g_data;
- if (!e_data.frag_shader_lib) {
- /* Shaders */
- e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_common_uniforms_lib_glsl,
- datatoc_bsdf_common_lib_glsl,
- datatoc_bsdf_sampling_lib_glsl,
- datatoc_ambient_occlusion_lib_glsl,
- datatoc_raytrace_lib_glsl,
- datatoc_ssr_lib_glsl,
- datatoc_octahedron_lib_glsl,
- datatoc_cubemap_lib_glsl,
- datatoc_irradiance_lib_glsl,
- datatoc_lightprobe_lib_glsl,
- datatoc_ltc_lib_glsl,
- datatoc_lights_lib_glsl,
- /* Add one for each Closure */
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_volumetric_lib_glsl);
-
- e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_common_uniforms_lib_glsl,
- datatoc_bsdf_common_lib_glsl,
- datatoc_ambient_occlusion_lib_glsl,
- datatoc_octahedron_lib_glsl,
- datatoc_cubemap_lib_glsl,
- datatoc_irradiance_lib_glsl,
- datatoc_lightprobe_lib_glsl,
- datatoc_ltc_lib_glsl,
- datatoc_lights_lib_glsl,
- datatoc_volumetric_lib_glsl,
- datatoc_volumetric_frag_glsl);
-
- e_data.vert_shader_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl);
-
- e_data.vert_shadow_shader_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl);
-
- e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_background_vert_glsl);
-
- e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_volumetric_vert_glsl);
-
- e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_volumetric_geom_glsl);
-
- e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
- NULL,
- datatoc_default_world_frag_glsl,
- datatoc_common_view_lib_glsl,
- NULL);
-
- char *vert_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_prepass_vert_glsl);
-
- e_data.default_prepass_sh = DRW_shader_create(vert_str, NULL, datatoc_prepass_frag_glsl, NULL);
-
- e_data.default_prepass_clip_sh = DRW_shader_create(
- vert_str, NULL, datatoc_prepass_frag_glsl, "#define CLIP_PLANES\n");
-
- e_data.default_hair_prepass_sh = DRW_shader_create(
- vert_str, NULL, datatoc_prepass_frag_glsl, "#define HAIR_SHADER\n");
-
- e_data.default_hair_prepass_clip_sh = DRW_shader_create(vert_str,
- NULL,
- datatoc_prepass_frag_glsl,
- "#define HAIR_SHADER\n"
- "#define CLIP_PLANES\n");
- MEM_freeN(vert_str);
-
- e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL);
+ if (!e_data.util_tex) {
+ EEVEE_shaders_material_shaders_init();
eevee_init_util_texture();
eevee_init_noise_texture();
@@ -728,33 +322,36 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
{
/* Create RenderPass UBO */
- if (sldata->renderpass_ubo[0] == NULL) {
- /* EEVEE_RENDER_PASS_COMBINED */
- sldata->renderpass_data[0] = (const EEVEE_RenderPassData){
- true, true, true, true, true, false};
- /* EEVEE_RENDER_PASS_DIFFUSE_COLOR */
- sldata->renderpass_data[1] = (const EEVEE_RenderPassData){
- true, false, false, false, false, true};
- /* EEVEE_RENDER_PASS_DIFFUSE_LIGHT */
- sldata->renderpass_data[2] = (const EEVEE_RenderPassData){
- true, true, false, false, false, false};
- /* EEVEE_RENDER_PASS_SPECULAR_COLOR */
- sldata->renderpass_data[3] = (const EEVEE_RenderPassData){
- false, false, true, false, false, false};
- /* EEVEE_RENDER_PASS_SPECULAR_LIGHT */
- sldata->renderpass_data[4] = (const EEVEE_RenderPassData){
- false, false, true, true, false, false};
- /* EEVEE_RENDER_PASS_EMIT */
- sldata->renderpass_data[5] = (const EEVEE_RenderPassData){
- false, false, false, false, true, false};
-
- for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) {
- sldata->renderpass_ubo[i] = DRW_uniformbuffer_create(sizeof(EEVEE_RenderPassData),
- &sldata->renderpass_data[i]);
- }
+ if (sldata->renderpass_ubo.combined == NULL) {
+ sldata->renderpass_ubo.combined = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, true, true, true, true, false});
+
+ sldata->renderpass_ubo.diff_color = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, false, false, false, false, true});
+
+ sldata->renderpass_ubo.diff_light = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, true, false, false, false, false});
+
+ sldata->renderpass_ubo.spec_color = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, true, false, false, false});
+
+ sldata->renderpass_ubo.spec_light = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, true, true, false, false});
+
+ sldata->renderpass_ubo.emit = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, false, false, true, false});
}
- /* HACK: EEVEE_material_world_background_get can create a new context. This can only be
+ /* Used combined pass by default. */
+ g_data->renderpass_ubo = sldata->renderpass_ubo.combined;
+
+ /* HACK: EEVEE_material_get can create a new context. This can only be
* done when there is no active framebuffer. We do this here otherwise
* `EEVEE_renderpasses_output_init` will fail. It cannot be done in
* `EEVEE_renderpasses_init` as the `e_data.vertcode` can be uninitialized.
@@ -763,414 +360,12 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
struct Scene *scene = draw_ctx->scene;
struct World *wo = scene->world;
if (wo && wo->use_nodes) {
- EEVEE_material_world_background_get(scene, wo);
+ EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND);
}
}
}
}
-struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- const int options = VAR_WORLD_PROBE;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, false);
- if (mat != NULL) {
- return mat;
- }
- return DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- false,
- e_data.vert_background_shader_str,
- NULL,
- e_data.frag_shader_lib,
- SHADER_DEFINES "#define PROBE_CAPTURE\n",
- false);
-}
-
-struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_WORLD_BACKGROUND;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
- return DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- false,
- e_data.vert_background_shader_str,
- NULL,
- e_data.frag_shader_lib,
- SHADER_DEFINES "#define WORLD_BACKGROUND\n",
- true);
-}
-
-struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_WORLD_VOLUME;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
-
- char *defines = eevee_get_volume_defines(options);
-
- mat = DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- true,
- e_data.vert_volume_shader_str,
- e_data.geom_volume_shader_str,
- e_data.volume_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene,
- Material *ma,
- EEVEE_Data *UNUSED(vedata),
- bool use_blend,
- bool use_refract)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
- SET_FLAG_FROM_TEST(options, use_refract, VAR_MAT_REFRACT);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- e_data.vert_shader_str,
- NULL,
- e_data.frag_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_VOLUME;
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
-
- char *defines = eevee_get_volume_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- true,
- e_data.vert_volume_shader_str,
- e_data.geom_volume_shader_str,
- e_data.volume_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH);
- SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP);
- SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- (is_shadow) ? e_data.vert_shadow_shader_str :
- e_data.vert_shader_str,
- NULL,
- frag_str,
- defines,
- true);
-
- MEM_freeN(frag_str);
- MEM_freeN(defines);
-
- return mat;
-}
-
-static struct GPUMaterial *EEVEE_material_hair_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH);
- SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP);
- SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- (is_shadow) ? e_data.vert_shadow_shader_str :
- e_data.vert_shader_str,
- NULL,
- frag_str,
- defines,
- false);
-
- MEM_freeN(frag_str);
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- e_data.vert_shader_str,
- NULL,
- e_data.frag_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-/**
- * Create a default shading group inside the given pass.
- */
-static struct DRWShadingGroup *EEVEE_default_shading_group_create(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- DRWPass *pass,
- bool is_hair,
- bool use_blend,
- bool use_ssr)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
- SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- use_blend,
- DEFAULT_RENDER_PASS_FLAG);
-
- return shgrp;
-}
-
-/**
- * Create a default shading group inside the default pass without standard uniforms.
- */
-static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- Object *ob,
- ParticleSystem *psys,
- ModifierData *md,
- bool is_hair,
- bool holdout,
- bool use_ssr)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- EEVEE_PassList *psl = vedata->psl;
-
- BLI_assert(!is_hair || (ob && ((psys && md) || ob->type == OB_HAIR)));
-
- SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- if (psl->default_pass[options] == NULL) {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->default_pass[options], state);
-
- /* XXX / WATCH: This creates non persistent binds for the ubos and textures.
- * But it's currently OK because the following shgroups does not add any bind.
- * EDIT: THIS IS NOT THE CASE FOR HAIRS !!! DUMMY!!! */
- if (!is_hair) {
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options],
- psl->default_pass[options]);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- }
- }
-
- if (is_hair) {
- DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
- ob, psys, md, vedata->psl->default_pass[options], e_data.default_lit[options]);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- return shgrp;
- }
- else {
- return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
- }
-}
-
-static struct DRWShadingGroup *EEVEE_default_render_pass_shading_group_get(
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- bool holdout,
- bool use_ssr,
- DRWPass *pass,
- eViewLayerEEVEEPassType render_pass_flag)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(
- shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag);
- return shgrp;
-}
-
-static struct DRWShadingGroup *EEVEE_default_hair_render_pass_shading_group_get(
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- Object *ob,
- ParticleSystem *psys,
- ModifierData *md,
- bool holdout,
- bool use_ssr,
- DRWPass *pass,
- eViewLayerEEVEEPassType render_pass_flag)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- BLI_assert((ob && psys && md));
-
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
- ob, psys, md, pass, e_data.default_lit[options]);
- add_standard_uniforms(
- shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag);
- return shgrp;
-}
-
void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
@@ -1180,10 +375,17 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Create Material Ghash */
{
stl->g_data->material_hash = BLI_ghash_ptr_new("Eevee_material ghash");
+
+ if (sldata->material_cache == NULL) {
+ sldata->material_cache = BLI_memblock_create(sizeof(EeveeMaterialCache));
+ }
+ else {
+ BLI_memblock_clear(sldata->material_cache, NULL);
+ }
}
{
- DRW_PASS_CREATE(psl->background_pass, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+ DRW_PASS_CREATE(psl->background_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = NULL;
@@ -1191,485 +393,297 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
Scene *scene = draw_ctx->scene;
World *wo = scene->world;
- const float *col = G_draw.block.colorBackground;
-
- EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_pass, wo, NULL);
+ EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_ps, wo, NULL);
if (!grp && wo) {
- col = &wo->horr;
-
- if (wo->use_nodes && wo->nodetree) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
- struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo);
-
- switch (GPU_material_status(gpumat)) {
- case GPU_MAT_SUCCESS:
- grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
- add_background_uniforms(grp, sldata, vedata);
- DRW_shgroup_call(grp, geom, NULL);
- break;
- case GPU_MAT_QUEUED:
- /* TODO Bypass probe compilation. */
- stl->g_data->queued_shaders_count++;
- col = compile_col;
- break;
- case GPU_MAT_FAILED:
- default:
- col = error_col;
- break;
- }
- }
+ struct GPUMaterial *gpumat = EEVEE_material_get(
+ vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND);
+
+ grp = DRW_shgroup_material_create(gpumat, psl->background_ps);
+ DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ /* TODO (fclem): remove those (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_call(grp, geom, NULL);
}
/* Fallback if shader fails or if not using nodetree. */
if (grp == NULL) {
- grp = DRW_shgroup_create(e_data.default_background, psl->background_pass);
- DRW_shgroup_uniform_vec3(grp, "color", col, 1);
+ GPUShader *sh = EEVEE_shaders_default_background_sh_get();
+ grp = DRW_shgroup_create(sh, psl->background_ps);
+ DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1);
DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
DRW_shgroup_call(grp, geom, NULL);
}
}
- {
- DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- DRW_PASS_CREATE(psl->depth_pass, state);
- stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh, psl->depth_pass);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->depth_pass_cull, state);
- stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->depth_pass_cull);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->depth_pass_clip, state);
- stl->g_data->depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->depth_pass_clip);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->depth_pass_clip_cull, state);
- stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->depth_pass_clip_cull);
- }
+#define EEVEE_PASS_CREATE(pass, state) \
+ do { \
+ DRW_PASS_CREATE(psl->pass##_ps, state); \
+ DRW_PASS_CREATE(psl->pass##_cull_ps, state | DRW_STATE_CULL_BACK); \
+ DRW_pass_link(psl->pass##_ps, psl->pass##_cull_ps); \
+ } while (0)
- {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->material_pass, state);
- DRW_PASS_CREATE(psl->material_pass_cull, state | DRW_STATE_CULL_BACK);
- }
+#define EEVEE_CLIP_PASS_CREATE(pass, state) \
+ do { \
+ DRWState st = state | DRW_STATE_CLIP_PLANES; \
+ DRW_PASS_INSTANCE_CREATE(psl->pass##_clip_ps, psl->pass##_ps, st); \
+ DRW_PASS_INSTANCE_CREATE( \
+ psl->pass##_clip_cull_ps, psl->pass##_cull_ps, st | DRW_STATE_CULL_BACK); \
+ DRW_pass_link(psl->pass##_clip_ps, psl->pass##_clip_cull_ps); \
+ } while (0)
{
- DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- DRW_PASS_CREATE(psl->refract_depth_pass, state);
- stl->g_data->refract_depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->refract_depth_pass);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->refract_depth_pass_cull, state);
- stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->refract_depth_pass_cull);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->refract_depth_pass_clip, state);
- stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->refract_depth_pass_clip);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->refract_depth_pass_clip_cull, state);
- stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create(
- e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull);
- }
+ DRWState state_depth = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+ DRWState state_shading = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
+ DRWState state_sss = DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
- {
- DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES);
- DRW_PASS_CREATE(psl->refract_pass, state);
- }
+ EEVEE_PASS_CREATE(depth, state_depth);
+ EEVEE_CLIP_PASS_CREATE(depth, state_depth);
- {
- DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS);
- DRW_PASS_CREATE(psl->sss_pass, state);
- DRW_PASS_CREATE(psl->sss_pass_cull, state | DRW_STATE_CULL_BACK);
- e_data.sss_count = 0;
+ EEVEE_PASS_CREATE(depth_refract, state_depth);
+ EEVEE_CLIP_PASS_CREATE(depth_refract, state_depth);
+
+ EEVEE_PASS_CREATE(material, state_shading);
+ EEVEE_PASS_CREATE(material_refract, state_shading);
+ EEVEE_PASS_CREATE(material_sss, state_shading | state_sss);
}
+ {
+ /* Renderpass accumulation. */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD_FULL;
+ /* Create an instance of each of theses passes and link them together. */
+ DRWPass *passes[] = {
+ psl->material_ps,
+ psl->material_cull_ps,
+ psl->material_sss_ps,
+ psl->material_sss_cull_ps,
+ };
+ DRWPass *first = NULL, *last = NULL;
+ for (int i = 0; i < ARRAY_SIZE(passes); i++) {
+ DRWPass *pass = DRW_pass_create_instance("Renderpass Accumulation", passes[i], state);
+ if (first == NULL) {
+ first = last = pass;
+ }
+ else {
+ DRW_pass_link(last, pass);
+ last = pass;
+ }
+ }
+ psl->material_accum_ps = first;
+ /* Same for background */
+ DRW_PASS_INSTANCE_CREATE(psl->background_accum_ps, psl->background_ps, state);
+ }
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
DRW_PASS_CREATE(psl->transparent_pass, state);
}
-
{
DRW_PASS_CREATE(psl->update_noise_pass, DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.update_noise_sh, psl->update_noise_pass);
+ GPUShader *sh = EEVEE_shaders_update_noise_sh_get();
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->update_noise_pass);
DRW_shgroup_uniform_texture(grp, "blueNoise", e_data.noise_tex);
DRW_shgroup_uniform_vec3(grp, "offsets", e_data.noise_offsets, 1);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
+}
- if (eevee_hdri_preview_overlay_enabled(draw_ctx->v3d)) {
- DRWShadingGroup *shgrp;
-
- struct GPUBatch *sphere = DRW_cache_sphere_get();
- static float color_chrome[3] = {1.0f, 1.0f, 1.0f};
- static float color_diffuse[3] = {0.8f, 0.8f, 0.8f};
- int options = VAR_MAT_MESH | VAR_MAT_LOOKDEV;
+BLI_INLINE void material_shadow(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma,
+ bool is_hair,
+ EeveeMaterialCache *emc)
+{
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_PassList *psl = vedata->psl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
+ if (ma->blend_shadow != MA_BS_NONE) {
+ /* Shadow Pass */
+ const bool use_shadow_shader = ma->use_nodes && ma->nodetree &&
+ ELEM(ma->blend_shadow, MA_BS_CLIP, MA_BS_HASHED);
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ SET_FLAG_FROM_TEST(mat_options, use_shadow_shader, VAR_MAT_HASH);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = (use_shadow_shader) ?
+ EEVEE_material_get(vedata, scene, ma, NULL, mat_options) :
+ EEVEE_material_default_get(scene, ma, mat_options);
+
+ /* Avoid possible confusion with depth pre-pass options. */
+ int option = KEY_SHADOW;
+ SET_FLAG_FROM_TEST(option, is_hair, KEY_HAIR);
+
+ /* Search for the same shaders usage in the pass. */
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
+ }
+ else {
+ *grp_p = grp = DRW_shgroup_create(sh, psl->shadow_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
}
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
- DRW_STATE_CULL_BACK;
-
- DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state);
- shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_diffuse_pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_diffuse, 1);
- DRW_shgroup_uniform_float_copy(shgrp, "metallic", 0.0f);
- DRW_shgroup_uniform_float_copy(shgrp, "specular", 0.5f);
- DRW_shgroup_uniform_float_copy(shgrp, "roughness", 1.0f);
- DRW_shgroup_call(shgrp, sphere, NULL);
-
- DRW_PASS_CREATE(psl->lookdev_glossy_pass, state);
- shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_glossy_pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_chrome, 1);
- DRW_shgroup_uniform_float_copy(shgrp, "metallic", 1.0f);
- DRW_shgroup_uniform_float_copy(shgrp, "roughness", 0.0f);
- DRW_shgroup_call(shgrp, sphere, NULL);
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- {
- memset(psl->material_accum_pass, 0, sizeof(psl->material_accum_pass));
- for (int pass_index = 0; pass_index < stl->g_data->render_passes_material_count;
- pass_index++) {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD_FULL;
- DRW_PASS_CREATE(psl->material_accum_pass[pass_index], state);
- }
+ emc->shadow_grp = grp;
+ emc->shadow_grp_p = grp_p;
+ }
+ else {
+ emc->shadow_grp = NULL;
+ emc->shadow_grp_p = NULL;
}
}
-#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \
- do { \
- if (oedata) { \
- DRW_shgroup_call_with_callback(shgrp, geom, ob, oedata); \
- } \
- else { \
- DRW_shgroup_call(shgrp, geom, ob); \
- } \
- } while (0)
-
-#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \
- do { \
- if (shgrp) { \
- ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \
- } \
- } while (0)
-
-typedef struct EeveeMaterialShadingGroups {
- struct DRWShadingGroup *shading_grp;
- struct DRWShadingGroup *depth_grp;
- struct DRWShadingGroup *depth_clip_grp;
- struct DRWShadingGroup *material_accum_grp[MAX_MATERIAL_RENDER_PASSES];
-} EeveeMaterialShadingGroups;
-
-static void material_opaque(Material *ma,
- GHash *material_hash,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- struct GPUMaterial **gpumat,
- struct GPUMaterial **gpumat_depth,
- struct EeveeMaterialShadingGroups *shgrps,
- bool holdout)
+static EeveeMaterialCache material_opaque(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma,
+ const bool is_hair)
{
EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_PassList *psl = vedata->psl;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
- bool use_diffuse, use_glossy, use_refract;
- bool store_material = true;
- float *color_p = &ma->r;
- float *metal_p = &ma->metallic;
- float *spec_p = &ma->spec;
- float *rough_p = &ma->roughness;
- const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
- const bool use_gpumat = (ma->use_nodes && ma->nodetree && !holdout);
+ const bool do_cull = !is_hair && (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
+ const bool use_gpumat = (ma->use_nodes && ma->nodetree);
const bool use_ssrefract = use_gpumat && ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
((effects->enabled_effects & EFFECT_REFRACT) != 0);
- const bool use_translucency = ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0);
+ const bool use_depth_shader = use_gpumat && ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED);
- EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma);
-
- if (emsg) {
- memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups));
-
- /* This will have been created already, just perform a lookup. */
- *gpumat = (use_gpumat) ? EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract) :
- NULL;
- *gpumat_depth = (use_gpumat) ? EEVEE_material_mesh_depth_get(
- scene, ma, (ma->blend_method == MA_BM_HASHED), false) :
- NULL;
- return;
+ /* HACK: Assume the struct will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparisons/hashing. */
+ void *key = (char *)ma + is_hair;
+ /* Search for other material instances (sharing the same Material data-block). */
+ EeveeMaterialCache **emc_p, *emc;
+ if (BLI_ghash_ensure_p(pd->material_hash, key, (void ***)&emc_p)) {
+ return **emc_p;
+ }
+ else {
+ *emc_p = emc = BLI_memblock_alloc(sldata->material_cache);
}
- emsg = MEM_callocN(sizeof(EeveeMaterialShadingGroups), "EeveeMaterialShadingGroups");
- if (use_gpumat) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
- static float half = 0.5f;
-
- /* Shading */
- *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract);
-
- eGPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat);
-
- /* Alpha CLipped : Discard pixel from depth pass, then
- * fail the depth test for shading. */
- if (ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED)) {
- *gpumat_depth = EEVEE_material_mesh_depth_get(
- scene, ma, (ma->blend_method == MA_BM_HASHED), false);
+ material_shadow(vedata, sldata, ma, is_hair, emc);
- eGPUMaterialStatus status_mat_depth = GPU_material_status(*gpumat_depth);
- if (status_mat_depth != GPU_MAT_SUCCESS) {
- /* Mixing both flags. If depth shader fails, show it to the user by not using
- * the surface shader. */
- status_mat_surface = status_mat_depth;
- }
- else if (use_ssrefract) {
- emsg->depth_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass);
- emsg->depth_clip_grp = DRW_shgroup_material_create(
- *gpumat_depth,
- (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip);
- }
- else {
- emsg->depth_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass);
- emsg->depth_clip_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip);
- }
-
- if (emsg->depth_grp != NULL) {
- use_diffuse = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_DIFFUSE);
- use_glossy = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_GLOSSY);
- use_refract = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_REFRACT);
-
- add_standard_uniforms(emsg->depth_grp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- add_standard_uniforms(emsg->depth_clip_grp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- if (ma->blend_method == MA_BM_CLIP) {
- DRW_shgroup_uniform_float(emsg->depth_grp, "alphaThreshold", &ma->alpha_threshold, 1);
- DRW_shgroup_uniform_float(
- emsg->depth_clip_grp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- }
+ {
+ /* Depth Pass */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ SET_FLAG_FROM_TEST(mat_options, use_depth_shader, VAR_MAT_HASH);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = (use_depth_shader) ?
+ EEVEE_material_get(vedata, scene, ma, NULL, mat_options) :
+ EEVEE_material_default_get(scene, ma, mat_options);
+
+ int option = 0;
+ SET_FLAG_FROM_TEST(option, do_cull, KEY_CULL);
+ SET_FLAG_FROM_TEST(option, use_ssrefract, KEY_REFRACT);
+ DRWPass *depth_ps = (DRWPass *[]){
+ psl->depth_ps,
+ psl->depth_cull_ps,
+ psl->depth_refract_ps,
+ psl->depth_refract_cull_ps,
+ }[option];
+ /* Hair are rendered inside the non-cull pass but needs to have a separate cache key. */
+ SET_FLAG_FROM_TEST(option, is_hair, KEY_HAIR);
+
+ /* Search for the same shaders usage in the pass. */
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
}
-
- switch (status_mat_surface) {
- case GPU_MAT_SUCCESS: {
- static int no_ssr = 0;
- static int first_ssr = 1;
- int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ?
- &first_ssr :
- &no_ssr;
- const bool use_sss = GPU_material_flag_get(*gpumat, GPU_MATFLAG_SSS);
- use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE);
- use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY);
- use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT);
-
- emsg->shading_grp = DRW_shgroup_material_create(
- *gpumat,
- (use_ssrefract) ?
- psl->refract_pass :
- (use_sss) ? ((do_cull) ? psl->sss_pass_cull : psl->sss_pass) :
- ((do_cull) ? psl->material_pass_cull : psl->material_pass));
-
- add_standard_uniforms(emsg->shading_grp,
- sldata,
- vedata,
- ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- if (use_sss) {
- struct GPUTexture *sss_tex_profile = NULL;
- struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(
- *gpumat, stl->effects->sss_sample_count, &sss_tex_profile);
-
- if (sss_profile) {
- /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
- if (e_data.sss_count < 254) {
- int sss_id = e_data.sss_count + 1;
- DRW_shgroup_stencil_mask(emsg->shading_grp, sss_id);
- EEVEE_subsurface_add_pass(sldata, vedata, sss_id, sss_profile);
- if (use_translucency) {
- EEVEE_subsurface_translucency_add_pass(
- sldata, vedata, sss_id, sss_profile, sss_tex_profile);
- }
- e_data.sss_count++;
- }
- else {
- /* TODO : display message. */
- printf("Error: Too many different Subsurface shader in the scene.\n");
- }
- }
- }
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- emsg->material_accum_grp[render_pass_index] = DRW_shgroup_material_create(
- *gpumat, psl->material_accum_pass[render_pass_index]);
- add_standard_uniforms(emsg->material_accum_grp[render_pass_index],
- sldata,
- vedata,
- ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- false,
- render_pass_flag);
- }
- RENDER_PASS_ITER_END(render_pass_index);
-
- break;
- }
- case GPU_MAT_QUEUED: {
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- store_material = false;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
+ else {
+ *grp_p = grp = DRW_shgroup_create(sh, depth_ps);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
}
- }
- /* Fallback to default shader */
- if (emsg->shading_grp == NULL) {
- bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0);
- emsg->shading_grp = EEVEE_default_shading_group_get(
- sldata, vedata, NULL, NULL, NULL, false, holdout, use_ssr);
- DRW_shgroup_uniform_vec3(emsg->shading_grp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "roughness", rough_p, 1);
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- DRWShadingGroup *shgrp = EEVEE_default_render_pass_shading_group_get(
- sldata,
- vedata,
- holdout,
- use_ssr,
- psl->material_accum_pass[render_pass_index],
- render_pass_flag);
-
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1);
- emsg->material_accum_grp[render_pass_index] = shgrp;
- }
- RENDER_PASS_ITER_END(render_pass_index);
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- /* Fallback default depth prepass */
- if (emsg->depth_grp == NULL) {
- if (use_ssrefract) {
- emsg->depth_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_cull :
- stl->g_data->refract_depth_shgrp;
- emsg->depth_clip_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_clip_cull :
- stl->g_data->refract_depth_shgrp_clip;
+ emc->depth_grp = grp;
+ emc->depth_grp_p = grp_p;
+ }
+ {
+ /* Shading Pass */
+ int mat_options = VAR_MAT_MESH;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ const bool use_sss = GPU_material_flag_get(gpumat, GPU_MATFLAG_SSS);
+
+ int ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ? 1 : 0;
+ int option = (use_ssrefract ? 0 : (use_sss ? 1 : 2)) * 2 + do_cull;
+ DRWPass *shading_pass = (DRWPass *[]){
+ psl->material_refract_ps,
+ psl->material_refract_cull_ps,
+ psl->material_sss_ps,
+ psl->material_sss_cull_ps,
+ psl->material_ps,
+ psl->material_cull_ps,
+ }[option];
+ /* Hair are rendered inside the non-cull pass but needs to have a separate cache key */
+ option = option * 2 + is_hair;
+
+ /* Search for the same shaders usage in the pass. */
+ /* HACK: Assume the struct will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparisons/hashing. */
+ BLI_assert(option <= 16);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
}
else {
- emsg->depth_grp = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp;
- emsg->depth_clip_grp = (do_cull) ? stl->g_data->depth_shgrp_clip_cull :
- stl->g_data->depth_shgrp_clip;
+ *grp_p = grp = DRW_shgroup_create(sh, shading_pass);
+ EEVEE_material_bind_resources(
+ grp, gpumat, sldata, vedata, &ssr_id, &ma->refract_depth, use_ssrefract, false);
}
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups));
- if (store_material) {
- BLI_ghash_insert(material_hash, ma, emsg);
- }
- else {
- MEM_freeN(emsg);
+ if (use_sss) {
+ EEVEE_subsurface_add_pass(sldata, vedata, ma, grp, gpumat);
+ }
+
+ emc->shading_grp = grp;
+ emc->shading_grp_p = grp_p;
+ emc->shading_gpumat = gpumat;
}
+ return *emc;
}
-static void material_transparent(Material *ma,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- struct GPUMaterial **gpumat,
- struct EeveeMaterialShadingGroups *shgrps)
+static EeveeMaterialCache material_transparent(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EeveeMaterialCache emc = {0};
const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
const bool use_gpumat = ma->use_nodes && ma->nodetree;
const bool use_ssrefract = use_gpumat && ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
- ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0);
- const float *color_p = &ma->r;
- const float *metal_p = &ma->metallic;
- const float *spec_p = &ma->spec;
- const float *rough_p = &ma->roughness;
-
+ ((effects->enabled_effects & EFFECT_REFRACT) != 0);
const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKFACE) != 0);
DRWState cur_state;
@@ -1677,81 +691,53 @@ static void material_transparent(Material *ma,
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL |
DRW_STATE_BLEND_CUSTOM);
- /* Depth prepass */
+ material_shadow(vedata, sldata, ma, false, &emc);
+
if (use_prepass) {
- shgrps->depth_grp = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass);
+ /* Depth prepass */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->transparent_pass);
+
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, true);
+ DRW_shgroup_add_material_resources(grp, gpumat);
cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
- DRW_shgroup_state_disable(shgrps->depth_grp, all_state);
- DRW_shgroup_state_enable(shgrps->depth_grp, cur_state);
+ DRW_shgroup_state_disable(grp, all_state);
+ DRW_shgroup_state_enable(grp, cur_state);
+
+ emc.depth_grp = grp;
}
+ {
+ /* Shading */
+ int ssr_id = -1; /* TODO transparent SSR */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_BLEND;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
- if (use_gpumat) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
- static float half = 0.5f;
+ DRWShadingGroup *grp = DRW_shgroup_create(GPU_material_get_shader(gpumat),
+ psl->transparent_pass);
- /* Shading */
- *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, use_ssrefract);
-
- switch (GPU_material_status(*gpumat)) {
- case GPU_MAT_SUCCESS: {
- static int ssr_id = -1; /* TODO transparent SSR */
-
- shgrps->shading_grp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass);
-
- bool use_blend = true;
- bool use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE);
- bool use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY);
- bool use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT);
-
- add_standard_uniforms(shgrps->shading_grp,
- sldata,
- vedata,
- &ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- use_blend,
- DEFAULT_RENDER_PASS_FLAG);
- break;
- }
- case GPU_MAT_QUEUED: {
- /* TODO Bypass probe compilation. */
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- }
+ EEVEE_material_bind_resources(
+ grp, gpumat, sldata, vedata, &ssr_id, &ma->refract_depth, use_ssrefract, true);
+ DRW_shgroup_add_material_resources(grp, gpumat);
- /* Fallback to default shader */
- if (shgrps->shading_grp == NULL) {
- shgrps->shading_grp = EEVEE_default_shading_group_create(
- sldata, vedata, psl->transparent_pass, false, true, false);
- DRW_shgroup_uniform_vec3(shgrps->shading_grp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "roughness", rough_p, 1);
- }
+ cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
+ cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL;
+ cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
- cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
- cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL;
- cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
+ /* Disable other blend modes and use the one we want. */
+ DRW_shgroup_state_disable(grp, all_state);
+ DRW_shgroup_state_enable(grp, cur_state);
- /* Disable other blend modes and use the one we want. */
- DRW_shgroup_state_disable(shgrps->shading_grp, all_state);
- DRW_shgroup_state_enable(shgrps->shading_grp, cur_state);
+ emc.shading_grp = grp;
+ emc.shading_gpumat = gpumat;
+ }
+ return emc;
}
/* Return correct material or empty default material if slot is empty. */
@@ -1766,12 +752,35 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot, bool holdou
ma = BKE_material_default_volume();
}
else {
- ma = BKE_material_default_empty();
+ ma = BKE_material_default_surface();
}
}
return ma;
}
+BLI_INLINE EeveeMaterialCache eevee_material_cache_get(
+ EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, int slot, bool is_hair)
+{
+ const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
+ EeveeMaterialCache matcache;
+ Material *ma = eevee_object_material_get(ob, slot, holdout);
+ switch (ma->blend_method) {
+ case MA_BM_BLEND:
+ if (!is_hair) {
+ matcache = material_transparent(vedata, sldata, ma);
+ break;
+ }
+ ATTR_FALLTHROUGH;
+ case MA_BM_SOLID:
+ case MA_BM_CLIP:
+ case MA_BM_HASHED:
+ default:
+ matcache = material_opaque(vedata, sldata, ma, is_hair);
+ break;
+ }
+ return matcache;
+}
+
static void eevee_hair_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
@@ -1780,240 +789,49 @@ static void eevee_hair_cache_populate(EEVEE_Data *vedata,
int matnr,
bool *cast_shadow)
{
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
-
- DRWShadingGroup *shgrp = NULL;
- Material *ma = eevee_object_material_get(ob, matnr - 1, holdout);
- const bool use_gpumat = ma->use_nodes && ma->nodetree && !holdout;
- const bool use_alpha_hash = (ma->blend_method == MA_BM_HASHED);
- const bool use_alpha_clip = (ma->blend_method == MA_BM_CLIP);
- const bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0);
+ EeveeMaterialCache matcache = eevee_material_cache_get(vedata, sldata, ob, matnr - 1, true);
- GPUMaterial *gpumat = use_gpumat ? EEVEE_material_hair_get(scene, ma) : NULL;
- eGPUMaterialStatus status_mat_surface = gpumat ? GPU_material_status(gpumat) : GPU_MAT_SUCCESS;
-
- float *color_p = &ma->r;
- float *metal_p = &ma->metallic;
- float *spec_p = &ma->spec;
- float *rough_p = &ma->roughness;
-
- /* Depth prepass. */
- if (use_gpumat && (use_alpha_clip || use_alpha_hash)) {
- GPUMaterial *gpumat_depth = EEVEE_material_hair_depth_get(scene, ma, use_alpha_hash, false);
-
- eGPUMaterialStatus status_mat_depth = GPU_material_status(gpumat_depth);
-
- if (status_mat_depth != GPU_MAT_SUCCESS) {
- /* Mixing both flags. If depth shader fails, show it to the user by not using
- * the surface shader. */
- status_mat_surface = status_mat_depth;
- }
- else {
- const bool use_diffuse = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_DIFFUSE);
- const bool use_glossy = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_GLOSSY);
- const bool use_refract = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_REFRACT);
-
- for (int i = 0; i < 2; i++) {
- DRWPass *pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip;
-
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, pass, gpumat_depth);
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
-
- if (use_alpha_clip) {
- DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- }
- }
+ if (matcache.depth_grp) {
+ *matcache.depth_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.depth_grp);
}
-
- /* Fallback to default shader */
- if (shgrp == NULL) {
- for (int i = 0; i < 2; i++) {
- DRWPass *depth_pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip;
- struct GPUShader *depth_sh = (i == 0) ? e_data.default_hair_prepass_sh :
- e_data.default_hair_prepass_clip_sh;
- DRW_shgroup_hair_create(ob, psys, md, depth_pass, depth_sh);
- }
+ if (matcache.shading_grp) {
+ *matcache.shading_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shading_grp);
}
-
- shgrp = NULL;
-
- if (gpumat) {
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- static float half = 0.5f;
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
-
- switch (status_mat_surface) {
- case GPU_MAT_SUCCESS: {
- bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE);
- bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY);
- bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT);
-
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->material_pass, gpumat);
-
- if (!use_diffuse && !use_glossy && !use_refract) {
- /* HACK: Small hack to avoid issue when utilTex is needed for
- * world_normals_get and none of the bsdfs are present.
- * This binds utilTex even if not needed. */
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- }
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- /* Add the hair to all the render_passes that are enabled */
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- shgrp = DRW_shgroup_material_hair_create(
- ob, psys, md, psl->material_accum_pass[render_pass_index], gpumat);
- if (!use_diffuse && !use_glossy && !use_refract) {
- /* Small hack to avoid issue when utilTex is needed for
- * world_normals_get and none of the bsdfs that need it are present.
- * This binds `utilTex` even if not needed. */
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- }
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- render_pass_flag);
- }
- RENDER_PASS_ITER_END(render_pass_index);
-
- break;
- }
- case GPU_MAT_QUEUED: {
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
+ if (matcache.shadow_grp) {
+ *matcache.shadow_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shadow_grp);
+ *cast_shadow = true;
}
+}
- /* Fallback to default shader */
- if (shgrp == NULL) {
- shgrp = EEVEE_default_shading_group_get(sldata, vedata, ob, psys, md, true, holdout, use_ssr);
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1);
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- shgrp = EEVEE_default_hair_render_pass_shading_group_get(
- sldata,
- vedata,
- ob,
- psys,
- md,
- holdout,
- use_ssr,
- psl->material_accum_pass[render_pass_index],
- render_pass_flag);
-
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1);
- }
- RENDER_PASS_ITER_END(render_pass_index);
- }
+#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \
+ do { \
+ if (oedata) { \
+ DRW_shgroup_call_with_callback(shgrp, geom, ob, oedata); \
+ } \
+ else { \
+ DRW_shgroup_call(shgrp, geom, ob); \
+ } \
+ } while (0)
- /* Shadows */
- char blend_shadow = use_gpumat ? ma->blend_shadow : MA_BS_SOLID;
- const bool shadow_alpha_hash = (blend_shadow == MA_BS_HASHED);
- switch (blend_shadow) {
- case MA_BS_SOLID:
- DRW_shgroup_hair_create(ob, psys, md, psl->shadow_pass, e_data.default_hair_prepass_sh);
- *cast_shadow = true;
- break;
- case MA_BS_CLIP:
- case MA_BS_HASHED:
- gpumat = EEVEE_material_hair_depth_get(scene, ma, shadow_alpha_hash, true);
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->shadow_pass, gpumat);
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
-
- if (!shadow_alpha_hash) {
- DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- *cast_shadow = true;
- break;
- case MA_BS_NONE:
- default:
- break;
+#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \
+ do { \
+ if (shgrp) { \
+ ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \
+ } \
+ } while (0)
+
+#define MATCACHE_AS_ARRAY(matcache, member, materials_len, output_array) \
+ for (int i = 0; i < materials_len; i++) { \
+ output_array[i] = matcache[i].member; \
}
-}
void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
bool *cast_shadow)
{
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- GHash *material_hash = stl->g_data->material_hash;
- const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
!DRW_state_is_image_render();
@@ -2022,139 +840,64 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
const int materials_len = DRW_cache_object_material_count_get(ob);
- struct EeveeMaterialShadingGroups *shgrps_array = BLI_array_alloca(shgrps_array,
- materials_len);
-
- struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
- struct GPUMaterial **gpumat_depth_array = BLI_array_alloca(gpumat_array, materials_len);
- struct Material **ma_array = BLI_array_alloca(ma_array, materials_len);
-
+ EeveeMaterialCache *matcache = BLI_array_alloca(matcache, materials_len);
for (int i = 0; i < materials_len; i++) {
- ma_array[i] = eevee_object_material_get(ob, i, holdout);
- memset(&shgrps_array[i], 0, sizeof(EeveeMaterialShadingGroups));
- gpumat_array[i] = NULL;
- gpumat_depth_array[i] = NULL;
-
- switch (ma_array[i]->blend_method) {
- case MA_BM_SOLID:
- case MA_BM_CLIP:
- case MA_BM_HASHED:
- material_opaque(ma_array[i],
- material_hash,
- sldata,
- vedata,
- &gpumat_array[i],
- &gpumat_depth_array[i],
- &shgrps_array[i],
- holdout);
- break;
- case MA_BM_BLEND:
- material_transparent(ma_array[i], sldata, vedata, &gpumat_array[i], &shgrps_array[i]);
- break;
- default:
- BLI_assert(0);
- break;
- }
+ matcache[i] = eevee_material_cache_get(vedata, sldata, ob, i, false);
}
/* Only support single volume material for now. */
/* XXX We rely on the previously compiled surface shader
* to know if the material has a "volume nodetree".
*/
- bool use_volume_material = (gpumat_array[0] &&
- GPU_material_has_volume_output(gpumat_array[0]));
+ bool use_volume_material = (matcache[0].shading_gpumat &&
+ GPU_material_has_volume_output(matcache[0].shading_gpumat));
if ((ob->dt >= OB_SOLID) || DRW_state_is_image_render()) {
- /* Get per-material split surface */
- struct GPUBatch **mat_geom = NULL;
-
- if (!use_sculpt_pbvh) {
- mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len);
- }
-
if (use_sculpt_pbvh) {
- struct DRWShadingGroup **sculpt_shgrps_array = BLI_array_alloca(sculpt_shgrps_array,
- materials_len);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].shading_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
+ struct DRWShadingGroup **shgrps_array = BLI_array_alloca(shgrps_array, materials_len);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].depth_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].depth_clip_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
+ MATCACHE_AS_ARRAY(matcache, shading_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
- for (int renderpass_index = 0;
- renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].material_accum_grp[renderpass_index];
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
- }
+ MATCACHE_AS_ARRAY(matcache, depth_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
- /* TODO(fclem): Support shadows in sculpt mode. */
+ MATCACHE_AS_ARRAY(matcache, shadow_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
}
- else if (mat_geom) {
- for (int i = 0; i < materials_len; i++) {
- if (mat_geom[i] == NULL) {
- continue;
- }
+ else {
+ struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
+ MATCACHE_AS_ARRAY(matcache, shading_gpumat, materials_len, gpumat_array);
+ /* Get per-material split surface */
+ struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
+ ob, gpumat_array, materials_len);
- /* Do not render surface if we are rendering a volume object
- * and do not have a surface closure. */
- if (use_volume_material &&
- (gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) {
- continue;
- }
+ if (mat_geom) {
+ for (int i = 0; i < materials_len; i++) {
+ if (mat_geom[i] == NULL) {
+ continue;
+ }
- /* XXX TODO rewrite this to include the dupli objects.
- * This means we cannot exclude dupli objects from reflections!!! */
- EEVEE_ObjectEngineData *oedata = NULL;
- if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
- oedata = EEVEE_object_data_ensure(ob);
- oedata->ob = ob;
- oedata->test_data = &sldata->probes->vis_data;
- }
- EeveeMaterialShadingGroups *shgrps = &shgrps_array[i];
- ADD_SHGROUP_CALL(shgrps->shading_grp, ob, mat_geom[i], oedata);
- ADD_SHGROUP_CALL_SAFE(shgrps->depth_grp, ob, mat_geom[i], oedata);
- ADD_SHGROUP_CALL_SAFE(shgrps->depth_clip_grp, ob, mat_geom[i], oedata);
- for (int renderpass_index = 0;
- renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- ADD_SHGROUP_CALL_SAFE(
- shgrps->material_accum_grp[renderpass_index], ob, mat_geom[i], oedata);
- }
+ /* Do not render surface if we are rendering a volume object
+ * and do not have a surface closure. */
+ if (use_volume_material &&
+ (gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) {
+ continue;
+ }
+
+ /* XXX TODO rewrite this to include the dupli objects.
+ * This means we cannot exclude dupli objects from reflections!!! */
+ EEVEE_ObjectEngineData *oedata = NULL;
+ if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
+ oedata = EEVEE_object_data_ensure(ob);
+ oedata->ob = ob;
+ oedata->test_data = &sldata->probes->vis_data;
+ }
- /* Shadow Pass */
- struct GPUMaterial *gpumat;
- const bool use_gpumat = (ma_array[i]->use_nodes && ma_array[i]->nodetree);
- char blend_shadow = use_gpumat ? ma_array[i]->blend_shadow : MA_BS_SOLID;
- switch (blend_shadow) {
- case MA_BS_SOLID:
- EEVEE_shadows_caster_add(sldata, stl, mat_geom[i], ob);
- *cast_shadow = true;
- break;
- case MA_BS_CLIP:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], false, true);
- EEVEE_shadows_caster_material_add(
- sldata, psl, gpumat, mat_geom[i], ob, &ma_array[i]->alpha_threshold);
- *cast_shadow = true;
- break;
- case MA_BS_HASHED:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], true, true);
- EEVEE_shadows_caster_material_add(sldata, psl, gpumat, mat_geom[i], ob, NULL);
- *cast_shadow = true;
- break;
- case MA_BS_NONE:
- default:
- break;
+ ADD_SHGROUP_CALL(matcache[i].shading_grp, ob, mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(matcache[i].depth_grp, ob, mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(matcache[i].shadow_grp, ob, mat_geom[i], oedata);
+ *cast_shadow = (matcache[i].shadow_grp != NULL);
}
}
}
@@ -2205,11 +948,12 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
- BLI_ghash_free(stl->g_data->material_hash, NULL, MEM_freeN);
+ BLI_ghash_free(pd->material_hash, NULL, NULL);
- SET_FLAG_FROM_TEST(stl->effects->enabled_effects, e_data.sss_count > 0, EFFECT_SSS);
+ SET_FLAG_FROM_TEST(effects->enabled_effects, effects->sss_surface_count > 0, EFFECT_SSS);
/* TODO(fclem) this is not really clean. Init should not be done in cache finish. */
EEVEE_subsurface_draw_init(sldata, vedata);
@@ -2217,38 +961,10 @@ void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
void EEVEE_materials_free(void)
{
- for (int i = 0; i < VAR_MAT_MAX; i++) {
- DRW_SHADER_FREE_SAFE(e_data.default_lit[i]);
- }
- MEM_SAFE_FREE(e_data.frag_shader_lib);
- MEM_SAFE_FREE(e_data.vert_shader_str);
- MEM_SAFE_FREE(e_data.vert_shadow_shader_str);
- MEM_SAFE_FREE(e_data.vert_background_shader_str);
- MEM_SAFE_FREE(e_data.vert_volume_shader_str);
- MEM_SAFE_FREE(e_data.geom_volume_shader_str);
- MEM_SAFE_FREE(e_data.volume_shader_lib);
- DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_clip_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_background);
- DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_TEXTURE_FREE_SAFE(e_data.util_tex);
DRW_TEXTURE_FREE_SAFE(e_data.noise_tex);
}
-void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_PassList *psl)
-{
- for (int i = 0; i < VAR_MAT_MAX; i++) {
- if (psl->default_pass[i]) {
- DRW_draw_pass(psl->default_pass[i]);
- }
- }
-
- DRW_draw_pass(psl->material_pass);
- DRW_draw_pass(psl->material_pass_cull);
-}
-
/* -------------------------------------------------------------------- */
/** \name Render Passes
@@ -2256,172 +972,140 @@ void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Pass
void EEVEE_material_renderpasses_init(EEVEE_Data *vedata)
{
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_PrivateData *g_data = stl->g_data;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
/* For diffuse and glossy we calculate the final light + color buffer where we extract the
* light from by dividing by the color buffer. When one the light is requested we also tag
* the color buffer to do the extraction. */
- if (g_data->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
- g_data->render_passes |= EEVEE_RENDER_PASS_DIFFUSE_COLOR;
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ pd->render_passes |= EEVEE_RENDER_PASS_DIFFUSE_COLOR;
}
- if (g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
- g_data->render_passes |= EEVEE_RENDER_PASS_SPECULAR_COLOR;
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ pd->render_passes |= EEVEE_RENDER_PASS_SPECULAR_COLOR;
}
+}
- /* Calculate the number of material based render passes */
- uint num_render_passes = count_bits_i(stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL);
- if ((num_render_passes != 0 && stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) ==
- 0) {
- num_render_passes += 1;
+static void material_renderpass_init(EEVEE_FramebufferList *fbl,
+ GPUTexture **output_tx,
+ const eGPUTextureFormat format,
+ const bool do_clear)
+{
+ DRW_texture_ensure_fullscreen_2d(output_tx, format, 0);
+ /* Clear texture. */
+ if (do_clear) {
+ float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* TODO(fclem) replace by GPU_texture_clear once it is fast. */
+ GPU_framebuffer_texture_attach(fbl->material_accum_fb, *output_tx, 0, 0);
+ GPU_framebuffer_bind(fbl->material_accum_fb);
+ GPU_framebuffer_clear_color(fbl->material_accum_fb, clear);
+ GPU_framebuffer_bind(fbl->main_fb);
+ GPU_framebuffer_texture_detach(fbl->material_accum_fb, *output_tx);
}
- stl->g_data->render_passes_material_count = num_render_passes;
}
void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples)
{
- const DRWContextState *draw_ctx = DRW_context_state_get();
EEVEE_FramebufferList *fbl = vedata->fbl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
EEVEE_TextureList *txl = vedata->txl;
EEVEE_StorageList *stl = vedata->stl;
- EEVEE_PassList *psl = vedata->psl;
EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_PrivateData *pd = stl->g_data;
- float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* Should be enough precision for many samples. */
+ const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F;
+ const bool do_clear = DRW_state_is_image_render() || (effects->taa_current_sample == 1);
/* Create FrameBuffer. */
+ GPU_framebuffer_ensure_config(&fbl->material_accum_fb,
+ {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE});
- /* Should be enough precision for many samples. */
- const eGPUTextureFormat texture_format_material_accum = (tot_samples > 128) ? GPU_RGBA32F :
- GPU_RGBA16F;
- const eViewLayerEEVEEPassType render_passes = stl->g_data->render_passes &
- EEVEE_RENDERPASSES_MATERIAL;
- if (render_passes != 0) {
- GPU_framebuffer_ensure_config(&fbl->material_accum_fb,
- {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE});
- int render_pass_index = ((render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) != 0) ? 0 : 1;
- for (int bit = 0; bit < 32; bit++) {
- eViewLayerEEVEEPassType bitflag = (1 << bit);
- if ((render_passes & bitflag) != 0) {
-
- DRW_texture_ensure_fullscreen_2d(
- &txl->material_accum[render_pass_index], texture_format_material_accum, 0);
-
- /* Clear texture. */
- if (DRW_state_is_image_render() || effects->taa_current_sample == 1) {
- GPU_framebuffer_texture_attach(
- fbl->material_accum_fb, txl->material_accum[render_pass_index], 0, 0);
- GPU_framebuffer_bind(fbl->material_accum_fb);
- GPU_framebuffer_clear_color(fbl->material_accum_fb, clear);
- GPU_framebuffer_bind(fbl->main_fb);
- GPU_framebuffer_texture_detach(fbl->material_accum_fb,
- txl->material_accum[render_pass_index]);
- }
- render_pass_index++;
- }
- }
+ if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
+ material_renderpass_init(fbl, &txl->env_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) {
+ material_renderpass_init(fbl, &txl->emit_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) {
+ material_renderpass_init(fbl, &txl->diff_color_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ material_renderpass_init(fbl, &txl->diff_light_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) {
+ material_renderpass_init(fbl, &txl->spec_color_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ material_renderpass_init(fbl, &txl->spec_light_accum, texture_format, do_clear);
- if ((render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) &&
- (effects->enabled_effects & EFFECT_SSR)) {
+ if (effects->enabled_effects & EFFECT_SSR) {
EEVEE_reflection_output_init(sldata, vedata, tot_samples);
}
+ }
+}
- if (render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
- Scene *scene = draw_ctx->scene;
- World *wo = scene->world;
+static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl,
+ DRWPass *renderpass,
+ EEVEE_PrivateData *pd,
+ GPUTexture *output_tx,
+ struct GPUUniformBuffer *renderpass_option_ubo)
+{
+ GPU_framebuffer_texture_attach(fbl->material_accum_fb, output_tx, 0, 0);
+ GPU_framebuffer_bind(fbl->material_accum_fb);
- if (wo && wo->use_nodes && wo->nodetree) {
- struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo);
- if (GPU_material_status(gpumat) == GPU_MAT_SUCCESS) {
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->material_accum_pass[0]);
- add_background_uniforms(grp, sldata, vedata);
- DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
- }
- }
- }
- }
+ pd->renderpass_ubo = renderpass_option_ubo;
+ DRW_draw_pass(renderpass);
+
+ GPU_framebuffer_texture_detach(fbl->material_accum_fb, output_tx);
}
void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
EEVEE_TextureList *txl = vedata->txl;
if (fbl->material_accum_fb != NULL) {
- for (int renderpass_index = 0; renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- if (txl->material_accum[renderpass_index] != NULL) {
- GPU_framebuffer_texture_attach(
- fbl->material_accum_fb, txl->material_accum[renderpass_index], 0, 0);
- GPU_framebuffer_bind(fbl->material_accum_fb);
- DRW_draw_pass(psl->material_accum_pass[renderpass_index]);
- GPU_framebuffer_bind(fbl->main_fb);
- GPU_framebuffer_texture_detach(fbl->material_accum_fb,
- txl->material_accum[renderpass_index]);
- }
+ DRWPass *material_accum_ps = psl->material_accum_ps;
+ if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
+ material_renderpass_accumulate(
+ fbl, psl->background_accum_ps, pd, txl->env_accum, sldata->renderpass_ubo.combined);
}
- if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) &&
- (stl->effects->enabled_effects & EFFECT_SSR)) {
- EEVEE_reflection_output_accumulate(sldata, vedata);
+ if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->emit_accum, sldata->renderpass_ubo.emit);
}
- }
-}
-
-int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type)
-{
- EEVEE_StorageList *stl = vedata->stl;
-
- BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL) != 0);
- BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL & renderpass_type) != 0);
-
- /* pass_index 0 is reserved for the environment pass. */
- if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT & renderpass_type) != 0) {
- return 0;
- }
-
- /* pass_index 0 is reserved for the environment pass. Other passes start from index 1 */
- int index = 1;
- eViewLayerEEVEEPassType active_material_passes = stl->g_data->render_passes &
- EEVEE_RENDERPASSES_MATERIAL &
- ~EEVEE_RENDER_PASS_ENVIRONMENT;
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->diff_color_accum, sldata->renderpass_ubo.diff_color);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->diff_light_accum, sldata->renderpass_ubo.diff_light);
- for (int bitshift = 0; bitshift < 32; bitshift++) {
- eViewLayerEEVEEPassType pass_flag = (1 << bitshift);
- if (pass_flag == renderpass_type) {
- break;
+ if (effects->enabled_effects & EFFECT_SSS) {
+ EEVEE_subsurface_output_accumulate(sldata, vedata);
+ }
}
- if (active_material_passes & pass_flag) {
- index++;
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->spec_color_accum, sldata->renderpass_ubo.spec_color);
}
- }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->spec_light_accum, sldata->renderpass_ubo.spec_light);
- return index;
-}
+ if (effects->enabled_effects & EFFECT_SSR) {
+ EEVEE_reflection_output_accumulate(sldata, vedata);
+ }
+ }
-/* Get the pass index that contains the color pass for the given renderpass_type. */
-int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type)
-{
- BLI_assert(
- ELEM(renderpass_type, EEVEE_RENDER_PASS_DIFFUSE_LIGHT, EEVEE_RENDER_PASS_SPECULAR_LIGHT));
- eViewLayerEEVEEPassType color_pass_type;
- switch (renderpass_type) {
- case EEVEE_RENDER_PASS_DIFFUSE_LIGHT:
- color_pass_type = EEVEE_RENDER_PASS_DIFFUSE_COLOR;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_LIGHT:
- color_pass_type = EEVEE_RENDER_PASS_SPECULAR_COLOR;
- break;
- default:
- color_pass_type = 0;
- BLI_assert(false);
+ /* Restore default. */
+ pd->renderpass_ubo = sldata->renderpass_ubo.combined;
+ GPU_framebuffer_bind(fbl->main_fb);
}
- return EEVEE_material_output_pass_index_get(sldata, vedata, color_pass_type);
}
+
/* \} */
diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c
index cdcfd64d995..7b942784ee9 100644
--- a/source/blender/draw/engines/eevee/eevee_mist.c
+++ b/source/blender/draw/engines/eevee/eevee_mist.c
@@ -114,8 +114,7 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRWShadingGroup *grp = DRW_shgroup_create(e_data.mist_sh, psl->mist_accum_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_vec3(grp, "mistSettings", &g_data->mist_start, 1);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index be4dfd07ce1..f5ebbe08dd1 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -170,8 +170,7 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
else {
@@ -209,8 +208,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, quad, NULL);
DRW_PASS_CREATE(psl->ao_horizon_search_layer, DRW_STATE_WRITE_COLOR);
@@ -219,8 +217,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBufferLayered", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1);
DRW_shgroup_call(grp, quad, NULL);
@@ -233,8 +230,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, quad, NULL);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 264f301e52c..40008c5c364 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -158,35 +158,34 @@ BLI_INLINE bool eevee_hdri_preview_overlay_enabled(const View3D *v3d)
(EEVEE_RENDER_PASS_EMIT | EEVEE_RENDER_PASS_DIFFUSE_COLOR | EEVEE_RENDER_PASS_DIFFUSE_LIGHT | \
EEVEE_RENDER_PASS_SPECULAR_COLOR | EEVEE_RENDER_PASS_SPECULAR_LIGHT | \
EEVEE_RENDER_PASS_ENVIRONMENT)
-#define MAX_MATERIAL_RENDER_PASSES 6
-#define MAX_MATERIAL_RENDER_PASSES_UBO 6
-/* World shader variations */
-enum {
- VAR_WORLD_BACKGROUND = 0,
- VAR_WORLD_PROBE = 1,
- VAR_WORLD_VOLUME = 2,
-};
/* Material shader variations */
enum {
VAR_MAT_MESH = (1 << 0),
- VAR_MAT_PROBE = (1 << 1),
+ VAR_MAT_VOLUME = (1 << 1),
VAR_MAT_HAIR = (1 << 2),
- VAR_MAT_BLEND = (1 << 3),
- VAR_MAT_VOLUME = (1 << 4),
+ VAR_MAT_PROBE = (1 << 3),
+ VAR_MAT_BLEND = (1 << 4),
VAR_MAT_LOOKDEV = (1 << 5),
VAR_MAT_HOLDOUT = (1 << 6),
- /* Max number of variation */
- /* IMPORTANT : Leave it last and set
- * it's value accordingly. */
- VAR_MAT_MAX = (1 << 7),
- /* These are options that are not counted in VAR_MAT_MAX
- * because they are not cumulative with the others above. */
- VAR_MAT_CLIP = (1 << 9),
- VAR_MAT_HASH = (1 << 10),
- VAR_MAT_MULT = (1 << 11),
- VAR_MAT_SHADOW = (1 << 12),
- VAR_MAT_REFRACT = (1 << 13),
+ VAR_MAT_HASH = (1 << 7),
+ VAR_MAT_DEPTH = (1 << 8),
+ VAR_MAT_REFRACT = (1 << 9),
+ VAR_WORLD_BACKGROUND = (1 << 10),
+ VAR_WORLD_PROBE = (1 << 11),
+ VAR_WORLD_VOLUME = (1 << 12),
+ VAR_DEFAULT = (1 << 13),
+};
+
+/* Material shader cache keys */
+enum {
+ /* HACK: This assumes the struct GPUShader will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparisons/hashing.
+ * We combine the GPUShader pointer with the key. */
+ KEY_CULL = (1 << 0),
+ KEY_REFRACT = (1 << 1),
+ KEY_HAIR = (1 << 2),
+ KEY_SHADOW = (1 << 3),
};
/* ************ PROBE UBO ************* */
@@ -272,23 +271,26 @@ typedef struct EEVEE_PassList {
struct DRWPass *maxz_copydepth_ps;
struct DRWPass *maxz_copydepth_layer_ps;
- struct DRWPass *depth_pass;
- struct DRWPass *depth_pass_cull;
- struct DRWPass *depth_pass_clip;
- struct DRWPass *depth_pass_clip_cull;
- struct DRWPass *refract_depth_pass;
- struct DRWPass *refract_depth_pass_cull;
- struct DRWPass *refract_depth_pass_clip;
- struct DRWPass *refract_depth_pass_clip_cull;
- struct DRWPass *default_pass[VAR_MAT_MAX];
- struct DRWPass *sss_pass;
- struct DRWPass *sss_pass_cull;
- struct DRWPass *material_pass;
- struct DRWPass *material_pass_cull;
- struct DRWPass *material_accum_pass[MAX_MATERIAL_RENDER_PASSES];
- struct DRWPass *refract_pass;
+ /* Renderpass Accumulation. */
+ struct DRWPass *material_accum_ps;
+ struct DRWPass *background_accum_ps;
+
+ struct DRWPass *depth_ps;
+ struct DRWPass *depth_cull_ps;
+ struct DRWPass *depth_clip_ps;
+ struct DRWPass *depth_clip_cull_ps;
+ struct DRWPass *depth_refract_ps;
+ struct DRWPass *depth_refract_cull_ps;
+ struct DRWPass *depth_refract_clip_ps;
+ struct DRWPass *depth_refract_clip_cull_ps;
+ struct DRWPass *material_ps;
+ struct DRWPass *material_cull_ps;
+ struct DRWPass *material_refract_ps;
+ struct DRWPass *material_refract_cull_ps;
+ struct DRWPass *material_sss_ps;
+ struct DRWPass *material_sss_cull_ps;
struct DRWPass *transparent_pass;
- struct DRWPass *background_pass;
+ struct DRWPass *background_ps;
struct DRWPass *update_noise_pass;
struct DRWPass *lookdev_glossy_pass;
struct DRWPass *lookdev_diffuse_pass;
@@ -348,7 +350,12 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *mist_accum;
struct GPUTexture *ao_accum;
struct GPUTexture *sss_accum;
- struct GPUTexture *material_accum[MAX_MATERIAL_RENDER_PASSES];
+ struct GPUTexture *env_accum;
+ struct GPUTexture *diff_color_accum;
+ struct GPUTexture *diff_light_accum;
+ struct GPUTexture *spec_color_accum;
+ struct GPUTexture *spec_light_accum;
+ struct GPUTexture *emit_accum;
struct GPUTexture *bloom_accum;
struct GPUTexture *ssr_accum;
struct GPUTexture *shadow_accum;
@@ -574,6 +581,7 @@ typedef struct EEVEE_EffectsInfo {
bool swap_double_buffer;
/* SSSS */
int sss_sample_count;
+ int sss_surface_count;
struct GPUTexture *sss_irradiance; /* Textures from pool */
struct GPUTexture *sss_radius;
struct GPUTexture *sss_albedo;
@@ -754,14 +762,22 @@ typedef struct EEVEE_ViewLayerData {
struct GPUUniformBuffer *planar_ubo;
/* Material Render passes */
- struct EEVEE_RenderPassData renderpass_data[MAX_MATERIAL_RENDER_PASSES_UBO];
- struct GPUUniformBuffer *renderpass_ubo[MAX_MATERIAL_RENDER_PASSES_UBO];
+ struct {
+ struct GPUUniformBuffer *combined;
+ struct GPUUniformBuffer *diff_color;
+ struct GPUUniformBuffer *diff_light;
+ struct GPUUniformBuffer *spec_color;
+ struct GPUUniformBuffer *spec_light;
+ struct GPUUniformBuffer *emit;
+ } renderpass_ubo;
/* Common Uniform Buffer */
struct EEVEE_CommonUniformBuffer common_data;
struct GPUUniformBuffer *common_ubo;
struct LightCache *fallback_lightcache;
+
+ struct BLI_memblock *material_cache;
} EEVEE_ViewLayerData;
/* ************ OBJECT DATA ************ */
@@ -809,14 +825,6 @@ typedef struct EEVEE_Data {
typedef struct EEVEE_PrivateData {
struct DRWShadingGroup *shadow_shgrp;
struct DRWShadingGroup *shadow_accum_shgrp;
- struct DRWShadingGroup *depth_shgrp;
- struct DRWShadingGroup *depth_shgrp_cull;
- struct DRWShadingGroup *depth_shgrp_clip;
- struct DRWShadingGroup *depth_shgrp_clip_cull;
- struct DRWShadingGroup *refract_depth_shgrp;
- struct DRWShadingGroup *refract_depth_shgrp_cull;
- struct DRWShadingGroup *refract_depth_shgrp_clip;
- struct DRWShadingGroup *refract_depth_shgrp_clip_cull;
struct DRWCallBuffer *planar_display_shgrp;
struct GHash *material_hash;
float background_alpha; /* TODO find a better place for this. */
@@ -862,9 +870,8 @@ typedef struct EEVEE_PrivateData {
GPUTexture *renderpass_input;
GPUTexture *renderpass_col_input;
GPUTexture *renderpass_light_input;
- /* The number of active material based render passes */
- uint render_passes_material_count;
-
+ /* Renderpass ubo reference used by material pass. */
+ struct GPUUniformBuffer *renderpass_ubo;
/** For rendering shadows. */
struct DRWView *cube_views[6];
/** For rendering probes. */
@@ -892,6 +899,7 @@ EEVEE_WorldEngineData *EEVEE_world_data_ensure(World *wo);
/* eevee_materials.c */
struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
EEVEE_StorageList *stl,
EEVEE_FramebufferList *fbl);
void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@@ -908,31 +916,20 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
Object *ob,
bool *cast_shadow);
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo);
-struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo);
-struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo);
-struct GPUMaterial *EEVEE_material_mesh_get(
- struct Scene *scene, Material *ma, EEVEE_Data *vedata, bool use_blend, bool use_refract);
-struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma);
-struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow);
-struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma);
-struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata);
void EEVEE_materials_free(void);
-void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl);
void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]);
void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4]);
void EEVEE_material_renderpasses_init(EEVEE_Data *vedata);
void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples);
void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type);
-int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type);
+void EEVEE_material_bind_resources(DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat,
+ EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ int *ssr_id,
+ float *refract_depth,
+ bool use_ssrefraction,
+ bool use_alpha_blend);
/* eevee_lights.c */
void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4]);
void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@@ -943,16 +940,6 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh);
void EEVEE_shadows_init(EEVEE_ViewLayerData *sldata);
void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *sldata,
- EEVEE_StorageList *stl,
- struct GPUBatch *geom,
- Object *ob);
-void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata,
- EEVEE_PassList *psl,
- struct GPUMaterial *gpumat,
- struct GPUBatch *geom,
- struct Object *ob,
- const float *alpha_threshold);
void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, struct Object *ob);
void EEVEE_shadows_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_shadows_cube_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, struct Object *ob);
@@ -986,6 +973,7 @@ void EEVEE_random_rotation_m4(int sample_ofs, float scale, float r_mat[4][4]);
/* eevee_shaders.c */
void EEVEE_shaders_lightprobe_shaders_init(void);
+void EEVEE_shaders_material_shaders_init(void);
struct GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_default_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_filter_diffuse_sh_get(void);
@@ -993,12 +981,22 @@ struct GPUShader *EEVEE_shaders_probe_filter_visibility_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_fill_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void);
struct GPUShader *EEVEE_shaders_default_studiolight_sh_get(void);
+struct GPUShader *EEVEE_shaders_default_background_sh_get(void);
struct GPUShader *EEVEE_shaders_background_studiolight_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void);
+struct GPUShader *EEVEE_shaders_update_noise_sh_get(void);
struct GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void);
struct GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects);
+struct bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma);
+struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo);
+Material *EEVEE_material_default_diffuse_get(void);
+Material *EEVEE_material_default_glossy_get(void);
+Material *EEVEE_material_default_error_get(void);
+struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options);
+struct GPUMaterial *EEVEE_material_get(
+ EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options);
void EEVEE_shaders_free(void);
/* eevee_lightprobes.c */
@@ -1105,13 +1103,9 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata,
uint tot_samples);
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile);
-void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile,
- struct GPUTexture *sss_tex_profile);
+ Material *ma,
+ DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat);
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 076738dcbdf..89a5ad2198a 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -151,7 +151,7 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
* `EEVEE_effects_init` needs to go second for TAA. */
EEVEE_renderpasses_init(vedata);
EEVEE_effects_init(sldata, vedata, ob_camera_eval, false);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
@@ -463,7 +463,7 @@ static void eevee_render_draw_background(EEVEE_Data *vedata)
GPU_ATTACHMENT_NONE});
GPU_framebuffer_bind(fbl->main_fb);
- DRW_draw_pass(psl->background_pass);
+ DRW_draw_pass(psl->background_ps);
GPU_framebuffer_ensure_config(&fbl->main_fb,
{GPU_ATTACHMENT_LEAVE,
@@ -556,7 +556,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
EEVEE_update_noise(psl, fbl, r);
EEVEE_temporal_sampling_matrices_calc(stl->effects, r);
EEVEE_volumes_set_jitter(sldata, stl->effects->taa_current_sample - 1);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
/* Refresh Probes
* Shadows needs to be updated for correct probes */
@@ -578,8 +578,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
GPU_framebuffer_bind(fbl->main_fb);
GPU_framebuffer_clear_color_depth_stencil(fbl->main_fb, clear_col, clear_depth, clear_stencil);
/* Depth prepass */
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
/* Create minmax texture */
EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1);
EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1);
@@ -587,16 +586,15 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
/* Shading pass */
eevee_render_draw_background(vedata);
GPU_framebuffer_bind(fbl->main_fb);
- EEVEE_materials_draw_opaque(sldata, psl);
+ DRW_draw_pass(psl->material_ps);
EEVEE_subsurface_data_render(sldata, vedata);
/* Effects pre-transparency */
EEVEE_subsurface_compute(sldata, vedata);
EEVEE_reflection_compute(sldata, vedata);
EEVEE_refraction_compute(sldata, vedata);
/* Opaque refraction */
- DRW_draw_pass(psl->refract_depth_pass);
- DRW_draw_pass(psl->refract_depth_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->depth_refract_ps);
+ DRW_draw_pass(psl->material_refract_ps);
/* Result NORMAL */
eevee_render_result_normal(rl, viewname, rect, vedata, sldata);
/* Volumetrics Resolve Opaque */
diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c
index 9112e14dcf5..9a47ca19e7b 100644
--- a/source/blender/draw/engines/eevee/eevee_renderpasses.c
+++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c
@@ -201,8 +201,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
grp, "inputSecondLightBuffer", &g_data->renderpass_light_input);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "currentSample", &g_data->renderpass_current_sample, 1);
DRW_shgroup_uniform_int(grp, "renderpassType", &g_data->renderpass_type, 1);
DRW_shgroup_uniform_int(grp, "postProcessType", &g_data->renderpass_postprocess, 1);
@@ -216,7 +215,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
}
}
-/* Postprocess data to construct a specific renderpass
+/* Post-process data to construct a specific render-pass
*
* This method will create a shading group to perform the post-processing for the given
* `renderpass_type`. The post-processing will be done and the result will be stored in the
@@ -224,8 +223,8 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
*
* Only invoke this function for passes that need post-processing.
*
- * After invoking this function the active framebuffer is set to `vedata->fbl->renderpass_fb`. */
-void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
+ * After invoking this function the active frame-buffer is set to `vedata->fbl->renderpass_fb`. */
+void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata),
EEVEE_Data *vedata,
eViewLayerEEVEEPassType renderpass_type)
{
@@ -276,22 +275,30 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
g_data->renderpass_input = txl->shadow_accum;
break;
}
- case EEVEE_RENDER_PASS_DIFFUSE_COLOR:
- case EEVEE_RENDER_PASS_SPECULAR_COLOR:
- case EEVEE_RENDER_PASS_ENVIRONMENT:
+ case EEVEE_RENDER_PASS_DIFFUSE_COLOR: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->diff_color_accum;
+ break;
+ }
+ case EEVEE_RENDER_PASS_SPECULAR_COLOR: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->spec_color_accum;
+ break;
+ }
+ case EEVEE_RENDER_PASS_ENVIRONMENT: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->env_accum;
+ break;
+ }
case EEVEE_RENDER_PASS_EMIT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
+ g_data->renderpass_input = txl->emit_accum;
break;
}
case EEVEE_RENDER_PASS_SPECULAR_LIGHT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- int renderpass_index_color = EEVEE_material_output_color_pass_index_get(
- sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
- g_data->renderpass_col_input = txl->material_accum[renderpass_index_color];
+ g_data->renderpass_input = txl->spec_light_accum;
+ g_data->renderpass_col_input = txl->spec_color_accum;
if ((stl->effects->enabled_effects & EFFECT_SSR) != 0) {
g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS;
g_data->renderpass_light_input = txl->ssr_accum;
@@ -303,11 +310,8 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
}
case EEVEE_RENDER_PASS_DIFFUSE_LIGHT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- int renderpass_index_color = EEVEE_material_output_color_pass_index_get(
- sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
- g_data->renderpass_col_input = txl->material_accum[renderpass_index_color];
+ g_data->renderpass_input = txl->diff_light_accum;
+ g_data->renderpass_col_input = txl->diff_color_accum;
if ((stl->effects->enabled_effects & EFFECT_SSS) != 0) {
g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS;
g_data->renderpass_light_input = txl->sss_accum;
@@ -343,10 +347,6 @@ void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata,
if ((render_pass & EEVEE_RENDER_PASS_MIST) != 0) {
EEVEE_mist_output_accumulate(sldata, vedata);
}
- if ((render_pass & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) != 0 &&
- (effects->enabled_effects & EFFECT_SSS) != 0) {
- EEVEE_subsurface_output_accumulate(sldata, vedata);
- }
if ((render_pass & EEVEE_RENDER_PASS_AO) != 0) {
EEVEE_occlusion_output_accumulate(sldata, vedata);
}
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index 2e467fe8535..cece67334c5 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -237,8 +237,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
if (!effects->reflection_trace_full) {
DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1);
}
@@ -259,8 +258,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1);
if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c
index 50b7c5c5f97..09e74c84948 100644
--- a/source/blender/draw/engines/eevee/eevee_shaders.c
+++ b/source/blender/draw/engines/eevee/eevee_shaders.c
@@ -22,12 +22,20 @@
#include "DRW_render.h"
+#include "BKE_lib_id.h"
+#include "BKE_node.h"
+
+#include "BLI_dynstr.h"
#include "BLI_string_utils.h"
#include "MEM_guardedalloc.h"
+#include "GPU_material.h"
#include "GPU_shader.h"
+#include "NOD_shader.h"
+
+#include "eevee_engine.h"
#include "eevee_private.h"
static const char *filter_defines = "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n"
@@ -61,6 +69,38 @@ static struct {
struct GPUShader *taa_resolve_sh;
struct GPUShader *taa_resolve_reproject_sh;
+ /* General purpose Shaders. */
+ struct GPUShader *default_background;
+ struct GPUShader *update_noise_sh;
+
+ /* Shader strings */
+ char *frag_shader_lib;
+ char *vert_shader_str;
+ char *vert_shadow_shader_str;
+ char *vert_background_shader_str;
+ char *vert_volume_shader_str;
+ char *geom_volume_shader_str;
+ char *volume_shader_lib;
+
+ /* LookDev Materials */
+ Material *glossy_mat;
+ Material *diffuse_mat;
+
+ Material *error_mat;
+
+ /* Default Material */
+ struct {
+ bNodeTree *ntree;
+ bNodeSocketValueRGBA *color_socket;
+ bNodeSocketValueFloat *metallic_socket;
+ bNodeSocketValueFloat *roughness_socket;
+ bNodeSocketValueFloat *specular_socket;
+ } surface;
+
+ struct {
+ bNodeTree *ntree;
+ bNodeSocketValueRGBA *color_socket;
+ } world;
} e_data = {NULL}; /* Engine data */
extern char datatoc_bsdf_common_lib_glsl[];
@@ -68,27 +108,42 @@ extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
+extern char datatoc_ambient_occlusion_lib_glsl[];
extern char datatoc_background_vert_glsl[];
+extern char datatoc_common_hair_lib_glsl[];
+extern char datatoc_cubemap_lib_glsl[];
extern char datatoc_default_world_frag_glsl[];
-extern char datatoc_lightprobe_geom_glsl[];
-extern char datatoc_lightprobe_vert_glsl[];
+extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_lightprobe_cube_display_frag_glsl[];
extern char datatoc_lightprobe_cube_display_vert_glsl[];
extern char datatoc_lightprobe_filter_diffuse_frag_glsl[];
extern char datatoc_lightprobe_filter_glossy_frag_glsl[];
extern char datatoc_lightprobe_filter_visibility_frag_glsl[];
+extern char datatoc_lightprobe_geom_glsl[];
extern char datatoc_lightprobe_grid_display_frag_glsl[];
extern char datatoc_lightprobe_grid_display_vert_glsl[];
extern char datatoc_lightprobe_grid_fill_frag_glsl[];
+extern char datatoc_lightprobe_lib_glsl[];
extern char datatoc_lightprobe_planar_display_frag_glsl[];
extern char datatoc_lightprobe_planar_display_vert_glsl[];
extern char datatoc_lightprobe_planar_downsample_frag_glsl[];
extern char datatoc_lightprobe_planar_downsample_geom_glsl[];
extern char datatoc_lightprobe_planar_downsample_vert_glsl[];
-extern char datatoc_irradiance_lib_glsl[];
-extern char datatoc_lightprobe_lib_glsl[];
+extern char datatoc_lightprobe_vert_glsl[];
+extern char datatoc_lights_lib_glsl[];
+extern char datatoc_lit_surface_frag_glsl[];
+extern char datatoc_lit_surface_vert_glsl[];
+extern char datatoc_ltc_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
-extern char datatoc_cubemap_lib_glsl[];
+extern char datatoc_prepass_frag_glsl[];
+extern char datatoc_raytrace_lib_glsl[];
+extern char datatoc_shadow_vert_glsl[];
+extern char datatoc_ssr_lib_glsl[];
+extern char datatoc_update_noise_frag_glsl[];
+extern char datatoc_volumetric_frag_glsl[];
+extern char datatoc_volumetric_geom_glsl[];
+extern char datatoc_volumetric_lib_glsl[];
+extern char datatoc_volumetric_vert_glsl[];
/* Velocity Resolve */
extern char datatoc_effect_velocity_resolve_frag_glsl[];
@@ -150,6 +205,64 @@ void EEVEE_shaders_lightprobe_shaders_init(void)
NULL);
}
+void EEVEE_shaders_material_shaders_init(void)
+{
+ e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_bsdf_sampling_lib_glsl,
+ datatoc_ambient_occlusion_lib_glsl,
+ datatoc_raytrace_lib_glsl,
+ datatoc_ssr_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_cubemap_lib_glsl,
+ datatoc_irradiance_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_ltc_lib_glsl,
+ datatoc_lights_lib_glsl,
+ /* Add one for each Closure */
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_volumetric_lib_glsl);
+
+ e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_ambient_occlusion_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_cubemap_lib_glsl,
+ datatoc_irradiance_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_ltc_lib_glsl,
+ datatoc_lights_lib_glsl,
+ datatoc_volumetric_lib_glsl,
+ datatoc_volumetric_frag_glsl);
+
+ e_data.vert_shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl);
+
+ e_data.vert_shadow_shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl);
+
+ e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_background_vert_glsl);
+
+ e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_volumetric_vert_glsl);
+
+ e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_volumetric_geom_glsl);
+}
+
GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void)
{
return e_data.probe_filter_glossy_sh;
@@ -292,6 +405,26 @@ GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void)
return e_data.velocity_resolve_sh;
}
+GPUShader *EEVEE_shaders_default_background_sh_get(void)
+{
+ if (e_data.default_background == NULL) {
+ e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
+ NULL,
+ datatoc_default_world_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
+ }
+ return e_data.default_background;
+}
+
+GPUShader *EEVEE_shaders_update_noise_sh_get(void)
+{
+ if (e_data.update_noise_sh == NULL) {
+ e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL);
+ }
+ return e_data.update_noise_sh;
+}
+
GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects)
{
GPUShader **sh;
@@ -316,8 +449,330 @@ GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects)
return *sh;
}
+Material *EEVEE_material_default_diffuse_get(void)
+{
+ if (!e_data.diffuse_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default diffuse");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_DIFFUSE);
+ bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 0.8f);
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "BSDF"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.diffuse_mat = ma;
+ }
+ return e_data.diffuse_mat;
+}
+
+Material *EEVEE_material_default_glossy_get(void)
+{
+ if (!e_data.glossy_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_GLOSSY);
+ bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 1.0f);
+ bNodeSocket *roughness = nodeFindSocket(bsdf, SOCK_IN, "Roughness");
+ ((bNodeSocketValueFloat *)roughness->default_value)->value = 0.0f;
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "BSDF"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.glossy_mat = ma;
+ }
+ return e_data.glossy_mat;
+}
+
+Material *EEVEE_material_default_error_get(void)
+{
+ if (!e_data.error_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ /* Use emission and output material to be compatible with both World and Material. */
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION);
+ bNodeSocket *color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl3(((bNodeSocketValueRGBA *)color->default_value)->value, 1.0f, 0.0f, 1.0f);
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "Emission"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.error_mat = ma;
+ }
+ return e_data.error_mat;
+}
+
+/* Configure a default nodetree with the given material. */
+struct bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma)
+{
+ /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */
+ if (!e_data.surface.ntree) {
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_PRINCIPLED);
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+ bNodeSocket *bsdf_out = nodeFindSocket(bsdf, SOCK_OUT, "BSDF");
+ bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface");
+ nodeAddLink(ntree, bsdf, bsdf_out, output, output_in);
+ nodeSetActive(ntree, output);
+
+ e_data.surface.color_socket = nodeFindSocket(bsdf, SOCK_IN, "Base Color")->default_value;
+ e_data.surface.metallic_socket = nodeFindSocket(bsdf, SOCK_IN, "Metallic")->default_value;
+ e_data.surface.roughness_socket = nodeFindSocket(bsdf, SOCK_IN, "Roughness")->default_value;
+ e_data.surface.specular_socket = nodeFindSocket(bsdf, SOCK_IN, "Specular")->default_value;
+ e_data.surface.ntree = ntree;
+ }
+ /* Update */
+ copy_v3_fl3(e_data.surface.color_socket->value, ma->r, ma->g, ma->b);
+ e_data.surface.metallic_socket->value = ma->metallic;
+ e_data.surface.roughness_socket->value = ma->roughness;
+ e_data.surface.specular_socket->value = ma->spec;
+
+ return e_data.surface.ntree;
+}
+
+/* Configure a default nodetree with the given world. */
+struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo)
+{
+ /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */
+ if (!e_data.world.ntree) {
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ bNode *bg = nodeAddStaticNode(NULL, ntree, SH_NODE_BACKGROUND);
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_WORLD);
+ bNodeSocket *bg_out = nodeFindSocket(bg, SOCK_OUT, "Background");
+ bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface");
+ nodeAddLink(ntree, bg, bg_out, output, output_in);
+ nodeSetActive(ntree, output);
+
+ e_data.world.color_socket = nodeFindSocket(bg, SOCK_IN, "Color")->default_value;
+ e_data.world.ntree = ntree;
+ }
+
+ copy_v3_fl3(e_data.world.color_socket->value, wo->horr, wo->horg, wo->horb);
+
+ return e_data.world.ntree;
+}
+
+static char *eevee_get_defines(int options)
+{
+ char *str = NULL;
+
+ DynStr *ds = BLI_dynstr_new();
+ BLI_dynstr_append(ds, SHADER_DEFINES);
+
+ if ((options & VAR_WORLD_BACKGROUND) != 0) {
+ BLI_dynstr_append(ds, "#define WORLD_BACKGROUND\n");
+ }
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ BLI_dynstr_append(ds, "#define VOLUMETRICS\n");
+ }
+ if ((options & VAR_MAT_MESH) != 0) {
+ BLI_dynstr_append(ds, "#define MESH_SHADER\n");
+ }
+ if ((options & VAR_MAT_DEPTH) != 0) {
+ BLI_dynstr_append(ds, "#define DEPTH_SHADER\n");
+ }
+ if ((options & VAR_MAT_HAIR) != 0) {
+ BLI_dynstr_append(ds, "#define HAIR_SHADER\n");
+ }
+ if ((options & (VAR_MAT_PROBE | VAR_WORLD_PROBE)) != 0) {
+ BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n");
+ }
+ if ((options & VAR_MAT_HASH) != 0) {
+ BLI_dynstr_append(ds, "#define USE_ALPHA_HASH\n");
+ }
+ if ((options & VAR_MAT_BLEND) != 0) {
+ BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND\n");
+ }
+ if ((options & VAR_MAT_REFRACT) != 0) {
+ BLI_dynstr_append(ds, "#define USE_REFRACTION\n");
+ }
+ if ((options & VAR_MAT_LOOKDEV) != 0) {
+ BLI_dynstr_append(ds, "#define LOOKDEV\n");
+ }
+ if ((options & VAR_MAT_HOLDOUT) != 0) {
+ BLI_dynstr_append(ds, "#define HOLDOUT\n");
+ }
+
+ str = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return str;
+}
+
+static char *eevee_get_vert(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.vert_volume_shader_str);
+ }
+ else if ((options & (VAR_WORLD_PROBE | VAR_WORLD_BACKGROUND)) != 0) {
+ str = BLI_strdup(e_data.vert_background_shader_str);
+ }
+ else {
+ str = BLI_strdup(e_data.vert_shader_str);
+ }
+
+ return str;
+}
+
+static char *eevee_get_geom(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.geom_volume_shader_str);
+ }
+
+ return str;
+}
+
+static char *eevee_get_frag(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.volume_shader_lib);
+ }
+ else if ((options & VAR_MAT_DEPTH) != 0) {
+ str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
+ }
+ else {
+ str = BLI_strdup(e_data.frag_shader_lib);
+ }
+
+ return str;
+}
+
+static struct GPUMaterial *eevee_material_get_ex(
+ struct Scene *scene, Material *ma, World *wo, int options, bool deferred)
+{
+ BLI_assert(ma || wo);
+ const bool is_volume = (options & VAR_MAT_VOLUME) != 0;
+ const bool is_default = (options & VAR_DEFAULT) != 0;
+ const void *engine = &DRW_engine_viewport_eevee_type;
+
+ GPUMaterial *mat = NULL;
+
+ if (ma) {
+ mat = DRW_shader_find_from_material(ma, engine, options, deferred);
+ }
+ else {
+ mat = DRW_shader_find_from_world(wo, engine, options, deferred);
+ }
+
+ if (mat) {
+ return mat;
+ }
+
+ char *defines = eevee_get_defines(options);
+ char *vert = eevee_get_vert(options);
+ char *geom = eevee_get_geom(options);
+ char *frag = eevee_get_frag(options);
+
+ if (ma) {
+ bNodeTree *ntree = !is_default ? ma->nodetree : EEVEE_shader_default_surface_nodetree(ma);
+ mat = DRW_shader_create_from_material(
+ scene, ma, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred);
+ }
+ else {
+ bNodeTree *ntree = !is_default ? wo->nodetree : EEVEE_shader_default_world_nodetree(wo);
+ mat = DRW_shader_create_from_world(
+ scene, wo, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred);
+ }
+
+ MEM_SAFE_FREE(defines);
+ MEM_SAFE_FREE(vert);
+ MEM_SAFE_FREE(geom);
+ MEM_SAFE_FREE(frag);
+
+ return mat;
+}
+
+/* Note: Compilation is not deferred. */
+struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options)
+{
+ Material *def_ma = (ma && (options & VAR_MAT_VOLUME)) ? BKE_material_default_volume() :
+ BKE_material_default_surface();
+ BLI_assert(def_ma->use_nodes && def_ma->nodetree);
+
+ return eevee_material_get_ex(scene, def_ma, NULL, options, false);
+}
+
+struct GPUMaterial *EEVEE_material_get(
+ EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options)
+{
+ if ((ma && (!ma->use_nodes || !ma->nodetree)) || (wo && (!wo->use_nodes || !wo->nodetree))) {
+ options |= VAR_DEFAULT;
+ }
+
+ /* Meh, implicit option. World probe cannot be deferred because they need
+ * to be rendered immediately. */
+ const bool deferred = (options & VAR_WORLD_PROBE) == 0;
+
+ GPUMaterial *mat = eevee_material_get_ex(scene, ma, wo, options, deferred);
+
+ int status = GPU_material_status(mat);
+ switch (status) {
+ case GPU_MAT_SUCCESS:
+ break;
+ case GPU_MAT_QUEUED:
+ vedata->stl->g_data->queued_shaders_count++;
+ mat = EEVEE_material_default_get(scene, ma, options);
+ break;
+ case GPU_MAT_FAILED:
+ default:
+ ma = EEVEE_material_default_error_get();
+ mat = eevee_material_get_ex(scene, ma, NULL, options, false);
+ break;
+ }
+ /* Returned material should be ready to be drawn. */
+ BLI_assert(GPU_material_status(mat) == GPU_MAT_SUCCESS);
+ return mat;
+}
+
void EEVEE_shaders_free(void)
{
+ MEM_SAFE_FREE(e_data.frag_shader_lib);
+ MEM_SAFE_FREE(e_data.vert_shader_str);
+ MEM_SAFE_FREE(e_data.vert_shadow_shader_str);
+ MEM_SAFE_FREE(e_data.vert_background_shader_str);
+ MEM_SAFE_FREE(e_data.vert_volume_shader_str);
+ MEM_SAFE_FREE(e_data.geom_volume_shader_str);
+ MEM_SAFE_FREE(e_data.volume_shader_lib);
+ DRW_SHADER_FREE_SAFE(e_data.default_background);
+ DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_default_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh);
@@ -332,4 +787,27 @@ void EEVEE_shaders_free(void)
DRW_SHADER_FREE_SAFE(e_data.velocity_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.taa_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.taa_resolve_reproject_sh);
+
+ if (e_data.glossy_mat) {
+ BKE_id_free(NULL, e_data.glossy_mat);
+ e_data.glossy_mat = NULL;
+ }
+ if (e_data.diffuse_mat) {
+ BKE_id_free(NULL, e_data.diffuse_mat);
+ e_data.diffuse_mat = NULL;
+ }
+ if (e_data.error_mat) {
+ BKE_id_free(NULL, e_data.error_mat);
+ e_data.error_mat = NULL;
+ }
+ if (e_data.surface.ntree) {
+ ntreeFreeEmbeddedTree(e_data.surface.ntree);
+ MEM_freeN(e_data.surface.ntree);
+ e_data.surface.ntree = NULL;
+ }
+ if (e_data.world.ntree) {
+ ntreeFreeEmbeddedTree(e_data.world.ntree);
+ MEM_freeN(e_data.world.ntree);
+ e_data.world.ntree = NULL;
+ }
}
diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c
index fb338d85fde..84c50a22ae6 100644
--- a/source/blender/draw/engines/eevee/eevee_shadows.c
+++ b/source/blender/draw/engines/eevee/eevee_shadows.c
@@ -159,47 +159,6 @@ void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
}
-/* Add a shadow caster to the shadowpasses */
-void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_StorageList *stl,
- struct GPUBatch *geom,
- Object *ob)
-{
- DRW_shgroup_call(stl->g_data->shadow_shgrp, geom, ob);
-}
-
-void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata,
- EEVEE_PassList *psl,
- struct GPUMaterial *gpumat,
- struct GPUBatch *geom,
- struct Object *ob,
- const float *alpha_threshold)
-{
- /* TODO / PERF : reuse the same shading group for objects with the same material */
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->shadow_pass);
-
- if (grp == NULL) {
- return;
- }
-
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
-
- if (alpha_threshold != NULL) {
- DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
- }
-
- DRW_shgroup_call(grp, geom, ob);
-}
-
/* Make that object update shadow casting lights inside its influence bounding box. */
void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob)
{
@@ -470,8 +429,7 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 3f4008eb8b9..7674148f76a 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -29,7 +29,9 @@
#include "DEG_depsgraph_query.h"
#include "GPU_extensions.h"
+#include "GPU_material.h"
#include "GPU_texture.h"
+
#include "eevee_private.h"
static struct {
@@ -83,6 +85,7 @@ void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
+ effects->sss_surface_count = 0;
common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
}
@@ -145,7 +148,7 @@ void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
else {
GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb);
- txl->sss_accum = NULL;
+ DRW_TEXTURE_FREE_SAFE(txl->sss_accum);
}
}
else {
@@ -154,11 +157,11 @@ void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_resolve_fb);
GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb);
+ DRW_TEXTURE_FREE_SAFE(txl->sss_accum);
effects->sss_stencil = NULL;
effects->sss_blur = NULL;
effects->sss_irradiance = NULL;
effects->sss_radius = NULL;
- txl->sss_accum = NULL;
}
}
@@ -221,70 +224,77 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile)
+ Material *ma,
+ DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat)
{
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth;
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
-
- grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur);
- DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
-}
+ struct GPUTexture *sss_tex_profile = NULL;
+ struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(
+ gpumat, stl->effects->sss_sample_count, &sss_tex_profile);
-void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile,
- GPUTexture *sss_tex_profile)
-{
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_EffectsInfo *effects = stl->effects;
- struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
- GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth;
+ if (!sss_profile) {
+ BLI_assert(0 && "SSS pass requested but no SSS data was found");
+ return;
+ }
+
+ /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
+ if (effects->sss_surface_count >= 254) {
+ /* TODO : display message. */
+ printf("Error: Too many different Subsurface shader in the scene.\n");
+ return;
+ }
+
+ int sss_id = ++(effects->sss_surface_count);
+ /* Make main pass output stencil mask. */
+ DRW_shgroup_stencil_mask(shgrp, sss_id);
+
+ {
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_translucency_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile);
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool);
- DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
+ if (ma->blend_flag & MA_BL_TRANSLUCENCY) {
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_translucency_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
}
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
@@ -310,8 +320,7 @@ void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)});
GPU_framebuffer_bind(fbl->main_fb);
- DRW_draw_pass(psl->sss_pass);
- DRW_draw_pass(psl->sss_pass_cull);
+ DRW_draw_pass(psl->material_sss_ps);
/* Restore */
GPU_framebuffer_ensure_config(&fbl->main_fb,
@@ -350,23 +359,15 @@ void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
if (!DRW_pass_is_empty(psl->sss_translucency_ps)) {
/* We sample the shadow-maps using normal sampler. We need to disable Comparison mode.
* TODO(fclem) avoid this by using sampler objects.*/
- GPU_texture_bind(sldata->shadow_cube_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cube_pool, false);
- GPU_texture_unbind(sldata->shadow_cube_pool);
- GPU_texture_bind(sldata->shadow_cascade_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cascade_pool, false);
- GPU_texture_unbind(sldata->shadow_cascade_pool);
GPU_framebuffer_bind(fbl->sss_translucency_fb);
DRW_draw_pass(psl->sss_translucency_ps);
/* Reset original state. */
- GPU_texture_bind(sldata->shadow_cube_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cube_pool, true);
- GPU_texture_unbind(sldata->shadow_cube_pool);
- GPU_texture_bind(sldata->shadow_cascade_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cascade_pool, true);
- GPU_texture_unbind(sldata->shadow_cascade_pool);
}
/* 1. horizontal pass */
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index b70d872c4af..d57048f2c4e 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -292,8 +292,7 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data
DRW_shgroup_uniform_texture_ref(grp, "colorHistoryBuffer", &txl->taa_history);
DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
if (effects->enabled_effects & EFFECT_TAA_REPROJECT) {
// DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 83bd4fcf8d2..90860e94270 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -355,7 +355,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
struct World *wo = scene->world;
if (wo != NULL && wo->use_nodes && wo->nodetree &&
!LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
- struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
+ struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_MAT_VOLUME);
if (GPU_material_has_volume_output(mat)) {
grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps);
@@ -369,8 +369,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
/* Fix principle volumetric not working with world materials. */
ListBase gpu_grids = GPU_material_volume_grids(mat);
@@ -388,8 +387,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* If no world or volume material is present just clear the buffer with this drawcall */
grp = DRW_shgroup_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
}
@@ -590,12 +588,10 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
return;
}
- struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
+ int mat_options = VAR_MAT_VOLUME | VAR_MAT_MESH;
+ struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
eGPUMaterialStatus status = GPU_material_status(mat);
- if (status == GPU_MAT_QUEUED) {
- vedata->stl->g_data->queued_shaders_count++;
- }
/* If shader failed to compile or is currently compiling. */
if (status != GPU_MAT_SUCCESS) {
return;
@@ -609,8 +605,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
@@ -661,8 +656,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
@@ -671,8 +665,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmit);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(
grp, NULL, USE_VOLUME_OPTI ? 1 : common_data->vol_tex_size[2]);
@@ -683,8 +676,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
@@ -775,12 +767,8 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* We sample the shadow-maps using shadow sampler. We need to enable Comparison mode.
* TODO(fclem) avoid this by using sampler objects.*/
- GPU_texture_bind(sldata->shadow_cube_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cube_pool, true);
- GPU_texture_unbind(sldata->shadow_cube_pool);
- GPU_texture_bind(sldata->shadow_cascade_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cascade_pool, true);
- GPU_texture_unbind(sldata->shadow_cascade_pool);
GPU_framebuffer_bind(fbl->volumetric_fb);
DRW_draw_pass(psl->volumetric_world_ps);
@@ -920,8 +908,7 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
}
else {
/* There is no volumetrics in the scene. Use a shader to fill the accum textures with a default
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 8662c0ecb6a..57b16418696 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -6,13 +6,9 @@
#if defined(MESH_SHADER)
# if !defined(USE_ALPHA_HASH)
-# if !defined(USE_ALPHA_CLIP)
-# if !defined(SHADOW_SHADER)
-# if !defined(USE_MULTIPLY)
-# if !defined(USE_ALPHA_BLEND)
-# define ENABLE_DEFERED_AO
-# endif
-# endif
+# if !defined(DEPTH_SHADER)
+# if !defined(USE_ALPHA_BLEND)
+# define ENABLE_DEFERED_AO
# endif
# endif
# endif
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index c3518198805..402d306df45 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -928,7 +928,7 @@ Closure closure_emission(vec3 rgb)
/* Breaking this across multiple lines causes issues for some older GLSL compilers. */
/* clang-format off */
-# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER)
+# if defined(MESH_SHADER) && !defined(DEPTH_SHADER)
/* clang-format on */
# ifndef USE_ALPHA_BLEND
layout(location = 0) out vec4 outRadiance;
@@ -1001,6 +1001,10 @@ void main()
outRadiance.rgb += cl.sss_irradiance.rgb * cl.sss_albedo.rgb * fac;
# endif
+# ifdef LOOKDEV
+ gl_FragDepth = 0.0;
+# endif
+
# ifndef USE_ALPHA_BLEND
float alpha_div = 1.0 / max(1e-8, alpha);
outRadiance.rgb *= alpha_div;
@@ -1011,6 +1015,6 @@ void main()
# endif
}
-# endif /* MESH_SHADER && !SHADOW_SHADER */
+# endif /* MESH_SHADER */
#endif /* VOLUMETRICS */
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
index 5277bfa32bb..d56890769a7 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
@@ -1,6 +1,4 @@
-uniform mat4 ProjectionMatrix;
-
uniform sampler2D colorBuffer;
uniform sampler2D depthBuffer;
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index 8c2619650b9..bc7879763c3 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -177,7 +177,7 @@ void CLOSURE_NAME(vec3 N
out_refr = vec3(0.0);
#endif
-#if defined(SHADOW_SHADER) || defined(WORLD_BACKGROUND)
+#if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND)
/* This makes shader resources become unused and avoid issues with samplers. (see T59747) */
return;
#else
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
index cf20b3ff5b9..1b94fc2bee1 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
@@ -4,11 +4,12 @@ in vec3 pos;
in vec3 nor;
#endif
+#ifdef MESH_SHADER
out vec3 worldPosition;
out vec3 viewPosition;
-
out vec3 worldNormal;
out vec3 viewNormal;
+#endif
#ifdef HAIR_SHADER
out vec3 hairTangent;
@@ -41,22 +42,28 @@ void main()
hairThickness,
hairThickTime);
worldNormal = cross(hairTangent, binor);
- worldPosition = pos;
+ vec3 world_pos = pos;
#else
- worldPosition = point_object_to_world(pos);
- worldNormal = normalize(normal_object_to_world(nor));
+ vec3 world_pos = point_object_to_world(pos);
#endif
- /* No need to normalize since this is just a rotation. */
- viewNormal = normal_world_to_view(worldNormal);
+ gl_Position = point_world_to_ndc(world_pos);
+ /* Used for planar reflections */
+ gl_ClipDistance[0] = dot(vec4(world_pos, 1.0), clipPlanes[0]);
+
+#ifdef MESH_SHADER
+ worldPosition = world_pos;
viewPosition = point_world_to_view(worldPosition);
- gl_Position = point_world_to_ndc(worldPosition);
- /* Used for planar reflections */
- gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), clipPlanes[0]);
+# ifndef HAIR_SHADER
+ worldNormal = normalize(normal_object_to_world(nor));
+# endif
-#ifdef USE_ATTR
+ /* No need to normalize since this is just a rotation. */
+ viewNormal = normal_world_to_view(worldNormal);
+# ifdef USE_ATTR
pass_attr(pos);
+# endif
#endif
}
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
index b49dbfceba2..9acd8f998f6 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
@@ -45,26 +45,22 @@ float hashed_alpha_threshold(vec3 co)
/* Find our final, uniformly distributed alpha threshold. */
float threshold = (x < one_a) ? ((x < a) ? cases.x : cases.y) : cases.z;
+ /* Jitter the threshold for TAA accumulation. */
+ threshold = fract(threshold + alphaHashOffset);
+
/* Avoids threshold == 0. */
threshold = clamp(threshold, 1.0e-6, 1.0);
- /* Jitter the threshold for TAA accumulation. */
- return fract(threshold + alphaHashOffset);
+ return threshold;
}
#endif
-#ifdef USE_ALPHA_CLIP
-uniform float alphaThreshold;
-#endif
+#define NODETREE_EXEC
void main()
{
- /* For now do nothing.
- * In the future, output object motion blur. */
-
-#if defined(USE_ALPHA_HASH) || defined(USE_ALPHA_CLIP)
-# define NODETREE_EXEC
+#if defined(USE_ALPHA_HASH)
Closure cl = nodetree_exec();
@@ -75,11 +71,6 @@ void main()
if (opacity < hashed_alpha_threshold(worldPosition)) {
discard;
}
-# elif defined(USE_ALPHA_CLIP)
- /* Alpha clip */
- if (opacity <= alphaThreshold) {
- discard;
- }
# endif
#endif
}
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index 6e636e4dc93..2f448b784ed 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -44,6 +44,11 @@
#define EXTERNAL_ENGINE "BLENDER_EXTERNAL"
+extern char datatoc_depth_frag_glsl[];
+extern char datatoc_depth_vert_glsl[];
+
+extern char datatoc_common_view_lib_glsl[];
+
/* *********** LISTS *********** */
/* GPUViewport.storage
@@ -106,7 +111,16 @@ static void external_engine_init(void *vedata)
/* Depth prepass */
if (!e_data.depth_sh) {
- e_data.depth_sh = DRW_shader_create_3d_depth_only(GPU_SHADER_CFG_DEFAULT);
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[GPU_SHADER_CFG_DEFAULT];
+
+ e_data.depth_sh = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_depth_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, NULL},
+ });
}
if (!stl->g_data) {
@@ -277,7 +291,7 @@ static void external_draw_scene(void *vedata)
static void external_engine_free(void)
{
- /* All shaders are builtin. */
+ DRW_SHADER_FREE_SAFE(e_data.depth_sh);
}
static const DrawEngineDataSize external_data_size = DRW_VIEWPORT_DATA_SIZE(EXTERNAL_Data);
diff --git a/source/blender/draw/engines/gpencil/gpencil_antialiasing.c b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
index 4dd5e3b2da1..8955240c549 100644
--- a/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
+++ b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
@@ -78,13 +78,8 @@ void GPENCIL_antialiasing_init(struct GPENCIL_Data *vedata)
false,
NULL);
- GPU_texture_bind(txl->smaa_search_tx, 0);
GPU_texture_filter_mode(txl->smaa_search_tx, true);
- GPU_texture_unbind(txl->smaa_search_tx);
-
- GPU_texture_bind(txl->smaa_area_tx, 0);
GPU_texture_filter_mode(txl->smaa_area_tx, true);
- GPU_texture_unbind(txl->smaa_area_tx);
}
{
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index 1344b649dff..2b811f1d52e 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -381,7 +381,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd,
struct GPUShader *sh = GPENCIL_shader_geometry_get();
DRWShadingGroup *grp = tgp_layer->base_shgrp = DRW_shgroup_create(sh, tgp_layer->geom_ps);
- DRW_shgroup_uniform_texture_persistent(grp, "gpSceneDepthTexture", depth_tex);
+ DRW_shgroup_uniform_texture(grp, "gpSceneDepthTexture", depth_tex);
DRW_shgroup_uniform_texture_ref(grp, "gpMaskTexture", mask_tex);
DRW_shgroup_uniform_vec3_copy(grp, "gpNormal", tgp_ob->plane_normal);
DRW_shgroup_uniform_bool_copy(grp, "strokeOrder3d", tgp_ob->is_drawmode3d);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 50e4e8d2ec4..495de7ef10b 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -91,6 +91,7 @@ void GPENCIL_engine_init(void *ved)
stl->pd->gp_object_pool = vldata->gp_object_pool;
stl->pd->gp_layer_pool = vldata->gp_layer_pool;
stl->pd->gp_vfx_pool = vldata->gp_vfx_pool;
+ stl->pd->view_layer = ctx->view_layer;
stl->pd->scene = ctx->scene;
stl->pd->v3d = ctx->v3d;
stl->pd->last_light_pool = NULL;
@@ -292,7 +293,7 @@ void GPENCIL_cache_init(void *ved)
grp = DRW_shgroup_create(sh, psl->merge_depth_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuf", &pd->depth_tx);
DRW_shgroup_uniform_bool(grp, "strokeOrder3d", &pd->is_stroke_order_3d, 1);
- DRW_shgroup_uniform_vec4(grp, "gpModelMatrix[0]", pd->object_bound_mat[0], 4);
+ DRW_shgroup_uniform_vec4(grp, "gpModelMatrix", pd->object_bound_mat[0], 4);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
{
@@ -468,7 +469,7 @@ static void gpencil_layer_cache_populate(bGPDlayer *gpl,
/* Iterator dependent uniforms. */
DRWShadingGroup *grp = iter->grp = tgp_layer->base_shgrp;
- DRW_shgroup_uniform_block_persistent(grp, "gpLightBlock", iter->ubo_lights);
+ DRW_shgroup_uniform_block(grp, "gpLightBlock", iter->ubo_lights);
DRW_shgroup_uniform_block(grp, "gpMaterialBlock", iter->ubo_mat);
DRW_shgroup_uniform_texture(grp, "gpFillTexture", iter->tex_fill);
DRW_shgroup_uniform_texture(grp, "gpStrokeTexture", iter->tex_stroke);
@@ -598,6 +599,7 @@ void GPENCIL_cache_populate(void *ved, Object *ob)
GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
GPENCIL_PrivateData *pd = vedata->stl->pd;
GPENCIL_TextureList *txl = vedata->txl;
+ const bool is_final_render = DRW_state_is_image_render();
/* object must be visible */
if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) {
@@ -617,7 +619,8 @@ void GPENCIL_cache_populate(void *ved, Object *ob)
bGPdata *gpd = (bGPdata *)ob->data;
bool do_onion = (!pd->is_render) ? pd->do_onion : (gpd->onion_flag & GP_ONION_GHOST_ALWAYS);
- BKE_gpencil_visible_stroke_iter(ob,
+ BKE_gpencil_visible_stroke_iter(is_final_render ? pd->view_layer : NULL,
+ ob,
gpencil_layer_cache_populate,
gpencil_stroke_cache_populate,
&iter,
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index f765dcf73de..cedd75af813 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -307,6 +307,8 @@ typedef struct GPENCIL_PrivateData {
float dof_params[2];
/* Used for DoF Setup. */
Object *camera;
+ /* Copy of draw_ctx->view_layer for convenience. */
+ struct ViewLayer *view_layer;
/* Copy of draw_ctx->scene for convenience. */
struct Scene *scene;
/* Copy of draw_ctx->vie3d for convenience. */
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
index fb5073b3dc7..1e75f6dd5bb 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -317,7 +317,7 @@ vec2 safe_normalize_len(vec2 v, out float len)
}
}
-float stroke_thickness_modulate(float thickness)
+float stroke_thickness_modulate(float thickness, out float opacity)
{
/* Modify stroke thickness by object and layer factors.-*/
thickness *= thicknessScale;
@@ -333,6 +333,11 @@ float stroke_thickness_modulate(float thickness)
/* World space point size. */
thickness *= thicknessWorldScale * ProjectionMatrix[1][1] * sizeViewport.y;
}
+ /* To avoid aliasing artifact, we clamp the line thickness and reduce its opacity. */
+ float min_thickness = gl_Position.w * 1.3;
+ opacity = smoothstep(0.0, gl_Position.w * 1.0, thickness);
+ thickness = max(min_thickness, thickness);
+
return thickness;
}
@@ -414,8 +419,9 @@ void stroke_vertex()
vec2 line = safe_normalize_len(ss2 - ss1, line_len);
vec2 line_adj = safe_normalize((use_curr) ? (ss1 - ss_adj) : (ss_adj - ss2));
+ float small_line_opacity;
float thickness = abs((use_curr) ? thickness1 : thickness2);
- thickness = stroke_thickness_modulate(thickness);
+ thickness = stroke_thickness_modulate(thickness, small_line_opacity);
finalUvs = vec2(x, y) * 0.5 + 0.5;
strokeHardeness = decode_hardness(use_curr ? hardness1 : hardness2);
@@ -505,7 +511,7 @@ void stroke_vertex()
vec4 stroke_col = MATERIAL(m).stroke_color;
float mix_tex = MATERIAL(m).stroke_texture_mix;
- color_output(stroke_col, vert_col, vert_strength, mix_tex);
+ color_output(stroke_col, vert_col, vert_strength * small_line_opacity, mix_tex);
matFlag = MATERIAL(m).flag & ~GP_FILL_FLAGS;
# endif
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index 624eef8fa47..95fd918f8c1 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -137,9 +137,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
pd->armature.do_pose_fade_geom = pd->armature.do_pose_xray &&
((draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) == 0) &&
draw_ctx->object_pose != NULL;
-
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ADD;
- DRW_PASS_CREATE(psl->armature_transp_ps, state | pd->clipping_state);
+ DRWState state;
if (pd->armature.do_pose_fade_geom) {
state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
@@ -163,17 +161,21 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
OVERLAY_InstanceFormats *formats = OVERLAY_shader_instance_formats_get();
OVERLAY_ArmatureCallBuffers *cb = &pd->armature_call_buffers[i];
- DRWPass **p_armature_ps = &psl->armature_ps[i];
cb->custom_shapes_ghash = BLI_ghash_ptr_new(__func__);
cb->custom_shapes_transp_ghash = BLI_ghash_ptr_new(__func__);
+ DRWPass **p_armature_ps = &psl->armature_ps[i];
DRWState infront_state = (DRW_state_is_select() && (i == 1)) ? DRW_STATE_IN_FRONT_SELECT : 0;
state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH;
DRW_PASS_CREATE(*p_armature_ps, state | pd->clipping_state | infront_state);
-
DRWPass *armature_ps = *p_armature_ps;
+ DRWPass **p_armature_trans_ps = &psl->armature_transp_ps[i];
+ state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ADD;
+ DRW_PASS_CREATE(*p_armature_trans_ps, state | pd->clipping_state);
+ DRWPass *armature_transp_ps = *p_armature_trans_ps;
+
#define BUF_INSTANCE DRW_shgroup_call_buffer_instance
#define BUF_LINE(grp, format) DRW_shgroup_call_buffer(grp, format, GPU_PRIM_LINES)
@@ -182,7 +184,7 @@ 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_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->point_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_point_get());
@@ -194,7 +196,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_shape(false);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->custom_solid = grp;
cb->box_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_box_get());
@@ -210,29 +212,29 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_sphere(true);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->point_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_point_wire_outline_get());
sh = OVERLAY_shader_armature_shape(true);
cb->custom_outline = grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->box_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_box_wire_get());
cb->octa_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_octahedral_wire_get());
sh = OVERLAY_shader_armature_shape_wire();
cb->custom_wire = grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
{
format = formats->instance_extra;
sh = OVERLAY_shader_armature_degrees_of_freedom();
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->dof_lines = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_lines_get());
- grp = DRW_shgroup_create(sh, psl->armature_transp_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ grp = DRW_shgroup_create(sh, armature_transp_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->dof_sphere = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_sphere_get());
}
{
@@ -240,7 +242,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_stick();
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->stick = BUF_INSTANCE(grp, format, DRW_cache_bone_stick_get());
}
{
@@ -249,7 +251,7 @@ 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_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ 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->envelope_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_solid_get());
@@ -264,14 +266,14 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_envelope(true);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->envelope_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_outline_get());
format = formats->instance_bone_envelope_distance;
sh = OVERLAY_shader_armature_envelope(false);
- grp = DRW_shgroup_create(sh, psl->armature_transp_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ grp = DRW_shgroup_create(sh, armature_transp_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "isDistance", true);
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);
cb->envelope_distance = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_solid_get());
@@ -281,7 +283,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_wire();
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->wire = BUF_LINE(grp, format);
}
}
@@ -2255,7 +2257,7 @@ void OVERLAY_armature_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
- DRW_draw_pass(psl->armature_transp_ps);
+ DRW_draw_pass(psl->armature_transp_ps[0]);
DRW_draw_pass(psl->armature_ps[0]);
}
@@ -2264,6 +2266,7 @@ void OVERLAY_armature_in_front_draw(OVERLAY_Data *vedata)
OVERLAY_PassList *psl = vedata->psl;
if (psl->armature_bone_select_ps == NULL || DRW_state_is_select()) {
+ DRW_draw_pass(psl->armature_transp_ps[1]);
DRW_draw_pass(psl->armature_ps[1]);
}
}
@@ -2285,6 +2288,7 @@ void OVERLAY_pose_draw(OVERLAY_Data *vedata)
GPU_framebuffer_clear_depth(fbl->overlay_line_in_front_fb, 1.0f);
}
+ DRW_draw_pass(psl->armature_transp_ps[1]);
DRW_draw_pass(psl->armature_ps[1]);
}
}
diff --git a/source/blender/draw/engines/overlay/overlay_edit_curve.c b/source/blender/draw/engines/overlay/overlay_edit_curve.c
index 6456d6868a5..9a79c78c996 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_curve.c
+++ b/source/blender/draw/engines/overlay/overlay_edit_curve.c
@@ -36,7 +36,8 @@ void OVERLAY_edit_curve_cache_init(OVERLAY_Data *vedata)
GPUShader *sh;
DRWState state;
- pd->edit_curve.show_handles = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0;
+ pd->edit_curve.show_handles = v3d->overlay.handle_display != CURVE_HANDLE_NONE;
+ pd->edit_curve.handle_display = v3d->overlay.handle_display;
pd->shdata.edit_curve_normal_length = v3d->overlay.normals_length;
/* Run Twice for in-front passes. */
@@ -62,11 +63,13 @@ void OVERLAY_edit_curve_cache_init(OVERLAY_Data *vedata)
pd->edit_curve_handle_grp = grp = DRW_shgroup_create(sh, psl->edit_curve_handle_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "showCurveHandles", pd->edit_curve.show_handles);
+ DRW_shgroup_uniform_int_copy(grp, "curveHandleDisplay", pd->edit_curve.handle_display);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
sh = OVERLAY_shader_edit_curve_point();
pd->edit_curve_points_grp = grp = DRW_shgroup_create(sh, psl->edit_curve_handle_ps);
DRW_shgroup_uniform_bool_copy(grp, "showCurveHandles", pd->edit_curve.show_handles);
+ DRW_shgroup_uniform_int_copy(grp, "curveHandleDisplay", pd->edit_curve.handle_display);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
}
diff --git a/source/blender/draw/engines/overlay/overlay_edit_text.c b/source/blender/draw/engines/overlay/overlay_edit_text.c
index 3de0155d6e0..c4d020adc11 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_text.c
+++ b/source/blender/draw/engines/overlay/overlay_edit_text.c
@@ -38,7 +38,8 @@ void OVERLAY_edit_text_cache_init(OVERLAY_Data *vedata)
GPUShader *sh;
DRWState state;
- pd->edit_curve.show_handles = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0;
+ pd->edit_curve.show_handles = v3d->overlay.handle_display != CURVE_HANDLE_NONE;
+ pd->edit_curve.handle_display = v3d->overlay.handle_display;
pd->shdata.edit_curve_normal_length = v3d->overlay.normals_length;
/* Run Twice for in-front passes. */
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
index e875f2c8291..61337ac8d1d 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -46,6 +46,8 @@ static void OVERLAY_engine_init(void *vedata)
const DRWContextState *draw_ctx = DRW_context_state_get();
const RegionView3D *rv3d = draw_ctx->rv3d;
const View3D *v3d = draw_ctx->v3d;
+ const Scene *scene = draw_ctx->scene;
+ const ToolSettings *ts = scene->toolsettings;
if (!stl->pd) {
/* Alloc transient pointers */
@@ -77,6 +79,15 @@ static void OVERLAY_engine_init(void *vedata)
pd->overlay.flag |= V3D_OVERLAY_WIREFRAMES;
}
+ if (ts->sculpt) {
+ if (ts->sculpt->flags & SCULPT_HIDE_FACE_SETS) {
+ pd->overlay.sculpt_mode_face_sets_opacity = 0.0f;
+ }
+ if (ts->sculpt->flags & SCULPT_HIDE_MASK) {
+ pd->overlay.sculpt_mode_mask_opacity = 0.0f;
+ }
+ }
+
pd->use_in_front = (v3d->shading.type <= OB_SOLID) ||
BKE_scene_uses_blender_workbench(draw_ctx->scene);
pd->wireframe_mode = (v3d->shading.type == OB_WIRE);
@@ -235,7 +246,8 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
const bool renderable = DRW_object_is_renderable(ob);
const bool in_pose_mode = ob->type == OB_ARMATURE && OVERLAY_armature_is_pose_mode(ob, draw_ctx);
const bool in_edit_mode = overlay_object_is_edit_mode(pd, ob);
- const bool in_particle_edit_mode = ob->mode == OB_MODE_PARTICLE_EDIT;
+ const bool in_particle_edit_mode = (ob->mode == OB_MODE_PARTICLE_EDIT) &&
+ (pd->ctx_mode == CTX_MODE_PARTICLE);
const bool in_paint_mode = (ob == draw_ctx->obact) &&
(draw_ctx->object_mode & OB_MODE_ALL_PAINT);
const bool in_sculpt_mode = (ob == draw_ctx->obact) && (ob->sculpt != NULL) &&
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index 38fa9f06079..94732fb62ed 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -65,6 +65,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_TextureList *txl = vedata->txl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
+ const bool is_select = DRW_state_is_select();
DRWState state_blend = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->extra_blend_ps, state_blend | pd->clipping_state);
@@ -80,8 +81,8 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
struct GPUTexture *tex = DRW_state_is_fbo() ? dtxl->depth : txl->dummy_depth_tx;
pd->extra_grid_grp = grp = DRW_shgroup_create(sh, psl->extra_grid_ps);
- DRW_shgroup_uniform_texture_persistent(grp, "depthBuffer", tex);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_texture(grp, "depthBuffer", tex);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
}
@@ -108,10 +109,10 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
/* Sorted by shader to avoid state changes during render. */
{
format = formats->instance_extra;
- sh = OVERLAY_shader_extra();
+ sh = OVERLAY_shader_extra(is_select);
grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
grp_sub = DRW_shgroup_create_sub(grp);
cb->camera_distances = BUF_INSTANCE(grp_sub, format, DRW_cache_camera_distances_get());
@@ -156,7 +157,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
{
format = formats->instance_extra;
grp = DRW_shgroup_create(sh, psl->extra_blend_ps); /* NOTE: not the same pass! */
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
grp_sub = DRW_shgroup_create_sub(grp);
DRW_shgroup_state_enable(grp_sub, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK);
@@ -173,38 +174,38 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_extra_groundline();
grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
cb->groundline = BUF_INSTANCE(grp, format, DRW_cache_groundline_get());
}
{
- sh = OVERLAY_shader_extra_wire(false);
+ sh = OVERLAY_shader_extra_wire(false, is_select);
grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->extra_dashed_lines = BUF_LINE(grp, formats->pos_color);
cb->extra_lines = BUF_LINE(grp, formats->wire_extra);
}
{
- sh = OVERLAY_shader_extra_wire(true);
+ sh = OVERLAY_shader_extra_wire(true, is_select);
cb->extra_wire = grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
{
sh = OVERLAY_shader_extra_loose_point();
cb->extra_loose_points = grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
{
format = formats->pos;
sh = OVERLAY_shader_extra_point();
grp = DRW_shgroup_create(sh, psl->extra_centers_ps); /* NOTE: not the same pass! */
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
grp_sub = DRW_shgroup_create_sub(grp);
DRW_shgroup_uniform_vec4_copy(grp_sub, "color", G_draw.block.colorActive);
@@ -768,10 +769,7 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob)
uint cell_count = prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z;
DRWShadingGroup *grp = DRW_shgroup_create_sub(vedata->stl->pd->extra_grid_grp);
- DRW_shgroup_uniform_vec4_copy(grp, "gridModelMatrix[0]", instdata.mat[0]);
- DRW_shgroup_uniform_vec4_copy(grp, "gridModelMatrix[1]", instdata.mat[1]);
- DRW_shgroup_uniform_vec4_copy(grp, "gridModelMatrix[2]", instdata.mat[2]);
- DRW_shgroup_uniform_vec4_copy(grp, "gridModelMatrix[3]", instdata.mat[3]);
+ DRW_shgroup_uniform_vec4_array_copy(grp, "gridModelMatrix", instdata.mat, 4);
DRW_shgroup_call_procedural_points(grp, NULL, cell_count);
}
break;
@@ -1373,9 +1371,9 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
madd_v3fl_v3fl_v3fl_v3i(min, mds->p0, mds->cell_size, mds->res_min);
float voxel_cubemat[4][4] = {{0.0f}};
/* scale small cube to voxel size */
- voxel_cubemat[0][0] = 1.0f / (float)mds->base_res[0];
- voxel_cubemat[1][1] = 1.0f / (float)mds->base_res[1];
- voxel_cubemat[2][2] = 1.0f / (float)mds->base_res[2];
+ voxel_cubemat[0][0] = mds->cell_size[0] / 2.0f;
+ voxel_cubemat[1][1] = mds->cell_size[1] / 2.0f;
+ voxel_cubemat[2][2] = mds->cell_size[2] / 2.0f;
voxel_cubemat[3][3] = 1.0f;
/* translate small cube to corner */
copy_v3_v3(voxel_cubemat[3], min);
diff --git a/source/blender/draw/engines/overlay/overlay_facing.c b/source/blender/draw/engines/overlay/overlay_facing.c
index 9216ae61b3e..4eb4b8ae85b 100644
--- a/source/blender/draw/engines/overlay/overlay_facing.c
+++ b/source/blender/draw/engines/overlay/overlay_facing.c
@@ -41,7 +41,7 @@ void OVERLAY_facing_cache_init(OVERLAY_Data *vedata)
GPUShader *sh = OVERLAY_shader_facing();
pd->facing_grp[i] = DRW_shgroup_create(sh, psl->facing_ps[i]);
- DRW_shgroup_uniform_block_persistent(pd->facing_grp[i], "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(pd->facing_grp[i], "globalsBlock", G_draw.block_ubo);
}
if (!pd->use_in_front) {
diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c
index 1397ef7b4b2..ccc914e0422 100644
--- a/source/blender/draw/engines/overlay/overlay_gpencil.c
+++ b/source/blender/draw/engines/overlay/overlay_gpencil.c
@@ -361,7 +361,7 @@ static void OVERLAY_gpencil_color_names(Object *ob)
int cfra = DEG_get_ctime(draw_ctx->depsgraph);
BKE_gpencil_visible_stroke_iter(
- ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra);
+ NULL, ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra);
}
void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
diff --git a/source/blender/draw/engines/overlay/overlay_motion_path.c b/source/blender/draw/engines/overlay/overlay_motion_path.c
index 531e1faf715..168f6f8a17f 100644
--- a/source/blender/draw/engines/overlay/overlay_motion_path.c
+++ b/source/blender/draw/engines/overlay/overlay_motion_path.c
@@ -49,11 +49,11 @@ void OVERLAY_motion_path_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_motion_path_line();
pd->motion_path_lines_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
sh = OVERLAY_shader_motion_path_vert();
pd->motion_path_points_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
/* Just convert the CPU cache to GPU cache. */
diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c
index 142421f58d8..99d22fc380f 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.c
+++ b/source/blender/draw/engines/overlay/overlay_outline.c
@@ -259,7 +259,7 @@ static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob)
}
BKE_gpencil_visible_stroke_iter(
- ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, false, pd->cfra);
+ NULL, ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, false, pd->cfra);
}
void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
diff --git a/source/blender/draw/engines/overlay/overlay_particle.c b/source/blender/draw/engines/overlay/overlay_particle.c
index 98bc62ae66a..b891bb4ce4c 100644
--- a/source/blender/draw/engines/overlay/overlay_particle.c
+++ b/source/blender/draw/engines/overlay/overlay_particle.c
@@ -152,13 +152,13 @@ void OVERLAY_particle_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_particle_dot();
pd->particle_dots_grp = grp = DRW_shgroup_create(sh, psl->particle_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
- DRW_shgroup_uniform_texture_persistent(grp, "weightTex", G_draw.ramp);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.ramp);
sh = OVERLAY_shader_particle_shape();
pd->particle_shapes_grp = grp = DRW_shgroup_create(sh, psl->particle_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
- DRW_shgroup_uniform_texture_persistent(grp, "weightTex", G_draw.ramp);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.ramp);
}
void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob)
diff --git a/source/blender/draw/engines/overlay/overlay_pointcloud.c b/source/blender/draw/engines/overlay/overlay_pointcloud.c
index a0de7aac1f1..b2a2d44bf73 100644
--- a/source/blender/draw/engines/overlay/overlay_pointcloud.c
+++ b/source/blender/draw/engines/overlay/overlay_pointcloud.c
@@ -46,7 +46,7 @@ void OVERLAY_pointcloud_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_pointcloud_dot();
pd->pointcloud_dots_grp = grp = DRW_shgroup_create(sh, psl->pointcloud_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
void OVERLAY_pointcloud_cache_populate(OVERLAY_Data *vedata, Object *ob)
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index 257cf777ed2..ed0a9cf6981 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -54,7 +54,7 @@ typedef struct OVERLAY_PassList {
DRWPass *antialiasing_ps;
DRWPass *armature_ps[2];
DRWPass *armature_bone_select_ps;
- DRWPass *armature_transp_ps;
+ DRWPass *armature_transp_ps[2];
DRWPass *background_ps;
DRWPass *clipping_frustum_ps;
DRWPass *edit_curve_wire_ps[2];
@@ -297,6 +297,7 @@ typedef struct OVERLAY_PrivateData {
} antialiasing;
struct {
bool show_handles;
+ int handle_display;
} edit_curve;
struct {
int ghost_ob;
@@ -589,9 +590,9 @@ GPUShader *OVERLAY_shader_edit_mesh_skin_root(void);
GPUShader *OVERLAY_shader_edit_mesh_vert(void);
GPUShader *OVERLAY_shader_edit_particle_strand(void);
GPUShader *OVERLAY_shader_edit_particle_point(void);
-GPUShader *OVERLAY_shader_extra(void);
+GPUShader *OVERLAY_shader_extra(bool is_select);
GPUShader *OVERLAY_shader_extra_groundline(void);
-GPUShader *OVERLAY_shader_extra_wire(bool use_object);
+GPUShader *OVERLAY_shader_extra_wire(bool use_object, bool is_select);
GPUShader *OVERLAY_shader_extra_loose_point(void);
GPUShader *OVERLAY_shader_extra_point(void);
GPUShader *OVERLAY_shader_facing(void);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index 59f388df4e3..0610b8397a1 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -164,8 +164,10 @@ typedef struct OVERLAY_Shaders {
GPUShader *edit_particle_strand;
GPUShader *edit_particle_point;
GPUShader *extra;
+ GPUShader *extra_select;
GPUShader *extra_groundline;
GPUShader *extra_wire[2];
+ GPUShader *extra_wire_select;
GPUShader *extra_point;
GPUShader *extra_lightprobe_grid;
GPUShader *extra_loose_point;
@@ -797,23 +799,24 @@ GPUShader *OVERLAY_shader_edit_particle_point(void)
return sh_data->edit_particle_point;
}
-GPUShader *OVERLAY_shader_extra(void)
+GPUShader *OVERLAY_shader_extra(bool is_select)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- if (!sh_data->extra) {
- sh_data->extra = GPU_shader_create_from_arrays({
+ GPUShader **sh = (is_select) ? &sh_data->extra_select : &sh_data->extra;
+ if (!*sh) {
+ *sh = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg->lib,
datatoc_common_globals_lib_glsl,
datatoc_common_view_lib_glsl,
datatoc_extra_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_common_view_lib_glsl, datatoc_extra_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
+ .defs = (const char *[]){sh_cfg->def, (is_select) ? "#define SELECT_EDGES\n" : NULL, NULL},
});
}
- return sh_data->extra;
+ return *sh;
}
GPUShader *OVERLAY_shader_extra_grid(void)
@@ -855,12 +858,13 @@ GPUShader *OVERLAY_shader_extra_groundline(void)
return sh_data->extra_groundline;
}
-GPUShader *OVERLAY_shader_extra_wire(bool use_object)
+GPUShader *OVERLAY_shader_extra_wire(bool use_object, bool is_select)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- if (!sh_data->extra_wire[use_object]) {
+ GPUShader **sh = (is_select) ? &sh_data->extra_wire_select : &sh_data->extra_wire[use_object];
+ if (!*sh) {
char colorids[1024];
/* NOTE: define all ids we need here. */
BLI_snprintf(colorids,
@@ -875,7 +879,7 @@ GPUShader *OVERLAY_shader_extra_wire(bool use_object)
TH_TRANSFORM,
TH_WIRE,
TH_CAMERA_PATH);
- sh_data->extra_wire[use_object] = GPU_shader_create_from_arrays({
+ *sh = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg->lib,
datatoc_common_globals_lib_glsl,
datatoc_common_view_lib_glsl,
@@ -884,11 +888,12 @@ GPUShader *OVERLAY_shader_extra_wire(bool use_object)
.frag = (const char *[]){datatoc_common_view_lib_glsl, datatoc_extra_wire_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg->def,
colorids,
+ (is_select) ? "#define SELECT_EDGES\n" : "",
(use_object) ? "#define OBJECT_WIRE \n" : NULL,
NULL},
});
}
- return sh_data->extra_wire[use_object];
+ return *sh;
}
GPUShader *OVERLAY_shader_extra_loose_point(void)
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c
index 309c7c1021a..eebfc88fdce 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -91,7 +91,7 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata)
for (int use_coloring = 0; use_coloring < 2; use_coloring++) {
pd->wires_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx);
DRW_shgroup_uniform_float_copy(grp, "wireStepParam", pd->shdata.wire_step_param);
DRW_shgroup_uniform_bool_copy(grp, "useColoring", use_coloring);
@@ -157,10 +157,7 @@ static void wireframe_hair_cache_populate(OVERLAY_Data *vedata, Object *ob, Part
const bool use_coloring = true;
DRWShadingGroup *shgrp = DRW_shgroup_create_sub(pd->wires_hair_grp[is_xray][use_coloring]);
- DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[0]", dupli_mat[0]);
- DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[1]", dupli_mat[1]);
- DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[2]", dupli_mat[2]);
- DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[3]", dupli_mat[3]);
+ DRW_shgroup_uniform_vec4_array_copy(shgrp, "hairDupliMatrix", dupli_mat, 4);
DRW_shgroup_call_no_cull(shgrp, hairs, ob);
}
@@ -200,13 +197,15 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
struct GPUBatch *geom = NULL;
switch (ob->type) {
case OB_CURVE:
- if (ob->runtime.curve_cache && BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
+ if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache &&
+ BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
break;
}
geom = DRW_cache_curve_edge_wire_get(ob);
break;
case OB_FONT:
- if (ob->runtime.curve_cache && BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
+ if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache &&
+ BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
break;
}
geom = DRW_cache_text_loose_edges_get(ob);
diff --git a/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl b/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl
index b444b3b0fec..306fbb473ee 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl
@@ -4,10 +4,15 @@
#define EVEN_U_BIT 1 << 4
#define COLOR_SHIFT 5
+/* Keep the same value in `handle_display` in `DNA_view3d_types.h` */
+#define CURVE_HANDLE_SELECTED 0
+#define CURVE_HANDLE_ALL 1
+
layout(lines) in;
layout(triangle_strip, max_vertices = 10) out;
uniform bool showCurveHandles;
+uniform int curveHandleDisplay;
flat in int vertFlag[];
@@ -46,6 +51,17 @@ void main()
}
bool edge_selected = (((vertFlag[1] | vertFlag[0]) & VERT_SELECTED) != 0);
+ bool handle_selected = (showCurveHandles &&
+ (((vertFlag[1] | vertFlag[0]) & HANDLE_SELECTED) != 0));
+
+ /* If handle type is only selected and the edge is not selected, don't show. */
+ if ((curveHandleDisplay != CURVE_HANDLE_ALL) && (!handle_selected)) {
+ /* Nurbs must show the handles always. */
+ bool is_u_segment = (((vertFlag[1] ^ vertFlag[0]) & EVEN_U_BIT) != 0);
+ if (!is_u_segment) {
+ return;
+ }
+ }
vec4 inner_color;
if (color_id == 0) {
diff --git a/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl
index 6fa4576ae71..b1e1c0879a5 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl
@@ -2,7 +2,11 @@
/* Keep the same value of `BEZIER_HANDLE` in `draw_cache_imp_curve.c` */
#define BEZIER_HANDLE 1 << 3
+/* Keep the same value in `handle_display` in `DNA_view3d_types.h` */
+#define CURVE_HANDLE_SELECTED 0
+
uniform bool showCurveHandles;
+uniform int curveHandleDisplay;
in vec3 pos;
in int data;
@@ -32,7 +36,12 @@ void main()
world_clip_planes_calc_clip_distance(world_pos);
#endif
- if (!showCurveHandles && ((data & BEZIER_HANDLE) != 0)) {
+ bool show_handle = showCurveHandles;
+ if ((curveHandleDisplay == CURVE_HANDLE_SELECTED) && ((data & HANDLE_SELECTED) == 0)) {
+ show_handle = false;
+ }
+
+ if (!show_handle && ((data & BEZIER_HANDLE) != 0)) {
/* We set the vertex at the camera origin to generate 0 fragments. */
gl_Position = vec4(0.0, 0.0, -3e36, 0.0);
}
diff --git a/source/blender/draw/engines/overlay/shaders/extra_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_vert.glsl
index 035fab1040e..2168d8065fc 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_vert.glsl
@@ -221,6 +221,13 @@ void main()
/* Convert to screen position [0..sizeVp]. */
edgePos = edgeStart = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
+#ifdef SELECT_EDGES
+ /* HACK: to avoid loosing sub pixel object in selections, we add a bit of randomness to the
+ * wire to at least create one fragment that will pass the occlusion query. */
+ /* TODO(fclem) Limit this workaround to selection. It's not very noticeable but still... */
+ gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexID % 2 == 0) ? -1.0 : 1.0);
+#endif
+
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
diff --git a/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl
index 474f3254389..0fbf9ba8137 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl
@@ -17,6 +17,13 @@ void main()
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
+#ifdef SELECT_EDGES
+ /* HACK: to avoid loosing sub pixel object in selections, we add a bit of randomness to the
+ * wire to at least create one fragment that will pass the occlusion query. */
+ /* TODO(fclem) Limit this workaround to selection. It's not very noticeable but still... */
+ gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexID % 2 == 0) ? -1.0 : 1.0);
+#endif
+
stipple_coord = stipple_start = screen_position(gl_Position);
#ifdef OBJECT_WIRE
@@ -34,6 +41,10 @@ void main()
}
#endif
+#ifdef SELECT_EDGES
+ finalColor.a = 0.0; /* No Stipple */
+#endif
+
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
index 0efcfb35929..51007a9f246 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
@@ -4,7 +4,6 @@
* Converted and adapted from HLSL to GLSL by Clément Foucault
*/
-uniform mat4 ProjectionMatrix;
uniform vec2 invertedViewportSize;
uniform vec2 nearFar;
uniform vec3 dofParams;
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl
index 6f99739f259..e45f7a7b9e3 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl
@@ -24,11 +24,17 @@ bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map)
vec4 workbench_sample_texture(sampler2D image, vec2 coord, bool nearest_sampling)
{
- vec2 tex_size = vec2(textureSize(image, 0).xy);
/* TODO(fclem) We could do the same with sampler objects.
* But this is a quick workaround instead of messing with the GPUTexture itself. */
- vec2 uv = nearest_sampling ? (floor(coord * tex_size) + 0.5) / tex_size : coord;
- return texture(image, uv);
+ if (nearest_sampling) {
+ /* Use texelFetch for nearest_sampling to reduce glitches. See: T73726 */
+ vec2 tex_size = vec2(textureSize(image, 0).xy);
+ ivec2 uv = ivec2(floor(coord * tex_size) + 0.5);
+ return texelFetch(image, uv, 0);
+ }
+ else {
+ return texture(image, coord);
+ }
}
vec4 workbench_sample_texture_array(sampler2DArray tile_array,
@@ -36,7 +42,6 @@ vec4 workbench_sample_texture_array(sampler2DArray tile_array,
vec2 coord,
bool nearest_sampling)
{
- vec2 tex_size = vec2(textureSize(tile_array, 0).xy);
vec3 uv = vec3(coord, 0);
if (!node_tex_tile_lookup(uv, tile_array, tile_data))
@@ -44,8 +49,15 @@ vec4 workbench_sample_texture_array(sampler2DArray tile_array,
/* TODO(fclem) We could do the same with sampler objects.
* But this is a quick workaround instead of messing with the GPUTexture itself. */
- uv.xy = nearest_sampling ? (floor(uv.xy * tex_size) + 0.5) / tex_size : uv.xy;
- return texture(tile_array, uv);
+ if (nearest_sampling) {
+ /* Use texelFetch for nearest_sampling to reduce glitches. See: T73726 */
+ vec3 tex_size = vec3(textureSize(tile_array, 0));
+ uv.xy = floor(uv.xy * tex_size.xy) + 0.5;
+ return texelFetch(tile_array, ivec3(uv), 0);
+ }
+ else {
+ return texture(tile_array, uv);
+ }
}
uniform sampler2DArray imageTileArray;
diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
index d2bd653a656..0e896c4b7bb 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
@@ -19,7 +19,7 @@
/** \file
* \ingroup draw_engine
*
- * Anti-aliasing:
+ * Anti-Aliasing:
*
* We use SMAA (Smart Morphological Anti-Aliasing) as a fast antialiasing solution.
*
@@ -266,13 +266,8 @@ void workbench_antialiasing_engine_init(WORKBENCH_Data *vedata)
false,
NULL);
- GPU_texture_bind(txl->smaa_search_tx, 0);
GPU_texture_filter_mode(txl->smaa_search_tx, true);
- GPU_texture_unbind(txl->smaa_search_tx);
-
- GPU_texture_bind(txl->smaa_area_tx, 0);
GPU_texture_filter_mode(txl->smaa_area_tx, true);
- GPU_texture_unbind(txl->smaa_area_tx);
}
}
else {
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 0b7d313342b..b36a4a3a494 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -284,11 +284,11 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd,
*grp_tex = grp = DRW_shgroup_create_sub(grp);
if (tex_tile_data) {
- DRW_shgroup_uniform_texture_persistent(grp, "imageTileArray", tex);
- DRW_shgroup_uniform_texture_persistent(grp, "imageTileData", tex_tile_data);
+ DRW_shgroup_uniform_texture(grp, "imageTileArray", tex);
+ DRW_shgroup_uniform_texture(grp, "imageTileData", tex_tile_data);
}
else {
- DRW_shgroup_uniform_texture_persistent(grp, "imageTexture", tex);
+ DRW_shgroup_uniform_texture(grp, "imageTexture", tex);
}
DRW_shgroup_uniform_bool_copy(grp, "imagePremult", (ima && ima->alpha_mode == IMA_ALPHA_PREMUL));
DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST));
diff --git a/source/blender/draw/engines/workbench/workbench_opaque.c b/source/blender/draw/engines/workbench/workbench_opaque.c
index c9c43e785ca..27d5b71f35c 100644
--- a/source/blender/draw/engines/workbench/workbench_opaque.c
+++ b/source/blender/draw/engines/workbench/workbench_opaque.c
@@ -95,21 +95,21 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
wpd->prepass[opaque][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
sh = workbench_shader_opaque_image_get(wpd, hair, false);
wpd->prepass[opaque][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
sh = workbench_shader_opaque_image_get(wpd, hair, true);
wpd->prepass[opaque][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
}
@@ -123,9 +123,9 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
sh = workbench_shader_composite_get(wpd);
grp = DRW_shgroup_create(sh, psl->composite_ps);
- DRW_shgroup_uniform_block_persistent(grp, "world_block", wpd->world_ubo);
- DRW_shgroup_uniform_texture_persistent(grp, "materialBuffer", wpd->material_buffer_tx);
- DRW_shgroup_uniform_texture_persistent(grp, "normalBuffer", wpd->normal_buffer_tx);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_texture(grp, "materialBuffer", wpd->material_buffer_tx);
+ DRW_shgroup_uniform_texture(grp, "normalBuffer", wpd->normal_buffer_tx);
DRW_shgroup_uniform_bool_copy(grp, "forceShadowing", false);
DRW_shgroup_stencil_mask(grp, 0x00);
@@ -137,8 +137,8 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
struct GPUTexture *spec_tx = wpd->studio_light->matcap_specular.gputexture;
const bool use_spec = workbench_is_specular_highlight_enabled(wpd);
spec_tx = (use_spec && spec_tx) ? spec_tx : diff_tx;
- DRW_shgroup_uniform_texture_persistent(grp, "matcapDiffuseImage", diff_tx);
- DRW_shgroup_uniform_texture_persistent(grp, "matcapSpecularImage", spec_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapDiffuseImage", diff_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapSpecularImage", spec_tx);
}
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c
index 2e796056029..99366779b22 100644
--- a/source/blender/draw/engines/workbench/workbench_shader.c
+++ b/source/blender/draw/engines/workbench/workbench_shader.c
@@ -23,6 +23,7 @@
#include "DRW_render.h"
#include "BLI_dynstr.h"
+#include "BLI_string_utils.h"
#include "workbench_engine.h"
#include "workbench_private.h"
@@ -359,32 +360,24 @@ void workbench_shader_depth_of_field_get(GPUShader **prepare_sh,
GPUShader **resolve_sh)
{
if (e_data.dof_prepare_sh == NULL) {
- e_data.dof_prepare_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define PREPARE\n");
-
- e_data.dof_downsample_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define DOWNSAMPLE\n");
+ char *frag = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_workbench_effect_dof_frag_glsl);
+ e_data.dof_prepare_sh = DRW_shader_create_fullscreen(frag, "#define PREPARE\n");
+ e_data.dof_downsample_sh = DRW_shader_create_fullscreen(frag, "#define DOWNSAMPLE\n");
#if 0 /* TODO(fclem) finish COC min_max optimization */
- e_data.dof_flatten_v_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_flatten_v_sh = DRW_shader_create_fullscreen(frag,
"#define FLATTEN_VERTICAL\n");
-
- e_data.dof_flatten_h_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_flatten_h_sh = DRW_shader_create_fullscreen(frag,
"#define FLATTEN_HORIZONTAL\n");
-
- e_data.dof_dilate_v_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_dilate_v_sh = DRW_shader_create_fullscreen(frag,
"#define DILATE_VERTICAL\n");
-
- e_data.dof_dilate_h_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_dilate_h_sh = DRW_shader_create_fullscreen(frag,
"#define DILATE_HORIZONTAL\n");
#endif
- e_data.dof_blur1_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define BLUR1\n");
-
- e_data.dof_blur2_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define BLUR2\n");
-
- e_data.dof_resolve_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define RESOLVE\n");
+ e_data.dof_blur1_sh = DRW_shader_create_fullscreen(frag, "#define BLUR1\n");
+ e_data.dof_blur2_sh = DRW_shader_create_fullscreen(frag, "#define BLUR2\n");
+ e_data.dof_resolve_sh = DRW_shader_create_fullscreen(frag, "#define RESOLVE\n");
+ MEM_freeN(frag);
}
*prepare_sh = e_data.dof_prepare_sh;
diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c
index 39aa721a41c..5fd8229304a 100644
--- a/source/blender/draw/engines/workbench/workbench_transparent.c
+++ b/source/blender/draw/engines/workbench/workbench_transparent.c
@@ -67,7 +67,7 @@ void workbench_transparent_engine_init(WORKBENCH_Data *data)
static void workbench_transparent_lighting_uniforms(WORKBENCH_PrivateData *wpd,
DRWShadingGroup *grp)
{
- DRW_shgroup_uniform_block_persistent(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
DRW_shgroup_uniform_bool_copy(grp, "forceShadowing", false);
if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
@@ -78,8 +78,8 @@ static void workbench_transparent_lighting_uniforms(WORKBENCH_PrivateData *wpd,
struct GPUTexture *spec_tx = wpd->studio_light->matcap_specular.gputexture;
const bool use_spec = workbench_is_specular_highlight_enabled(wpd);
spec_tx = (use_spec && spec_tx) ? spec_tx : diff_tx;
- DRW_shgroup_uniform_texture_persistent(grp, "matcapDiffuseImage", diff_tx);
- DRW_shgroup_uniform_texture_persistent(grp, "matcapSpecularImage", spec_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapDiffuseImage", diff_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapSpecularImage", spec_tx);
}
}
@@ -116,20 +116,20 @@ void workbench_transparent_cache_init(WORKBENCH_Data *data)
workbench_transparent_lighting_uniforms(wpd, grp);
wpd->prepass[transp][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */
sh = workbench_shader_transparent_image_get(wpd, hair, false);
wpd->prepass[transp][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
workbench_transparent_lighting_uniforms(wpd, grp);
sh = workbench_shader_transparent_image_get(wpd, hair, true);
wpd->prepass[transp][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
workbench_transparent_lighting_uniforms(wpd, grp);
}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index c4d9396307a..e7dd9e449b7 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -210,10 +210,7 @@ struct GPUShader *DRW_shader_create_with_transform_feedback(const char *vert,
const eGPUShaderTFBType prim_type,
const char **varying_names,
const int varying_count);
-struct GPUShader *DRW_shader_create_2d(const char *frag, const char *defines);
-struct GPUShader *DRW_shader_create_3d(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines);
-struct GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig slot);
struct GPUMaterial *DRW_shader_find_from_world(struct World *wo,
const void *engine_type,
const int options,
@@ -224,6 +221,7 @@ struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma,
bool deferred);
struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
struct World *wo,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -234,6 +232,7 @@ struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
bool deferred);
struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
struct Material *ma,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -365,6 +364,8 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
DRWPass *pass,
struct GPUVertBuf *tf_target);
+void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial *material);
+
/* return final visibility */
typedef bool(DRWCallVisibilityFn)(bool vis_in, void *user_data);
@@ -460,18 +461,15 @@ void DRW_shgroup_clear_framebuffer(DRWShadingGroup *shgroup,
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup,
const char *name,
const struct GPUTexture *tex);
-void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const struct GPUTexture *tex);
-void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
- const char *name,
- const struct GPUUniformBuffer *ubo);
-void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const struct GPUUniformBuffer *ubo);
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 GPUUniformBuffer *ubo);
+void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup,
+ const char *name,
+ struct GPUUniformBuffer **ubo);
void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup,
const char *name,
const float *value,
@@ -521,11 +519,17 @@ void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name,
void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value);
void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value);
void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value);
+void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
+ const char *name,
+ const float (*value)[4],
+ int arraysize);
bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup);
/* Passes */
DRWPass *DRW_pass_create(const char *name, DRWState state);
+DRWPass *DRW_pass_create_instance(const char *name, DRWPass *original, DRWState state);
+void DRW_pass_link(DRWPass *first, DRWPass *second);
/* TODO Replace with passes inheritance. */
void DRW_pass_state_set(DRWPass *pass, DRWState state);
void DRW_pass_state_add(DRWPass *pass, DRWState state);
@@ -539,6 +543,8 @@ void DRW_pass_sort_shgroup_reverse(DRWPass *pass);
bool DRW_pass_is_empty(DRWPass *pass);
#define DRW_PASS_CREATE(pass, state) (pass = DRW_pass_create(#pass, state))
+#define DRW_PASS_INSTANCE_CREATE(pass, original, state) \
+ (pass = DRW_pass_create_instance(#pass, (original), state))
/* Views */
DRWView *DRW_view_create(const float viewmat[4][4],
@@ -692,6 +698,8 @@ typedef struct DRWContextState {
struct Depsgraph *depsgraph;
+ struct TaskGraph *task_graph;
+
eObjectMode object_mode;
eGPUShaderConfig sh_cfg;
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 23d0d74534d..c23ea3d7c82 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -3534,13 +3534,15 @@ void drw_batch_cache_generate_requested(Object *ob)
struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
switch (ob->type) {
case OB_MESH:
- DRW_mesh_batch_cache_create_requested(ob, (Mesh *)ob->data, scene, is_paint_mode, use_hide);
+ DRW_mesh_batch_cache_create_requested(
+ DST.task_graph, ob, (Mesh *)ob->data, scene, is_paint_mode, use_hide);
break;
case OB_CURVE:
case OB_FONT:
case OB_SURF:
if (mesh_eval) {
- DRW_mesh_batch_cache_create_requested(ob, mesh_eval, scene, is_paint_mode, use_hide);
+ DRW_mesh_batch_cache_create_requested(
+ DST.task_graph, ob, mesh_eval, scene, is_paint_mode, use_hide);
}
DRW_curve_batch_cache_create_requested(ob);
break;
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h
index b2fea957227..f203c2ff1ea 100644
--- a/source/blender/draw/intern/draw_cache_extract.h
+++ b/source/blender/draw/intern/draw_cache_extract.h
@@ -23,6 +23,8 @@
#ifndef __DRAW_CACHE_EXTRACT_H__
#define __DRAW_CACHE_EXTRACT_H__
+struct TaskGraph;
+
/* Vertex Group Selection and display options */
typedef struct DRW_MeshWeightState {
int defgroup_active;
@@ -249,7 +251,8 @@ typedef struct MeshBatchCache {
bool no_loose_wire;
} MeshBatchCache;
-void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
+void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
+ MeshBatchCache *cache,
MeshBufferCache mbc,
Mesh *me,
const bool is_editmode,
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c
index 401f5c76a02..06462d5b9c5 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.c
@@ -105,6 +105,14 @@ typedef struct MeshRenderData {
BMEditMesh *edit_bmesh;
BMesh *bm;
EditMeshData *edit_data;
+
+ /* For deformed edit-mesh data. */
+ /* Use for #ME_WRAPPER_TYPE_BMESH. */
+ const float (*bm_vert_coords)[3];
+ const float (*bm_vert_normals)[3];
+ const float (*bm_poly_normals)[3];
+ const float (*bm_poly_centers)[3];
+
int *v_origindex, *e_origindex, *p_origindex;
int crease_ofs;
int bweight_ofs;
@@ -126,15 +134,12 @@ typedef struct MeshRenderData {
float (*poly_normals)[3];
int *lverts, *ledges;
} MeshRenderData;
-
static MeshRenderData *mesh_render_data_create(Mesh *me,
const bool is_editmode,
const bool is_paint_mode,
const float obmat[4][4],
const bool do_final,
const bool do_uvedit,
- const eMRIterType iter_type,
- const eMRDataType data_flag,
const DRW_MeshCDMask *UNUSED(cd_used),
const ToolSettings *ts)
{
@@ -144,16 +149,28 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
copy_m4_m4(mr->obmat, obmat);
- const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
- const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
-
if (is_editmode) {
BLI_assert(me->edit_mesh->mesh_eval_cage && me->edit_mesh->mesh_eval_final);
mr->bm = me->edit_mesh->bm;
mr->edit_bmesh = me->edit_mesh;
- mr->edit_data = me->runtime.edit_data;
mr->me = (do_final) ? me->edit_mesh->mesh_eval_final : me->edit_mesh->mesh_eval_cage;
- bool use_mapped = !do_uvedit && mr->me && !mr->me->runtime.is_original;
+ mr->edit_data = mr->me->runtime.edit_data;
+
+ if (mr->edit_data) {
+ EditMeshData *emd = mr->edit_data;
+ if (emd->vertexCos) {
+ BKE_editmesh_cache_ensure_vert_normals(mr->edit_bmesh, emd);
+ BKE_editmesh_cache_ensure_poly_normals(mr->edit_bmesh, emd);
+ }
+
+ mr->bm_vert_coords = mr->edit_data->vertexCos;
+ mr->bm_vert_normals = mr->edit_data->vertexNos;
+ mr->bm_poly_normals = mr->edit_data->polyNos;
+ mr->bm_poly_centers = mr->edit_data->polyCos;
+ }
+
+ bool has_mdata = (mr->me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA);
+ bool use_mapped = has_mdata && !do_uvedit && mr->me && !mr->me->runtime.is_original;
int bm_ensure_types = BM_VERT | BM_EDGE | BM_LOOP | BM_FACE;
@@ -184,7 +201,7 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
/* Seems like the mesh_eval_final do not have the right origin indices.
* Force not mapped in this case. */
- if (do_final && me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage) {
+ if (has_mdata && do_final && me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage) {
// mr->edit_bmesh = NULL;
mr->extract_type = MR_EXTRACT_MESH;
}
@@ -221,7 +238,32 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
+ }
+ else {
+ /* BMesh */
+ BMesh *bm = mr->bm;
+ mr->vert_len = bm->totvert;
+ mr->edge_len = bm->totedge;
+ mr->loop_len = bm->totloop;
+ mr->poly_len = bm->totface;
+ mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
+ }
+
+ return mr;
+}
+
+/* Part of the creation of the MeshRenderData that happens in a thread. */
+static void mesh_render_data_update(MeshRenderData *mr,
+ const eMRIterType iter_type,
+ const eMRDataType data_flag)
+{
+ Mesh *me = mr->me;
+ const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
+ const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
+
+ if (mr->extract_type != MR_EXTRACT_BMESH) {
+ /* Mesh */
if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) {
mr->poly_normals = MEM_mallocN(sizeof(*mr->poly_normals) * mr->poly_len, __func__);
BKE_mesh_calc_normals_poly((MVert *)mr->mvert,
@@ -300,23 +342,27 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
else {
/* BMesh */
BMesh *bm = mr->bm;
-
- mr->vert_len = bm->totvert;
- mr->edge_len = bm->totedge;
- mr->loop_len = bm->totloop;
- mr->poly_len = bm->totface;
- mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
-
if (data_flag & MR_DATA_POLY_NOR) {
/* Use bmface->no instead. */
}
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
+
+ const float(*vert_coords)[3] = NULL;
+ const float(*vert_normals)[3] = NULL;
+ const float(*poly_normals)[3] = NULL;
+
+ if (mr->edit_data && mr->edit_data->vertexCos) {
+ vert_coords = mr->bm_vert_coords;
+ vert_normals = mr->bm_vert_normals;
+ poly_normals = mr->bm_poly_normals;
+ }
+
mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_loops_calc_normal_vcos(mr->bm,
- NULL,
- NULL,
- NULL,
+ vert_coords,
+ vert_normals,
+ poly_normals,
is_auto_smooth,
split_angle,
mr->loop_normals,
@@ -360,7 +406,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2;
}
}
- return mr;
}
static void mesh_render_data_free(MeshRenderData *mr)
@@ -396,6 +441,42 @@ BLI_INLINE BMVert *bm_original_vert_get(const MeshRenderData *mr, int idx)
NULL;
}
+BLI_INLINE const float *bm_vert_co_get(const MeshRenderData *mr, const BMVert *eve)
+{
+ const float(*vert_coords)[3] = mr->bm_vert_coords;
+ if (vert_coords != NULL) {
+ return vert_coords[BM_elem_index_get(eve)];
+ }
+ else {
+ UNUSED_VARS(mr);
+ return eve->co;
+ }
+}
+
+BLI_INLINE const float *bm_vert_no_get(const MeshRenderData *mr, const BMVert *eve)
+{
+ const float(*vert_normals)[3] = mr->bm_vert_normals;
+ if (vert_normals != NULL) {
+ return vert_normals[BM_elem_index_get(eve)];
+ }
+ else {
+ UNUSED_VARS(mr);
+ return eve->co;
+ }
+}
+
+BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *efa)
+{
+ const float(*poly_normals)[3] = mr->bm_poly_normals;
+ if (poly_normals != NULL) {
+ return poly_normals[BM_elem_index_get(efa)];
+ }
+ else {
+ UNUSED_VARS(mr);
+ return efa->no;
+ }
+}
+
/** \} */
/* ---------------------------------------------------------------------- */
@@ -672,46 +753,15 @@ static const MeshExtract extract_lines = {
0,
false,
};
-
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Loose Edges Indices
+/** \name Extract Loose Edges Sub Buffer
* \{ */
-static void *extract_lines_loose_init(const MeshRenderData *UNUSED(mr), void *UNUSED(buf))
-{
- return NULL;
-}
-
-static void extract_lines_loose_ledge_mesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(e),
- const MEdge *UNUSED(medge),
- void *UNUSED(elb))
-{
- /* This function is intentionally empty. The existence of this functions ensures that
- * `iter_type` `MR_ITER_LVERT` is set when initializing the `MeshRenderData` (See
- * `mesh_extract_iter_type`). This flag ensures that `mr->edge_loose_len` field is filled. This
- * field we use in the `extract_lines_loose_finish` function to create a subrange from the
- * `ibo.lines`. */
-}
-
-static void extract_lines_loose_ledge_bmesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(e),
- BMEdge *UNUSED(eed),
- void *UNUSED(elb))
-{
- /* This function is intentionally empty. The existence of this functions ensures that
- * `iter_type` `MR_ITER_LVERT` is set when initializing the `MeshRenderData` (See
- * `mesh_extract_iter_type`). This flag ensures that `mr->edge_loose_len` field is filled. This
- * field we use in the `extract_lines_loose_finish` function to create a subrange from the
- * `ibo.lines`. */
-}
-
-static void extract_lines_loose_finish(const MeshRenderData *mr,
- void *UNUSED(ibo),
- void *UNUSED(elb))
+static void extract_lines_loose_subbuffer(const MeshRenderData *mr)
{
+ BLI_assert(mr->cache->final.ibo.lines);
/* Multiply by 2 because these are edges indices. */
const int start = mr->edge_len * 2;
const int len = mr->edge_loose_len * 2;
@@ -720,17 +770,24 @@ static void extract_lines_loose_finish(const MeshRenderData *mr,
mr->cache->no_loose_wire = (len == 0);
}
-static const MeshExtract extract_lines_loose = {
- extract_lines_loose_init,
- NULL,
- NULL,
+static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, void *ibo, void *elb)
+{
+ GPU_indexbuf_build_in_place(elb, ibo);
+ extract_lines_loose_subbuffer(mr);
+ MEM_freeN(elb);
+}
+
+static const MeshExtract extract_lines_with_lines_loose = {
+ extract_lines_init,
NULL,
NULL,
- extract_lines_loose_ledge_bmesh,
- extract_lines_loose_ledge_mesh,
+ extract_lines_loop_bmesh,
+ extract_lines_loop_mesh,
+ extract_lines_ledge_bmesh,
+ extract_lines_ledge_mesh,
NULL,
NULL,
- extract_lines_loose_finish,
+ extract_lines_with_lines_loose_finish,
0,
false,
};
@@ -1480,7 +1537,7 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf)
BMVert *eve;
int v;
BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) {
- data->packed_nor[v] = GPU_normal_convert_i10_v3(eve->no);
+ data->packed_nor[v] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, eve));
}
}
else {
@@ -1492,14 +1549,11 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_pos_nor_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *_data)
+static void extract_pos_nor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data)
{
MeshExtract_PosNor_Data *data = _data;
PosNorLoop *vert = data->vbo_data + l;
- copy_v3_v3(vert->pos, loop->v->co);
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, loop->v));
vert->nor = data->packed_nor[BM_elem_index_get(loop->v)];
BMFace *efa = loop->f;
vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
@@ -1536,8 +1590,8 @@ static void extract_pos_nor_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge
int l = mr->loop_len + e * 2;
MeshExtract_PosNor_Data *data = _data;
PosNorLoop *vert = data->vbo_data + l;
- copy_v3_v3(vert[0].pos, eed->v1->co);
- copy_v3_v3(vert[1].pos, eed->v2->co);
+ copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
+ copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
vert[0].nor = data->packed_nor[BM_elem_index_get(eed->v1)];
vert[1].nor = data->packed_nor[BM_elem_index_get(eed->v2)];
}
@@ -1561,7 +1615,7 @@ static void extract_pos_nor_lvert_bmesh(const MeshRenderData *mr, int v, BMVert
int l = mr->loop_len + mr->edge_loose_len * 2 + v;
MeshExtract_PosNor_Data *data = _data;
PosNorLoop *vert = data->vbo_data + l;
- copy_v3_v3(vert->pos, eve->co);
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
vert->nor = data->packed_nor[BM_elem_index_get(eve)];
}
@@ -1627,10 +1681,10 @@ static void extract_lnor_hq_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *
normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->loop_normals[l]);
}
else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) {
- normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, loop->v->no);
+ normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_vert_no_get(mr, loop->v));
}
else {
- normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, loop->f->no);
+ normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_face_no_get(mr, loop->f));
}
}
@@ -1649,8 +1703,8 @@ static void extract_lnor_hq_loop_mesh(
}
/* Flag for paint mode overlay.
- * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In paint
- * mode it will use the unmapped data to draw the wireframe. */
+ * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In
+ * paint mode it will use the unmapped data to draw the wireframe. */
if (mpoly->flag & ME_HIDE ||
(mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
@@ -1704,10 +1758,10 @@ static void extract_lnor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loo
((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->loop_normals[l]);
}
else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) {
- ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(loop->v->no);
+ ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, loop->v));
}
else {
- ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(loop->f->no);
+ ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, loop->f));
}
BMFace *efa = loop->f;
((GPUPackedNormal *)data)[l].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
@@ -1728,8 +1782,8 @@ static void extract_lnor_loop_mesh(
}
/* Flag for paint mode overlay.
- * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In paint
- * mode it will use the unmapped data to draw the wireframe. */
+ * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In
+ * paint mode it will use the unmapped data to draw the wireframe. */
if (mpoly->flag & ME_HIDE ||
(mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
@@ -1915,7 +1969,10 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
if (mr->extract_type == MR_EXTRACT_BMESH) {
BMesh *bm = mr->bm;
for (int v = 0; v < mr->vert_len; v++) {
- copy_v3_v3(orco[v], BM_vert_at_index(bm, v)->co);
+ const BMVert *eve = BM_vert_at_index(bm, v);
+ /* Exceptional case where #bm_vert_co_get can be avoided, as we want the original coords.
+ * not the distorted ones. */
+ copy_v3_v3(orco[v], eve->co);
}
}
else {
@@ -2092,10 +2149,10 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
GPUVertFormat format = {0};
GPU_vertformat_deinterleave(&format);
- CustomData *cd_ldata = &mr->me->ldata;
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
uint32_t vcol_layers = mr->cache->cd_used.vcol;
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i);
@@ -2127,14 +2184,32 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
} gpuMeshVcol;
gpuMeshVcol *vcol_data = (gpuMeshVcol *)vbo->data;
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
- MLoopCol *mcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
- for (int l = 0; l < mr->loop_len; l++, mcol++, vcol_data++) {
- vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]);
- vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]);
- vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]);
- vcol_data->a = unit_float_to_ushort_clamp(mcol->a * (1.0f / 255.0f));
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i);
+ BMIter f_iter, l_iter;
+ BMFace *efa;
+ BMLoop *loop;
+ BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) {
+ const MLoopCol *mloopcol = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs);
+ vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
+ vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
+ vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
+ vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
+ vcol_data++;
+ }
+ }
+ }
+ else {
+ const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
+ for (int l = 0; l < mr->loop_len; l++, mloopcol++, vcol_data++) {
+ vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
+ vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
+ vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
+ vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
+ }
}
}
}
@@ -2301,14 +2376,14 @@ static void *extract_edge_fac_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_edge_fac_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *_data)
+static void extract_edge_fac_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data)
{
MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
if (BM_edge_is_manifold(loop->e)) {
- float ratio = loop_edge_factor_get(loop->f->no, loop->v->co, loop->v->no, loop->next->v->co);
+ float ratio = loop_edge_factor_get(bm_face_no_get(mr, loop->f),
+ bm_vert_co_get(mr, loop->v),
+ bm_vert_no_get(mr, loop->v),
+ bm_vert_co_get(mr, loop->next->v));
data->vbo_data[l] = ratio * 253 + 1;
}
else {
@@ -3133,7 +3208,7 @@ static void *extract_stretch_angle_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_stretch_angle_loop_bmesh(const MeshRenderData *UNUSED(mr),
+static void extract_stretch_angle_loop_bmesh(const MeshRenderData *mr,
int l,
BMLoop *loop,
void *_data)
@@ -3150,8 +3225,12 @@ static void extract_stretch_angle_loop_bmesh(const MeshRenderData *UNUSED(mr),
BMLoop *l_next_tmp = loop;
luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs);
luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs);
- compute_normalize_edge_vectors(
- auv, av, luv->uv, luv_next->uv, l_tmp->v->co, l_next_tmp->v->co);
+ compute_normalize_edge_vectors(auv,
+ av,
+ luv->uv,
+ luv_next->uv,
+ bm_vert_co_get(mr, l_tmp->v),
+ bm_vert_co_get(mr, l_next_tmp->v));
/* Save last edge. */
copy_v2_v2(last_auv, auv[1]);
copy_v3_v3(last_av, av[1]);
@@ -3167,7 +3246,12 @@ static void extract_stretch_angle_loop_bmesh(const MeshRenderData *UNUSED(mr),
else {
luv = BM_ELEM_CD_GET_VOID_P(loop, data->cd_ofs);
luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs);
- compute_normalize_edge_vectors(auv, av, luv->uv, luv_next->uv, loop->v->co, l_next->v->co);
+ compute_normalize_edge_vectors(auv,
+ av,
+ luv->uv,
+ luv_next->uv,
+ bm_vert_co_get(mr, loop->v),
+ bm_vert_co_get(mr, l_next->v));
}
edituv_get_stretch_angle(auv, av, data->vbo_data + l);
}
@@ -3307,7 +3391,7 @@ static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang)
if (mr->extract_type == MR_EXTRACT_BMESH) {
int l = 0;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- float fac = angle_normalized_v3v3(f->no, dir) / (float)M_PI;
+ float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI;
fac = overhang_remap(fac, min, max, minmax_irange);
for (int i = 0; i < f->len; i++, l++) {
r_overhang[l] = fac;
@@ -3385,7 +3469,11 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
for (int i = 0; i < mr->tri_len; i++) {
BMLoop **ltri = looptris[i];
const int index = BM_elem_index_get(ltri[0]->f);
- const float *cos[3] = {ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co};
+ const float *cos[3] = {
+ bm_vert_co_get(mr, ltri[0]->v),
+ bm_vert_co_get(mr, ltri[1]->v),
+ bm_vert_co_get(mr, ltri[2]->v),
+ };
float ray_co[3];
float ray_no[3];
@@ -3398,7 +3486,8 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
BMFace *f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, &dist, NULL, NULL);
if (f_hit && dist < face_dists[index]) {
- float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no));
+ float angle_fac = fabsf(
+ dot_v3v3(bm_face_no_get(mr, ltri[0]->f), bm_face_no_get(mr, f_hit)));
angle_fac = 1.0f - angle_fac;
angle_fac = angle_fac * angle_fac * angle_fac;
angle_fac = 1.0f - angle_fac;
@@ -3603,8 +3692,17 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
BMesh *bm = em->bm;
BMFace *f;
+ if (mr->bm_vert_coords != NULL) {
+ BKE_editmesh_cache_ensure_poly_normals(em, mr->edit_data);
+
+ /* Most likely this is already valid, ensure just in case.
+ * Needed for #BM_loop_calc_face_normal_safe_vcos. */
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+ }
+
int l = 0;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ int p = 0;
+ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, p) {
float fac = -1.0f;
if (f->len > 3) {
@@ -3613,13 +3711,23 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
fac = 0.0f;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
+ const float *no_face;
float no_corner[3];
- BM_loop_calc_face_normal_safe(l_iter, no_corner);
+ if (mr->bm_vert_coords != NULL) {
+ no_face = mr->bm_poly_normals[p];
+ BM_loop_calc_face_normal_safe_vcos(l_iter, no_face, mr->bm_vert_coords, no_corner);
+ }
+ else {
+ no_face = f->no;
+ BM_loop_calc_face_normal_safe(l_iter, no_corner);
+ }
+
/* simple way to detect (what is most likely) concave */
- if (dot_v3v3(f->no, no_corner) < 0.0f) {
+ if (dot_v3v3(no_face, no_corner) < 0.0f) {
negate_v3(no_corner);
}
- fac = max_ff(fac, angle_normalized_v3v3(f->no, no_corner));
+ fac = max_ff(fac, angle_normalized_v3v3(no_face, no_corner));
+
} while ((l_iter = l_iter->next) != l_first);
fac *= 2.0f;
}
@@ -3842,14 +3950,14 @@ static void *extract_fdots_pos_init(const MeshRenderData *mr, void *buf)
return vbo->data;
}
-static void extract_fdots_pos_loop_bmesh(const MeshRenderData *UNUSED(mr),
+static void extract_fdots_pos_loop_bmesh(const MeshRenderData *mr,
int UNUSED(l),
BMLoop *loop,
void *data)
{
float(*center)[3] = (float(*)[3])data;
float w = 1.0f / (float)loop->f->len;
- madd_v3_v3fl(center[BM_elem_index_get(loop->f)], loop->v->co, w);
+ madd_v3_v3fl(center[BM_elem_index_get(loop->f)], bm_vert_co_get(mr, loop->v), w);
}
static void extract_fdots_pos_loop_mesh(const MeshRenderData *mr,
@@ -3928,7 +4036,7 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void *
nor[f].w = NOR_AND_FLAG_HIDDEN;
}
else {
- nor[f] = GPU_normal_convert_i10_v3(efa->no);
+ nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa));
/* Select / Active Flag. */
nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
@@ -3946,7 +4054,7 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void *
nor[f].w = NOR_AND_FLAG_HIDDEN;
}
else {
- nor[f] = GPU_normal_convert_i10_v3(efa->no);
+ nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa));
/* Select / Active Flag. */
nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
@@ -4171,7 +4279,7 @@ static void *extract_skin_roots_init(const MeshRenderData *mr, void *buf)
const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_ofs);
if (vs->flag & MVERT_SKIN_ROOT) {
vbo_data->size = (vs->radius[0] + vs->radius[1]) * 0.5f;
- copy_v3_v3(vbo_data->local_pos, eve->co);
+ copy_v3_v3(vbo_data->local_pos, bm_vert_co_get(mr, eve));
vbo_data++;
root_len++;
}
@@ -4419,10 +4527,14 @@ static const MeshExtract extract_fdot_idx = {
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Loop
+/** \name ExtractTaskData
* \{ */
+typedef struct ExtractUserData {
+ void *user_data;
+} ExtractUserData;
typedef struct ExtractTaskData {
+ void *next, *prev;
const MeshRenderData *mr;
const MeshExtract *extract;
eMRIterType iter_type;
@@ -4430,9 +4542,16 @@ typedef struct ExtractTaskData {
/** Decremented each time a task is finished. */
int32_t *task_counter;
void *buf;
- void *user_data;
+ ExtractUserData *user_data;
} ExtractTaskData;
+static void extract_task_data_free(void *data)
+{
+ ExtractTaskData *task_data = data;
+ MEM_SAFE_FREE(task_data->user_data);
+ MEM_freeN(task_data);
+}
+
BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr,
const eMRIterType iter_type,
int start,
@@ -4509,31 +4628,184 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr,
}
}
-static void extract_run(TaskPool *__restrict UNUSED(pool), void *taskdata)
+static void extract_init(ExtractTaskData *data)
{
- ExtractTaskData *data = taskdata;
- mesh_extract_iter(
- data->mr, data->iter_type, data->start, data->end, data->extract, data->user_data);
+ data->user_data->user_data = data->extract->init(data->mr, data->buf);
+}
+
+static void extract_run(void *__restrict taskdata)
+{
+ ExtractTaskData *data = (ExtractTaskData *)taskdata;
+ mesh_extract_iter(data->mr,
+ data->iter_type,
+ data->start,
+ data->end,
+ data->extract,
+ data->user_data->user_data);
/* If this is the last task, we do the finish function. */
int remainin_tasks = atomic_sub_and_fetch_int32(data->task_counter, 1);
if (remainin_tasks == 0 && data->extract->finish != NULL) {
- data->extract->finish(data->mr, data->buf, data->user_data);
+ data->extract->finish(data->mr, data->buf, data->user_data->user_data);
}
}
-static void extract_range_task_create(
- TaskPool *task_pool, ExtractTaskData *taskdata, const eMRIterType type, int start, int length)
+static void extract_init_and_run(void *__restrict taskdata)
+{
+ extract_init((ExtractTaskData *)taskdata);
+ extract_run(taskdata);
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - Update Mesh Render Data
+ * \{ */
+typedef struct MeshRenderDataUpdateTaskData {
+ MeshRenderData *mr;
+ eMRIterType iter_type;
+ eMRDataType data_flag;
+} MeshRenderDataUpdateTaskData;
+
+static void mesh_render_data_update_task_data_free(MeshRenderDataUpdateTaskData *taskdata)
+{
+ BLI_assert(taskdata);
+ mesh_render_data_free(taskdata->mr);
+ MEM_freeN(taskdata);
+}
+
+static void mesh_extract_render_data_node_exec(void *__restrict task_data)
+{
+ MeshRenderDataUpdateTaskData *update_task_data = task_data;
+ mesh_render_data_update(
+ update_task_data->mr, update_task_data->iter_type, update_task_data->data_flag);
+}
+
+static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *task_graph,
+ MeshRenderData *mr,
+ const eMRIterType iter_type,
+ const eMRDataType data_flag)
+{
+ MeshRenderDataUpdateTaskData *task_data = MEM_mallocN(sizeof(MeshRenderDataUpdateTaskData),
+ __func__);
+ task_data->mr = mr;
+ task_data->iter_type = iter_type;
+ task_data->data_flag = data_flag;
+
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ mesh_extract_render_data_node_exec,
+ task_data,
+ (TaskGraphNodeFreeFunction)mesh_render_data_update_task_data_free);
+ return task_node;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - Extract Single Threaded
+ * \{ */
+typedef struct ExtractSingleThreadedTaskData {
+ ListBase task_datas;
+} ExtractSingleThreadedTaskData;
+
+static void extract_single_threaded_task_data_free(ExtractSingleThreadedTaskData *taskdata)
+{
+ BLI_assert(taskdata);
+ LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) {
+ extract_task_data_free(td);
+ }
+ BLI_listbase_clear(&taskdata->task_datas);
+ MEM_freeN(taskdata);
+}
+
+static void extract_single_threaded_task_node_exec(void *__restrict task_data)
+{
+ ExtractSingleThreadedTaskData *extract_task_data = task_data;
+ LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) {
+ extract_init_and_run(td);
+ }
+}
+
+static struct TaskNode *extract_single_threaded_task_node_create(
+ struct TaskGraph *task_graph, ExtractSingleThreadedTaskData *task_data)
+{
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ extract_single_threaded_task_node_exec,
+ task_data,
+ (TaskGraphNodeFreeFunction)extract_single_threaded_task_data_free);
+ return task_node;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - UserData Initializer
+ * \{ */
+typedef struct UserDataInitTaskData {
+ ListBase task_datas;
+ int32_t *task_counters;
+
+} UserDataInitTaskData;
+
+static void user_data_init_task_data_free(UserDataInitTaskData *taskdata)
+{
+ BLI_assert(taskdata);
+ LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) {
+ extract_task_data_free(td);
+ }
+ BLI_listbase_clear(&taskdata->task_datas);
+ MEM_SAFE_FREE(taskdata->task_counters);
+ MEM_freeN(taskdata);
+}
+
+static void user_data_init_task_data_exec(void *__restrict task_data)
+{
+ UserDataInitTaskData *extract_task_data = task_data;
+ LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) {
+ extract_init(td);
+ }
+}
+
+static struct TaskNode *user_data_init_task_node_create(struct TaskGraph *task_graph,
+ UserDataInitTaskData *task_data)
+{
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ user_data_init_task_data_exec,
+ task_data,
+ (TaskGraphNodeFreeFunction)user_data_init_task_data_free);
+ return task_node;
+}
+
+/** \} */
+/* ---------------------------------------------------------------------- */
+/** \name Extract Loop
+ * \{ */
+
+static void extract_range_task_create(struct TaskGraph *task_graph,
+ struct TaskNode *task_node_user_data_init,
+ ExtractTaskData *taskdata,
+ const eMRIterType type,
+ int start,
+ int length)
{
taskdata = MEM_dupallocN(taskdata);
atomic_add_and_fetch_int32(taskdata->task_counter, 1);
taskdata->iter_type = type;
taskdata->start = start;
taskdata->end = start + length;
- BLI_task_pool_push(task_pool, extract_run, taskdata, true, NULL);
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph, extract_run, taskdata, MEM_freeN);
+ BLI_task_graph_edge_create(task_node_user_data_init, task_node);
}
-static void extract_task_create(TaskPool *task_pool,
+static void extract_task_create(struct TaskGraph *task_graph,
+ struct TaskNode *task_node_mesh_render_data,
+ struct TaskNode *task_node_user_data_init,
+ ListBase *single_threaded_task_datas,
+ ListBase *user_data_init_task_datas,
const Scene *scene,
const MeshRenderData *mr,
const MeshExtract *extract,
@@ -4551,58 +4823,75 @@ static void extract_task_create(TaskPool *task_pool,
/* Divide extraction of the VBO/IBO into sensible chunks of works. */
ExtractTaskData *taskdata = MEM_mallocN(sizeof(*taskdata), "ExtractTaskData");
+ taskdata->next = NULL;
+ taskdata->prev = NULL;
taskdata->mr = mr;
taskdata->extract = extract;
taskdata->buf = buf;
- taskdata->user_data = extract->init(mr, buf);
+
+ /* ExtractUserData is shared between the iterations as it holds counters to detect if the
+ * extraction is finished. To make sure the duplication of the userdata does not create a new
+ * instance of the counters we allocate the userdata in its own container.
+ *
+ * This structure makes sure that when extract_init is called, that the user data of all
+ * iterations are updated. */
+ taskdata->user_data = MEM_callocN(sizeof(ExtractUserData), __func__);
taskdata->iter_type = mesh_extract_iter_type(extract);
taskdata->task_counter = task_counter;
taskdata->start = 0;
taskdata->end = INT_MAX;
/* Simple heuristic. */
- const bool use_thread = (mr->loop_len + mr->loop_loose_len) > 8192;
+ const int chunk_size = 8192;
+ const bool use_thread = (mr->loop_len + mr->loop_loose_len) > chunk_size;
if (use_thread && extract->use_threading) {
+
/* Divide task into sensible chunks. */
- const int chunk_size = 8192;
if (taskdata->iter_type & MR_ITER_LOOPTRI) {
for (int i = 0; i < mr->tri_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LOOPTRI, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOPTRI, i, chunk_size);
}
}
if (taskdata->iter_type & MR_ITER_LOOP) {
for (int i = 0; i < mr->poly_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LOOP, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOP, i, chunk_size);
}
}
if (taskdata->iter_type & MR_ITER_LEDGE) {
for (int i = 0; i < mr->edge_loose_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LEDGE, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LEDGE, i, chunk_size);
}
}
if (taskdata->iter_type & MR_ITER_LVERT) {
for (int i = 0; i < mr->vert_loose_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LVERT, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LVERT, i, chunk_size);
}
}
- MEM_freeN(taskdata);
+ BLI_addtail(user_data_init_task_datas, taskdata);
}
else if (use_thread) {
/* One task for the whole VBO. */
(*task_counter)++;
- BLI_task_pool_push(task_pool, extract_run, taskdata, true, NULL);
+ struct TaskNode *one_task = BLI_task_graph_node_create(
+ task_graph, extract_init_and_run, taskdata, extract_task_data_free);
+ BLI_task_graph_edge_create(task_node_mesh_render_data, one_task);
}
else {
/* Single threaded extraction. */
(*task_counter)++;
- extract_run(NULL, taskdata);
- MEM_freeN(taskdata);
+ BLI_addtail(single_threaded_task_datas, taskdata);
}
}
-void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
+void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
+ MeshBatchCache *cache,
MeshBufferCache mbc,
Mesh *me,
+
const bool is_editmode,
const bool is_paint_mode,
const float obmat[4][4],
@@ -4614,9 +4903,41 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
const ToolSettings *ts,
const bool use_hide)
{
+ /* For each mesh where batches needs to be updated a sub-graph will be added to the task_graph.
+ * This sub-graph starts with an extract_render_data_node. This fills/converts the required data
+ * from Mesh.
+ *
+ * Small extractions and extractions that can't be multi-threaded are grouped in a single
+ * `extract_single_threaded_task_node`.
+ *
+ * Other extractions will create a node for each loop exceeding 8192 items. these nodes are
+ * linked to the `user_data_init_task_node`. the `user_data_init_task_node` prepares the userdata
+ * needed for the extraction based on the data extracted from the mesh. counters are used to
+ * check if the finalize of a task has to be called.
+ *
+ * Mesh extraction sub graph
+ *
+ * +----------------------+
+ * +-----> | extract_task1_loop_1 |
+ * | +----------------------+
+ * +------------------+ +----------------------+ +----------------------+
+ * | mesh_render_data | --> | | --> | extract_task1_loop_2 |
+ * +------------------+ | | +----------------------+
+ * | | | +----------------------+
+ * | | user_data_init | --> | extract_task2_loop_1 |
+ * v | | +----------------------+
+ * +------------------+ | | +----------------------+
+ * | single_threaded | | | --> | extract_task2_loop_2 |
+ * +------------------+ +----------------------+ +----------------------+
+ * | +----------------------+
+ * +-----> | extract_task2_loop_3 |
+ * +----------------------+
+ */
eMRIterType iter_flag = 0;
eMRDataType data_flag = 0;
+ const bool do_lines_loose_subbuffer = mbc.ibo.lines_loose != NULL;
+
#define TEST_ASSIGN(type, type_lowercase, name) \
do { \
if (DRW_TEST_ASSIGN_##type(mbc.type_lowercase.name)) { \
@@ -4654,7 +4975,6 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
TEST_ASSIGN(IBO, ibo, fdots);
TEST_ASSIGN(IBO, ibo, lines_paint_mask);
TEST_ASSIGN(IBO, ibo, lines_adjacency);
- TEST_ASSIGN(IBO, ibo, lines_loose);
TEST_ASSIGN(IBO, ibo, edituv_tris);
TEST_ASSIGN(IBO, ibo, edituv_lines);
TEST_ASSIGN(IBO, ibo, edituv_points);
@@ -4666,16 +4986,8 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
double rdata_start = PIL_check_seconds_timer();
#endif
- MeshRenderData *mr = mesh_render_data_create(me,
- is_editmode,
- is_paint_mode,
- obmat,
- do_final,
- do_uvedit,
- iter_flag,
- data_flag,
- cd_layer_used,
- ts);
+ MeshRenderData *mr = mesh_render_data_create(
+ me, is_editmode, is_paint_mode, obmat, do_final, do_uvedit, cd_layer_used, ts);
mr->cache = cache; /* HACK */
mr->use_hide = use_hide;
mr->use_subsurf_fdots = use_subsurf_fdots;
@@ -4685,20 +4997,32 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
double rdata_end = PIL_check_seconds_timer();
#endif
- TaskPool *task_pool;
-
- /* Create a suspended pool as the finalize method could be called too early.
- * See `extract_run`. */
- task_pool = BLI_task_pool_create_suspended(NULL, TASK_PRIORITY_HIGH);
-
size_t counters_size = (sizeof(mbc) / sizeof(void *)) * sizeof(int32_t);
int32_t *task_counters = MEM_callocN(counters_size, __func__);
int counter_used = 0;
+ struct TaskNode *task_node_mesh_render_data = mesh_extract_render_data_node_create(
+ task_graph, mr, iter_flag, data_flag);
+ ExtractSingleThreadedTaskData *single_threaded_task_data = MEM_callocN(
+ sizeof(ExtractSingleThreadedTaskData), __func__);
+ UserDataInitTaskData *user_data_init_task_data = MEM_callocN(sizeof(UserDataInitTaskData),
+ __func__);
+ user_data_init_task_data->task_counters = task_counters;
+ struct TaskNode *task_node_user_data_init = user_data_init_task_node_create(
+ task_graph, user_data_init_task_data);
+
#define EXTRACT(buf, name) \
if (mbc.buf.name) { \
- extract_task_create( \
- task_pool, scene, mr, &extract_##name, mbc.buf.name, &task_counters[counter_used++]); \
+ extract_task_create(task_graph, \
+ task_node_mesh_render_data, \
+ task_node_user_data_init, \
+ &single_threaded_task_data->task_datas, \
+ &user_data_init_task_data->task_datas, \
+ scene, \
+ mr, \
+ &extract_##name, \
+ mbc.buf.name, \
+ &task_counters[counter_used++]); \
} \
((void)0)
@@ -4726,7 +5050,33 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
EXTRACT(vbo, skin_roots);
EXTRACT(ibo, tris);
- EXTRACT(ibo, lines);
+ if (mbc.ibo.lines) {
+ /* When `lines` and `lines_loose` are requested, schedule lines extraction that also creates
+ * the `lines_loose` sub-buffer. */
+ const MeshExtract *lines_extractor = do_lines_loose_subbuffer ?
+ &extract_lines_with_lines_loose :
+ &extract_lines;
+ extract_task_create(task_graph,
+ task_node_mesh_render_data,
+ task_node_user_data_init,
+ &single_threaded_task_data->task_datas,
+ &user_data_init_task_data->task_datas,
+ scene,
+ mr,
+ lines_extractor,
+ mbc.ibo.lines,
+ &task_counters[counter_used++]);
+ }
+ else {
+ if (do_lines_loose_subbuffer) {
+ /* When `lines_loose` is requested without `lines` we can create the sub-buffer on the fly as
+ * the `lines` buffer should then already be up-to-date.
+ * (see `DRW_batch_requested(cache->batch.loose_edges, GPU_PRIM_LINES)` in
+ * `DRW_mesh_batch_cache_create_requested`).
+ */
+ extract_lines_loose_subbuffer(mr);
+ }
+ }
EXTRACT(ibo, points);
EXTRACT(ibo, fdots);
EXTRACT(ibo, lines_paint_mask);
@@ -4736,27 +5086,29 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
EXTRACT(ibo, edituv_points);
EXTRACT(ibo, edituv_fdots);
- /* TODO(fclem) Ideally, we should have one global pool for all
- * objects and wait for finish only before drawing when buffers
- * need to be ready. */
- BLI_task_pool_work_and_wait(task_pool);
-
- /* The next task(s) rely on the result of the tasks above. */
+ /* Only create the edge when there is user data that needs to be initialized.
+ * The task is still part of the graph so the task_data will be freed when the graph is freed.
+ */
+ if (!BLI_listbase_is_empty(&user_data_init_task_data->task_datas)) {
+ BLI_task_graph_edge_create(task_node_mesh_render_data, task_node_user_data_init);
+ }
- /* The `lines_loose` is a sub buffer from `ibo.lines`.
- * We schedule it here due to potential synchronization issues.*/
- EXTRACT(ibo, lines_loose);
+ if (!BLI_listbase_is_empty(&single_threaded_task_data->task_datas)) {
+ struct TaskNode *task_node = extract_single_threaded_task_node_create(
+ task_graph, single_threaded_task_data);
+ BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
+ }
+ else {
+ extract_single_threaded_task_data_free(single_threaded_task_data);
+ }
- BLI_task_pool_work_and_wait(task_pool);
+ /* Trigger the sub-graph for this mesh. */
+ BLI_task_graph_node_push_work(task_node_mesh_render_data);
#undef EXTRACT
- BLI_task_pool_free(task_pool);
- MEM_freeN(task_counters);
-
- mesh_render_data_free(mr);
-
#ifdef DEBUG_TIME
+ BLI_task_graph_work_and_wait(task_graph);
double end = PIL_check_seconds_timer();
static double avg = 0;
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index de0cd027ece..80649143537 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -31,6 +31,7 @@ struct ListBase;
struct ModifierData;
struct PTCacheEdit;
struct ParticleSystem;
+struct TaskGraph;
struct Curve;
struct Hair;
@@ -150,7 +151,8 @@ int DRW_volume_material_count_get(struct Volume *volume);
struct GPUBatch *DRW_volume_batch_cache_get_wireframes_face(struct Volume *volume);
/* Mesh */
-void DRW_mesh_batch_cache_create_requested(struct Object *ob,
+void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
+ struct Object *ob,
struct Mesh *me,
const struct Scene *scene,
const bool is_paint_mode,
@@ -208,6 +210,7 @@ enum {
VFLAG_EDGE_SEAM = 1 << 4,
VFLAG_EDGE_SHARP = 1 << 5,
VFLAG_EDGE_FREESTYLE = 1 << 6,
+ VFLAG_HANDLE_SELECTED = 1 << 7,
/* Beware to not go over 1 << 7 (it's a byte flag)
* (see gpu_shader_edit_mesh_overlay_geom.glsl) */
};
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c
index 5642ffba4f1..c6112994b65 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.c
+++ b/source/blender/draw/intern/draw_cache_impl_curve.c
@@ -685,14 +685,20 @@ static void curve_create_edit_curves_nor(CurveRenderData *rdata, GPUVertBuf *vbo
BLI_assert(vbo_len_used == verts_len_capacity);
}
-static char beztriple_vflag_get(
- CurveRenderData *rdata, char flag, char col_id, int v_idx, int nu_id, bool handle_point)
+static char beztriple_vflag_get(CurveRenderData *rdata,
+ char flag,
+ char col_id,
+ int v_idx,
+ int nu_id,
+ bool handle_point,
+ const bool handle_selected)
{
char vflag = 0;
SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED);
SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE);
SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB);
SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE);
+ SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_HANDLE_SELECTED);
/* handle color id */
vflag |= col_id << COLOR_SHIFT;
return vflag;
@@ -754,11 +760,13 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata,
for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next, nu_id++) {
const BezTriple *bezt = nu->bezt;
const BPoint *bp = nu->bp;
+
if (bezt) {
for (int a = 0; a < nu->pntsu; a++, bezt++) {
if (bezt->hide == true) {
continue;
}
+ const bool handle_selected = BEZT_ISSEL_ANY(bezt);
if (elbp_verts) {
GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 0);
@@ -771,9 +779,9 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata,
}
if (vbo_data) {
const char vflag[3] = {
- beztriple_vflag_get(rdata, bezt->f1, bezt->h1, a, nu_id, true),
- beztriple_vflag_get(rdata, bezt->f2, bezt->h1, a, nu_id, false),
- beztriple_vflag_get(rdata, bezt->f3, bezt->h2, a, nu_id, true),
+ beztriple_vflag_get(rdata, bezt->f1, bezt->h1, a, nu_id, true, handle_selected),
+ beztriple_vflag_get(rdata, bezt->f2, bezt->h1, a, nu_id, false, handle_selected),
+ beztriple_vflag_get(rdata, bezt->f3, bezt->h2, a, nu_id, true, handle_selected),
};
for (int j = 0; j < 3; j++) {
GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used + j, &vflag[j]);
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c
index ee148e0934d..b4974330043 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.c
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c
@@ -102,6 +102,7 @@ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
cache->is_dirty = true;
cache->cache_frame = cfra;
+
return cache;
}
@@ -385,7 +386,8 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
.vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */
.tri_len = 0,
};
- BKE_gpencil_visible_stroke_iter(ob, NULL, gp_object_verts_count_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(
+ NULL, ob, NULL, gp_object_verts_count_cb, &iter, do_onion, cfra);
/* Create VBOs. */
GPUVertFormat *format = gpencil_stroke_format();
@@ -401,7 +403,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len);
/* Fill buffers with data. */
- BKE_gpencil_visible_stroke_iter(ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra);
/* Mark last 2 verts as invalid. */
for (int i = 0; i < 2; i++) {
@@ -475,7 +477,7 @@ GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob)
/* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */
bool do_onion = true;
- BKE_gpencil_visible_stroke_iter(ob, NULL, gp_lines_indices_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gp_lines_indices_cb, &iter, do_onion, cfra);
GPUIndexBuf *ibo = GPU_indexbuf_build(&iter.ibo);
@@ -724,7 +726,8 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
iter.verts = (gpEditVert *)cache->edit_vbo->data;
/* Fill buffers with data. */
- BKE_gpencil_visible_stroke_iter(ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(
+ NULL, ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra);
/* Create the batches */
cache->edit_points_batch = GPU_batch_create(GPU_PRIM_POINTS, cache->vbo, NULL);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 649bcd7bbaa..99e285a18f1 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -33,6 +33,7 @@
#include "BLI_math_bits.h"
#include "BLI_math_vector.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "DNA_mesh_types.h"
@@ -96,11 +97,25 @@ static void mesh_cd_calc_edit_uv_layer(const Mesh *UNUSED(me), DRW_MeshCDMask *c
cd_used->edit_uv = 1;
}
+BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me)
+{
+ switch ((eMeshWrapperType)me->runtime.wrapper_type) {
+ case ME_WRAPPER_TYPE_MDATA:
+ return &me->ldata;
+ break;
+ case ME_WRAPPER_TYPE_BMESH:
+ return &me->edit_mesh->bm->ldata;
+ break;
+ }
+
+ BLI_assert(0);
+ return &me->ldata;
+}
+
static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
- const CustomData *cd_ldata = &me_final->ldata;
-
+ const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
if (layer != -1) {
cd_used->uv |= (1 << layer);
@@ -110,8 +125,7 @@ static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used
static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
- const CustomData *cd_ldata = &me_final->ldata;
-
+ const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
int layer = CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV);
if (layer != -1) {
cd_used->uv |= (1 << layer);
@@ -121,8 +135,7 @@ static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd
static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
- const CustomData *cd_ldata = &me_final->ldata;
-
+ const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
if (layer != -1) {
cd_used->vcol |= (1 << layer);
@@ -134,7 +147,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
int gpumat_array_len)
{
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
- const CustomData *cd_ldata = &me_final->ldata;
+ const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
/* See: DM_vertex_attributes_from_gpu for similar logic */
DRW_MeshCDMask cd_used;
@@ -302,7 +315,7 @@ static void drw_mesh_weight_state_extract(Object *ob,
wstate->alert_mode = ts->weightuser;
if (paint_mode && ts->multipaint) {
- /* Multipaint needs to know all selected bones, not just the active group.
+ /* Multi-paint needs to know all selected bones, not just the active group.
* This is actually a relatively expensive operation, but caching would be difficult. */
wstate->defgroup_sel = BKE_object_defgroup_selected_get(
ob, wstate->defgroup_len, &wstate->defgroup_sel_count);
@@ -1007,9 +1020,14 @@ void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime)
}
/* Can be called for any surface type. Mesh *me is the final mesh. */
-void DRW_mesh_batch_cache_create_requested(
- Object *ob, Mesh *me, const Scene *scene, const bool is_paint_mode, const bool use_hide)
-{
+void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
+ Object *ob,
+ Mesh *me,
+ const Scene *scene,
+ const bool is_paint_mode,
+ const bool use_hide)
+{
+ BLI_assert(task_graph);
GPUIndexBuf **saved_elem_ranges = NULL;
const ToolSettings *ts = NULL;
if (scene) {
@@ -1366,7 +1384,8 @@ void DRW_mesh_batch_cache_create_requested(
false;
if (do_uvcage) {
- mesh_buffer_cache_create_requested(cache,
+ mesh_buffer_cache_create_requested(task_graph,
+ cache,
cache->uv_cage,
me,
is_editmode,
@@ -1382,7 +1401,8 @@ void DRW_mesh_batch_cache_create_requested(
}
if (do_cage) {
- mesh_buffer_cache_create_requested(cache,
+ mesh_buffer_cache_create_requested(task_graph,
+ cache,
cache->cage,
me,
is_editmode,
@@ -1397,7 +1417,8 @@ void DRW_mesh_batch_cache_create_requested(
true);
}
- mesh_buffer_cache_create_requested(cache,
+ mesh_buffer_cache_create_requested(task_graph,
+ cache,
cache->final,
me,
is_editmode,
@@ -1410,10 +1431,12 @@ void DRW_mesh_batch_cache_create_requested(
scene,
ts,
use_hide);
-
#ifdef DEBUG
check:
/* Make sure all requested batches have been setup. */
+ /* TODO(jbakker): we should move this to the draw_manager but that needs refactoring and
+ * additional looping.*/
+ BLI_task_graph_work_and_wait(task_graph);
for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
}
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index f14cdc0dbde..656d72b2808 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -172,23 +172,11 @@ bool DRW_object_axis_orthogonal_to_view(Object *ob, int axis);
/* This creates a shading group with display hairs.
* The draw call is already added by this function, just add additional uniforms. */
-struct DRWShadingGroup *DRW_shgroup_hair_create(struct Object *object,
- struct ParticleSystem *psys,
- struct ModifierData *md,
- struct DRWPass *hair_pass,
- struct GPUShader *shader);
-
struct DRWShadingGroup *DRW_shgroup_hair_create_sub(struct Object *object,
struct ParticleSystem *psys,
struct ModifierData *md,
struct DRWShadingGroup *shgrp);
-struct DRWShadingGroup *DRW_shgroup_material_hair_create(struct Object *object,
- struct ParticleSystem *psys,
- struct ModifierData *md,
- struct DRWPass *hair_pass,
- struct GPUMaterial *material);
-
void DRW_hair_init(void);
void DRW_hair_update(void);
void DRW_hair_free(void);
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index ed7c72ac116..2fdaf0d5345 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -124,13 +124,10 @@ void DRW_hair_init(void)
}
}
-static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
- ParticleSystem *psys,
- ModifierData *md,
- DRWPass *hair_pass,
- DRWShadingGroup *shgrp_parent,
- struct GPUMaterial *gpu_mat,
- GPUShader *gpu_shader)
+DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
+ ParticleSystem *psys,
+ ModifierData *md,
+ DRWShadingGroup *shgrp_parent)
{
/* TODO(fclem): Pass the scene as parameter */
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -154,24 +151,7 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
need_ft_update = hair_ensure_procedural_data(object, &hair_cache, subdiv, thickness_res);
}
- DRWShadingGroup *shgrp;
- if (shgrp_parent) {
- shgrp = DRW_shgroup_create_sub(shgrp_parent);
- }
- else if (gpu_mat) {
- shgrp = DRW_shgroup_material_create(gpu_mat, hair_pass);
- }
- else if (gpu_shader) {
- shgrp = DRW_shgroup_create(gpu_shader, hair_pass);
- }
- else {
- shgrp = NULL;
- BLI_assert(0);
- }
-
- if (shgrp == NULL) {
- return NULL;
- }
+ DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent);
/* TODO optimize this. Only bind the ones GPUMaterial needs. */
for (int i = 0; i < hair_cache->num_uv_layers; i++) {
@@ -240,10 +220,7 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1);
DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape);
- DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[0]", dupli_mat[0]);
- DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[1]", dupli_mat[1]);
- DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[2]", dupli_mat[2]);
- DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[3]", dupli_mat[3]);
+ DRW_shgroup_uniform_vec4_array_copy(shgrp, "hairDupliMatrix", dupli_mat, 4);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip);
DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip);
@@ -287,29 +264,6 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
return shgrp;
}
-DRWShadingGroup *DRW_shgroup_hair_create(
- Object *object, ParticleSystem *psys, ModifierData *md, DRWPass *hair_pass, GPUShader *shader)
-{
- return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, NULL, shader);
-}
-
-DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
- ParticleSystem *psys,
- ModifierData *md,
- DRWShadingGroup *shgrp)
-{
- return drw_shgroup_create_hair_procedural_ex(object, psys, md, NULL, shgrp, NULL, NULL);
-}
-
-DRWShadingGroup *DRW_shgroup_material_hair_create(Object *object,
- ParticleSystem *psys,
- ModifierData *md,
- DRWPass *hair_pass,
- struct GPUMaterial *material)
-{
- return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, material, NULL);
-}
-
void DRW_hair_update(void)
{
#ifndef USE_TRANSFORM_FEEDBACK
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 970578c7438..e7dff422105 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -27,6 +27,7 @@
#include "BLI_memblock.h"
#include "BLI_rect.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "BLF_api.h"
@@ -111,17 +112,6 @@ static ListBase DRW_engines = {NULL, NULL};
static void drw_state_prepare_clean_for_draw(DRWManager *dst)
{
memset(dst, 0x0, offsetof(DRWManager, gl_context));
-
- /* Maybe not the best place for this. */
- if (!DST.uniform_names.buffer) {
- DST.uniform_names.buffer = MEM_callocN(DRW_UNIFORM_BUFFER_NAME, "Name Buffer");
- DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
- }
- else if (DST.uniform_names.buffer_len > DRW_UNIFORM_BUFFER_NAME) {
- DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer, DRW_UNIFORM_BUFFER_NAME);
- DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
- }
- DST.uniform_names.buffer_ofs = 0;
}
/* This function is used to reset draw manager to a state
@@ -136,6 +126,23 @@ static void drw_state_ensure_not_reused(DRWManager *dst)
#endif
/* -------------------------------------------------------------------- */
+/** \name Threading
+ * \{ */
+static void drw_task_graph_init(void)
+{
+ BLI_assert(DST.task_graph == NULL);
+ DST.task_graph = BLI_task_graph_create();
+}
+
+static void drw_task_graph_deinit(void)
+{
+ BLI_task_graph_work_and_wait(DST.task_graph);
+ BLI_task_graph_free(DST.task_graph);
+ DST.task_graph = NULL;
+}
+/* \} */
+
+/* -------------------------------------------------------------------- */
/** \name Settings
* \{ */
@@ -584,9 +591,6 @@ static void drw_viewport_var_init(void)
ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d);
}
- /* Alloc array of texture reference. */
- memset(&DST.RST, 0x0, sizeof(DST.RST));
-
if (G_draw.view_ubo == NULL) {
G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(DRWViewUboStorage), NULL);
}
@@ -1424,6 +1428,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
/* reuse if caller sets */
.evil_C = DST.draw_ctx.evil_C,
};
+ drw_task_graph_init();
drw_context_state_init();
drw_viewport_var_init();
@@ -1488,6 +1493,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
#endif
}
+ drw_task_graph_deinit();
DRW_stats_begin();
GPU_framebuffer_bind(DST.default_framebuffer);
@@ -1768,7 +1774,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
DST.options.is_image_render = true;
DST.options.is_scene_render = true;
DST.options.draw_background = scene->r.alphamode == R_ADDSKY;
-
DST.draw_ctx = (DRWContextState){
.scene = scene,
.view_layer = view_layer,
@@ -1853,9 +1858,9 @@ void DRW_render_object_iter(
void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph))
{
const DRWContextState *draw_ctx = DRW_context_state_get();
-
DRW_hair_init();
+ drw_task_graph_init();
const int object_type_exclude_viewport = draw_ctx->v3d ?
draw_ctx->v3d->object_type_exclude_viewport :
0;
@@ -1878,6 +1883,7 @@ void DRW_render_object_iter(
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
drw_duplidata_free();
+ drw_task_graph_deinit();
}
/* Assume a valid gl context is bound (and that the gl_context_mutex has been acquired).
@@ -2049,7 +2055,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
DST.viewport = viewport;
DST.options.is_select = true;
-
+ drw_task_graph_init();
/* Get list of enabled engines */
if (use_obedit) {
drw_engines_enable_overlays();
@@ -2159,6 +2165,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
}
drw_duplidata_free();
+ drw_task_graph_deinit();
drw_engines_cache_finish();
DRW_render_instance_buffer_finish();
@@ -2239,7 +2246,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph,
.engine_type = engine_type,
.depsgraph = depsgraph,
};
-
+ drw_task_graph_init();
drw_engines_data_validate();
/* Setup framebuffer */
@@ -2283,6 +2290,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph,
DRW_render_instance_buffer_finish();
}
+ drw_task_graph_deinit();
/* Start Drawing */
DRW_state_reset();
@@ -2372,7 +2380,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons
.obact = OBACT(view_layer),
.depsgraph = depsgraph,
};
-
+ drw_task_graph_init();
drw_context_state_init();
/* Setup viewport */
@@ -2407,6 +2415,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons
drw_resource_buffer_finish(DST.vmempool);
#endif
}
+ drw_task_graph_deinit();
/* Start Drawing */
DRW_state_reset();
@@ -2470,8 +2479,10 @@ void DRW_draw_depth_object(
else {
batch = DRW_mesh_batch_cache_get_surface(me);
}
-
- DRW_mesh_batch_cache_create_requested(object, me, scene, false, true);
+ struct TaskGraph *task_graph = BLI_task_graph_create();
+ DRW_mesh_batch_cache_create_requested(task_graph, object, me, scene, false, true);
+ BLI_task_graph_work_and_wait(task_graph);
+ BLI_task_graph_free(task_graph);
const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
GPU_SHADER_CFG_DEFAULT;
@@ -2714,8 +2725,6 @@ void DRW_engines_free(void)
DRW_TEXTURE_FREE_SAFE(G_draw.ramp);
DRW_TEXTURE_FREE_SAFE(G_draw.weight_ramp);
- MEM_SAFE_FREE(DST.uniform_names.buffer);
-
if (DST.draw_list) {
GPU_draw_list_discard(DST.draw_list);
}
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index f6d8179b193..6cae2a4f9f6 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -31,6 +31,7 @@
#include "BLI_assert.h"
#include "BLI_linklist.h"
#include "BLI_memblock.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "GPU_batch.h"
@@ -276,10 +277,9 @@ typedef enum {
DRW_UNIFORM_FLOAT,
DRW_UNIFORM_FLOAT_COPY,
DRW_UNIFORM_TEXTURE,
- DRW_UNIFORM_TEXTURE_PERSIST,
DRW_UNIFORM_TEXTURE_REF,
DRW_UNIFORM_BLOCK,
- DRW_UNIFORM_BLOCK_PERSIST,
+ DRW_UNIFORM_BLOCK_REF,
DRW_UNIFORM_TFEEDBACK_TARGET,
/** Per drawcall uniforms/UBO */
DRW_UNIFORM_BLOCK_OBMATS,
@@ -290,7 +290,6 @@ typedef enum {
DRW_UNIFORM_BASE_INSTANCE,
DRW_UNIFORM_MODEL_MATRIX,
DRW_UNIFORM_MODEL_MATRIX_INVERSE,
- DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX,
/* WARNING: set DRWUniform->type
* bit length accordingly. */
} DRWUniformType;
@@ -299,15 +298,28 @@ struct DRWUniform {
union {
/* For reference or array/vector types. */
const void *pvalue;
- /* Single values. */
+ /* DRW_UNIFORM_TEXTURE */
+ struct {
+ union {
+ GPUTexture *texture;
+ GPUTexture **texture_ref;
+ };
+ eGPUSamplerState sampler_state;
+ };
+ /* DRW_UNIFORM_BLOCK */
+ union {
+ GPUUniformBuffer *block;
+ GPUUniformBuffer **block_ref;
+ };
+ /* DRW_UNIFORM_FLOAT_COPY */
float fvalue[4];
+ /* DRW_UNIFORM_INT_COPY */
int ivalue[4];
};
- int location;
- uint32_t type : 5; /* DRWUniformType */
- uint32_t length : 5; /* cannot be more than 16 */
- uint32_t arraysize : 5; /* cannot be more than 16 too */
- uint32_t name_ofs : 17; /* name offset in name buffer. */
+ int location; /* Uniform location or binding point for textures and ubos. */
+ uint8_t type; /* DRWUniformType */
+ uint8_t length; /* Length of vector types. */
+ uint8_t arraysize; /* Array size of scalar/vector types. */
};
struct DRWShadingGroup {
@@ -322,10 +334,13 @@ struct DRWShadingGroup {
} cmd;
union {
+ /* This struct is used during cache populate. */
struct {
int objectinfo; /* Equal to 1 if the shader needs obinfos. */
DRWResourceHandle pass_handle; /* Memblock key to parent pass. */
};
+ /* This struct is used after cache populate if using the Z sorting.
+ * It will not conflict with the above struct. */
struct {
float distance; /* Distance from camera. */
uint original_index; /* Original position inside the shgroup list. */
@@ -342,6 +357,13 @@ struct DRWPass {
DRWShadingGroup *last;
} shgroups;
+ /* Draw the shgroups of this pass instead.
+ * This avoid duplicating drawcalls/shgroups
+ * for similar passes. */
+ DRWPass *original;
+ /* Link list of additional passes to render. */
+ DRWPass *next;
+
DRWResourceHandle handle;
DRWState state;
char name[MAX_PASS_NAME];
@@ -525,6 +547,8 @@ typedef struct DRWManager {
uint select_id;
#endif
+ struct TaskGraph *task_graph;
+
/* ---------- Nothing after this point is cleared after use ----------- */
/* gl_context serves as the offset for clearing only
@@ -537,31 +561,11 @@ typedef struct DRWManager {
GPUDrawList *draw_list;
- /** GPU Resource State: Memory storage between drawing. */
- struct {
- /* High end GPUs supports up to 32 binds per shader stage.
- * We only use textures during the vertex and fragment stage,
- * so 2 * 32 slots is a nice limit. */
- GPUTexture *bound_texs[DST_MAX_SLOTS];
- uint64_t bound_tex_slots;
- uint64_t bound_tex_slots_persist;
-
- GPUUniformBuffer *bound_ubos[DST_MAX_SLOTS];
- uint64_t bound_ubo_slots;
- uint64_t bound_ubo_slots_persist;
- } RST;
-
struct {
/* TODO(fclem) optimize: use chunks. */
DRWDebugLine *lines;
DRWDebugSphere *spheres;
} debug;
-
- struct {
- char *buffer;
- uint buffer_len;
- uint buffer_ofs;
- } uniform_names;
} DRWManager;
extern DRWManager DST; /* TODO: get rid of this and allow multi-threaded rendering. */
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index ff27fa958ef..ea67dd87772 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -170,13 +170,20 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool)
/** \name Uniforms (DRW_shgroup_uniform)
* \{ */
-static DRWUniform *drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
- int loc,
- DRWUniformType type,
- const void *value,
- int length,
- int arraysize)
-{
+static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
+ int loc,
+ DRWUniformType type,
+ const void *value,
+ eGPUSamplerState sampler_state,
+ int length,
+ int arraysize)
+{
+ if (loc == -1) {
+ /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
+ // BLI_assert(0);
+ return;
+ }
+
DRWUniformChunk *unichunk = shgroup->uniforms;
/* Happens on first uniform or if chunk is full. */
if (!unichunk || unichunk->uniform_used == unichunk->uniform_len) {
@@ -202,22 +209,24 @@ static DRWUniform *drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
BLI_assert(length <= 4);
memcpy(uni->fvalue, value, sizeof(float) * length);
break;
+ case DRW_UNIFORM_BLOCK:
+ uni->block = (GPUUniformBuffer *)value;
+ break;
+ case DRW_UNIFORM_BLOCK_REF:
+ uni->block_ref = (GPUUniformBuffer **)value;
+ break;
+ case DRW_UNIFORM_TEXTURE:
+ uni->texture = (GPUTexture *)value;
+ uni->sampler_state = sampler_state;
+ break;
+ case DRW_UNIFORM_TEXTURE_REF:
+ uni->texture_ref = (GPUTexture **)value;
+ uni->sampler_state = sampler_state;
+ break;
default:
uni->pvalue = (const float *)value;
break;
}
-
- return uni;
-}
-
-static void drw_shgroup_builtin_uniform(
- DRWShadingGroup *shgroup, int builtin, const void *value, int length, int arraysize)
-{
- int loc = GPU_shader_get_builtin_uniform(shgroup->shader, builtin);
-
- if (loc != -1) {
- drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_FLOAT, value, length, arraysize);
- }
}
static void drw_shgroup_uniform(DRWShadingGroup *shgroup,
@@ -227,61 +236,29 @@ static void drw_shgroup_uniform(DRWShadingGroup *shgroup,
int length,
int arraysize)
{
- int location;
- if (ELEM(type, DRW_UNIFORM_BLOCK, DRW_UNIFORM_BLOCK_PERSIST)) {
- location = GPU_shader_get_uniform_block(shgroup->shader, name);
- }
- else {
- location = GPU_shader_get_uniform(shgroup->shader, name);
- }
-
- if (location == -1) {
- /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
- // BLI_assert(0);
- return;
- }
-
BLI_assert(arraysize > 0 && arraysize <= 16);
BLI_assert(length >= 0 && length <= 16);
-
- DRWUniform *uni = drw_shgroup_uniform_create_ex(
- shgroup, location, type, value, length, arraysize);
-
- /* If location is -2, the uniform has not yet been queried.
- * We save the name for query just before drawing. */
- if (location == -2 || DRW_DEBUG_USE_UNIFORM_NAME) {
- int ofs = DST.uniform_names.buffer_ofs;
- int max_len = DST.uniform_names.buffer_len - ofs;
- size_t len = strlen(name) + 1;
-
- if (len >= max_len) {
- DST.uniform_names.buffer_len += MAX2(DST.uniform_names.buffer_len, len);
- DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer,
- DST.uniform_names.buffer_len);
- }
-
- char *dst = DST.uniform_names.buffer + ofs;
- memcpy(dst, name, len); /* Copies NULL terminator. */
-
- DST.uniform_names.buffer_ofs += len;
- uni->name_ofs = ofs;
- }
+ BLI_assert(!ELEM(type,
+ DRW_UNIFORM_BLOCK,
+ DRW_UNIFORM_BLOCK_REF,
+ DRW_UNIFORM_TEXTURE,
+ DRW_UNIFORM_TEXTURE_REF));
+ int location = GPU_shader_get_uniform(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, location, type, value, 0, length, arraysize);
}
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
{
BLI_assert(tex != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 1);
+ int loc = GPU_shader_get_texture_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE, tex, GPU_SAMPLER_MAX, 0, 1);
}
-/* Same as DRW_shgroup_uniform_texture but is guaranteed to be bound if shader does not change
- * between shgrp. */
-void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const GPUTexture *tex)
+void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
{
BLI_assert(tex != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_PERSIST, tex, 0, 1);
+ int loc = GPU_shader_get_texture_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE_REF, tex, GPU_SAMPLER_MAX, 0, 1);
}
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
@@ -289,22 +266,17 @@ void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
const GPUUniformBuffer *ubo)
{
BLI_assert(ubo != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 1);
+ int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK, ubo, 0, 0, 1);
}
-/* Same as DRW_shgroup_uniform_block but is guaranteed to be bound if shader does not change
- * between shgrp. */
-void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const GPUUniformBuffer *ubo)
+void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup,
+ const char *name,
+ GPUUniformBuffer **ubo)
{
BLI_assert(ubo != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK_PERSIST, ubo, 0, 1);
-}
-
-void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
-{
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_REF, tex, 0, 1);
+ int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK_REF, ubo, 0, 0, 1);
}
void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup,
@@ -436,6 +408,25 @@ void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, c
drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, value, 4, 1);
}
+void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
+ const char *name,
+ const float (*value)[4],
+ int arraysize)
+{
+ int location = GPU_shader_get_uniform(shgroup->shader, name);
+
+ if (location == -1) {
+ /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
+ // BLI_assert(0);
+ return;
+ }
+
+ for (int i = 0; i < arraysize; i++) {
+ drw_shgroup_uniform_create_ex(
+ shgroup, location + i, DRW_UNIFORM_FLOAT_COPY, &value[i], 0, 4, 1);
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1177,53 +1168,49 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
{
shgroup->uniforms = NULL;
- /* TODO(fclem) make them builtin. */
- int view_ubo_location = GPU_shader_get_uniform_block(shader, "viewBlock");
- int model_ubo_location = GPU_shader_get_uniform_block(shader, "modelBlock");
- int info_ubo_location = GPU_shader_get_uniform_block(shader, "infoBlock");
+ int view_ubo_location = GPU_shader_get_builtin_block(shader, GPU_UNIFORM_BLOCK_VIEW);
+ int model_ubo_location = GPU_shader_get_builtin_block(shader, GPU_UNIFORM_BLOCK_MODEL);
+ int info_ubo_location = GPU_shader_get_builtin_block(shader, GPU_UNIFORM_BLOCK_INFO);
int baseinst_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_BASE_INSTANCE);
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);
if (chunkid_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, chunkid_location, DRW_UNIFORM_RESOURCE_CHUNK, NULL, 0, 1);
+ shgroup, chunkid_location, DRW_UNIFORM_RESOURCE_CHUNK, NULL, 0, 0, 1);
}
if (resourceid_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, resourceid_location, DRW_UNIFORM_RESOURCE_ID, NULL, 0, 1);
+ shgroup, resourceid_location, DRW_UNIFORM_RESOURCE_ID, NULL, 0, 0, 1);
}
if (baseinst_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, baseinst_location, DRW_UNIFORM_BASE_INSTANCE, NULL, 0, 1);
+ shgroup, baseinst_location, DRW_UNIFORM_BASE_INSTANCE, NULL, 0, 0, 1);
}
if (model_ubo_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 1);
+ shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 0, 1);
}
else {
+ /* Note: This is only here to support old hardware fallback where uniform buffer is still
+ * too slow or buggy. */
int model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL);
int modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV);
- int modelviewprojection = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP);
if (model != -1) {
- drw_shgroup_uniform_create_ex(shgroup, model, DRW_UNIFORM_MODEL_MATRIX, NULL, 0, 1);
+ drw_shgroup_uniform_create_ex(shgroup, model, DRW_UNIFORM_MODEL_MATRIX, NULL, 0, 0, 1);
}
if (modelinverse != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, modelinverse, DRW_UNIFORM_MODEL_MATRIX_INVERSE, NULL, 0, 1);
- }
- if (modelviewprojection != -1) {
- drw_shgroup_uniform_create_ex(
- shgroup, modelviewprojection, DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX, NULL, 0, 1);
+ shgroup, modelinverse, DRW_UNIFORM_MODEL_MATRIX_INVERSE, NULL, 0, 0, 1);
}
}
if (info_ubo_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, info_ubo_location, DRW_UNIFORM_BLOCK_OBINFOS, NULL, 0, 1);
+ shgroup, info_ubo_location, DRW_UNIFORM_BLOCK_OBINFOS, NULL, 0, 0, 1);
/* Abusing this loc to tell shgroup we need the obinfos. */
shgroup->objectinfo = 1;
@@ -1234,25 +1221,21 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
if (view_ubo_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, view_ubo_location, DRW_UNIFORM_BLOCK_PERSIST, G_draw.view_ubo, 0, 1);
- }
- else {
- /* Only here to support builtin shaders. This should not be used by engines. */
- /* TODO remove. */
- DRWViewUboStorage *storage = &DST.view_storage_cpy;
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW, storage->viewmat, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW_INV, storage->viewinv, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION, storage->persmat, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION_INV, storage->persinv, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION, storage->winmat, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION_INV, storage->wininv, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_CLIPPLANES, storage->clipplanes, 4, 6);
+ shgroup, view_ubo_location, DRW_UNIFORM_BLOCK, G_draw.view_ubo, 0, 0, 1);
}
/* Not supported. */
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV) == -1);
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW) == -1);
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEW) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEW_INV) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEWPROJECTION) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEWPROJECTION_INV) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION_INV) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CLIPPLANES) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP) == -1);
}
static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass)
@@ -1290,18 +1273,20 @@ static DRWShadingGroup *drw_shgroup_material_create_ex(GPUPass *gpupass, DRWPass
static void drw_shgroup_material_texture(DRWShadingGroup *grp,
GPUMaterialTexture *tex,
const char *name,
+ eGPUSamplerState state,
int textarget)
{
GPUTexture *gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget);
- DRW_shgroup_uniform_texture(grp, name, gputex);
+
+ int loc = GPU_shader_get_texture_binding(grp->shader, name);
+ drw_shgroup_uniform_create_ex(grp, loc, DRW_UNIFORM_TEXTURE, gputex, state, 0, 1);
GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images);
*gputex_ref = gputex;
GPU_texture_ref(gputex);
}
-static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
- struct GPUMaterial *material)
+void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial *material)
{
ListBase textures = GPU_material_textures(material);
@@ -1310,11 +1295,14 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
if (tex->ima) {
/* Image */
if (tex->tiled_mapping_name[0]) {
- drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D_ARRAY);
- drw_shgroup_material_texture(grp, tex, tex->tiled_mapping_name, GL_TEXTURE_1D_ARRAY);
+ drw_shgroup_material_texture(
+ grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D_ARRAY);
+ drw_shgroup_material_texture(
+ grp, tex, tex->tiled_mapping_name, tex->sampler_state, GL_TEXTURE_1D_ARRAY);
}
else {
- drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D);
+ drw_shgroup_material_texture(
+ grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D);
}
}
else if (tex->colorband) {
@@ -1327,8 +1315,6 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
if (ubo != NULL) {
DRW_shgroup_uniform_block(grp, GPU_UBO_BLOCK_NAME, ubo);
}
-
- return grp;
}
GPUVertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttrFormat attrs[],
@@ -1353,7 +1339,7 @@ DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPa
if (shgroup) {
drw_shgroup_init(shgroup, GPU_pass_shader_get(gpupass));
- drw_shgroup_material_inputs(shgroup, material);
+ DRW_shgroup_add_material_resources(shgroup, material);
}
return shgroup;
}
@@ -1372,7 +1358,7 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
BLI_assert(tf_target != NULL);
DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
drw_shgroup_init(shgroup, shader);
- drw_shgroup_uniform_create_ex(shgroup, 0, DRW_UNIFORM_TFEEDBACK_TARGET, tf_target, 0, 1);
+ drw_shgroup_uniform_create_ex(shgroup, 0, DRW_UNIFORM_TFEEDBACK_TARGET, tf_target, 0, 0, 1);
return shgroup;
}
@@ -1904,9 +1890,28 @@ DRWPass *DRW_pass_create(const char *name, DRWState state)
pass->handle = DST.pass_handle;
DRW_handle_increment(&DST.pass_handle);
+ pass->original = NULL;
+ pass->next = NULL;
+
return pass;
}
+DRWPass *DRW_pass_create_instance(const char *name, DRWPass *original, DRWState state)
+{
+ DRWPass *pass = DRW_pass_create(name, state);
+ pass->original = original;
+
+ return pass;
+}
+
+/* Link two passes so that they are both rendered if the first one is being drawn. */
+void DRW_pass_link(DRWPass *first, DRWPass *second)
+{
+ BLI_assert(first != second);
+ BLI_assert(first->next == NULL);
+ first->next = second;
+}
+
bool DRW_pass_is_empty(DRWPass *pass)
{
LISTBASE_FOREACH (DRWShadingGroup *, shgroup, &pass->shgroups) {
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 6c62d4d2405..59b4e9af14e 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -22,6 +22,7 @@
#include "draw_manager.h"
+#include "BLI_alloca.h"
#include "BLI_math.h"
#include "BLI_math_bits.h"
#include "BLI_memblock.h"
@@ -65,7 +66,6 @@ typedef struct DRWCommandsState {
/* Legacy matrix support. */
int obmat_loc;
int obinv_loc;
- int mvp_loc;
/* Selection ID state. */
GPUVertBuf *select_buf;
uint select_id;
@@ -454,6 +454,8 @@ void DRW_state_reset(void)
{
DRW_state_reset_ex(DRW_STATE_DEFAULT);
+ GPU_texture_unbind_all();
+
/* Should stay constant during the whole rendering. */
GPU_point_size(5);
GPU_line_smooth(false);
@@ -655,8 +657,7 @@ static void draw_compute_culling(DRWView *view)
BLI_INLINE void draw_legacy_matrix_update(DRWShadingGroup *shgroup,
DRWResourceHandle *handle,
float obmat_loc,
- float obinv_loc,
- float mvp_loc)
+ float obinv_loc)
{
/* Still supported for compatibility with gpu_shader_* but should be forbidden. */
DRWObjectMatrix *ob_mats = DRW_memblock_elem_from_handle(DST.vmempool->obmats, handle);
@@ -666,13 +667,6 @@ BLI_INLINE void draw_legacy_matrix_update(DRWShadingGroup *shgroup,
if (obinv_loc != -1) {
GPU_shader_uniform_vector(shgroup->shader, obinv_loc, 16, 1, (float *)ob_mats->modelinverse);
}
- /* Still supported for compatibility with gpu_shader_* but should be forbidden
- * and is slow (since it does not cache the result). */
- if (mvp_loc != -1) {
- float mvp[4][4];
- mul_m4_m4m4(mvp, DST.view_active->storage.persmat, ob_mats->model);
- GPU_shader_uniform_vector(shgroup->shader, mvp_loc, 16, 1, (float *)mvp);
- }
}
BLI_INLINE void draw_geometry_bind(DRWShadingGroup *shgroup, GPUBatch *geom)
@@ -744,107 +738,6 @@ BLI_INLINE void draw_indirect_call(DRWShadingGroup *shgroup, DRWCommandsState *s
}
}
-enum {
- BIND_NONE = 0,
- BIND_TEMP = 1, /* Release slot after this shading group. */
- BIND_PERSIST = 2, /* Release slot only after the next shader change. */
-};
-
-static void set_bound_flags(uint64_t *slots, uint64_t *persist_slots, int slot_idx, char bind_type)
-{
- uint64_t slot = 1llu << (unsigned long)slot_idx;
- *slots |= slot;
- if (bind_type == BIND_PERSIST) {
- *persist_slots |= slot;
- }
-}
-
-static int get_empty_slot_index(uint64_t slots)
-{
- uint64_t empty_slots = ~slots;
- /* Find first empty slot using bitscan. */
- if (empty_slots != 0) {
- if ((empty_slots & 0xFFFFFFFFlu) != 0) {
- return (int)bitscan_forward_uint(empty_slots);
- }
- else {
- return (int)bitscan_forward_uint(empty_slots >> 32) + 32;
- }
- }
- else {
- /* Greater than GPU_max_textures() */
- return 99999;
- }
-}
-
-static void bind_texture(GPUTexture *tex, char bind_type)
-{
- int idx = GPU_texture_bound_number(tex);
- if (idx == -1) {
- /* Texture isn't bound yet. Find an empty slot and bind it. */
- idx = get_empty_slot_index(DST.RST.bound_tex_slots);
-
- if (idx < GPU_max_textures()) {
- GPUTexture **gpu_tex_slot = &DST.RST.bound_texs[idx];
- /* Unbind any previous texture. */
- if (*gpu_tex_slot != NULL) {
- GPU_texture_unbind(*gpu_tex_slot);
- }
- GPU_texture_bind(tex, idx);
- *gpu_tex_slot = tex;
- }
- else {
- printf("Not enough texture slots! Reduce number of textures used by your shader.\n");
- return;
- }
- }
- else {
- /* This texture slot was released but the tex
- * is still bound. Just flag the slot again. */
- BLI_assert(DST.RST.bound_texs[idx] == tex);
- }
- set_bound_flags(&DST.RST.bound_tex_slots, &DST.RST.bound_tex_slots_persist, idx, bind_type);
-}
-
-static void bind_ubo(GPUUniformBuffer *ubo, char bind_type)
-{
- int idx = GPU_uniformbuffer_bindpoint(ubo);
- if (idx == -1) {
- /* UBO isn't bound yet. Find an empty slot and bind it. */
- idx = get_empty_slot_index(DST.RST.bound_ubo_slots);
-
- /* [0..1] are reserved ubo slots. */
- idx += 2;
-
- if (idx < GPU_max_ubo_binds()) {
- GPUUniformBuffer **gpu_ubo_slot = &DST.RST.bound_ubos[idx];
- /* Unbind any previous UBO. */
- if (*gpu_ubo_slot != NULL) {
- GPU_uniformbuffer_unbind(*gpu_ubo_slot);
- }
- GPU_uniformbuffer_bind(ubo, idx);
- *gpu_ubo_slot = ubo;
- }
- else {
- /* printf so user can report bad behavior */
- printf("Not enough ubo slots! This should not happen!\n");
- /* This is not depending on user input.
- * It is our responsibility to make sure there is enough slots. */
- BLI_assert(0);
- return;
- }
- }
- else {
- BLI_assert(idx < 64);
- /* This UBO slot was released but the UBO is
- * still bound here. Just flag the slot again. */
- BLI_assert(DST.RST.bound_ubos[idx] == ubo);
- }
- /* Remove offset for flag bitfield. */
- idx -= 2;
- set_bound_flags(&DST.RST.bound_ubo_slots, &DST.RST.bound_ubo_slots_persist, idx, bind_type);
-}
-
#ifndef NDEBUG
/**
* Opengl specification is strict on buffer binding.
@@ -900,28 +793,6 @@ static bool ubo_bindings_validate(DRWShadingGroup *shgroup)
}
#endif
-static void release_texture_slots(bool with_persist)
-{
- if (with_persist) {
- DST.RST.bound_tex_slots = 0;
- DST.RST.bound_tex_slots_persist = 0;
- }
- else {
- DST.RST.bound_tex_slots &= DST.RST.bound_tex_slots_persist;
- }
-}
-
-static void release_ubo_slots(bool with_persist)
-{
- if (with_persist) {
- DST.RST.bound_ubo_slots = 0;
- DST.RST.bound_ubo_slots_persist = 0;
- }
- else {
- DST.RST.bound_ubo_slots &= DST.RST.bound_ubo_slots_persist;
- }
-}
-
static void draw_update_uniforms(DRWShadingGroup *shgroup,
DRWCommandsState *state,
bool *use_tfeedback)
@@ -929,69 +800,42 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
for (DRWUniformChunk *unichunk = shgroup->uniforms; unichunk; unichunk = unichunk->next) {
DRWUniform *uni = unichunk->uniforms;
for (int i = 0; i < unichunk->uniform_used; i++, uni++) {
- GPUTexture *tex;
- GPUUniformBuffer *ubo;
- if (uni->location == -2) {
- uni->location = GPU_shader_get_uniform_ensure(shgroup->shader,
- DST.uniform_names.buffer + uni->name_ofs);
- if (uni->location == -1) {
- continue;
- }
- }
- const void *data = uni->pvalue;
- if (ELEM(uni->type, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT_COPY)) {
- data = uni->fvalue;
- }
switch (uni->type) {
case DRW_UNIFORM_INT_COPY:
+ GPU_shader_uniform_vector_int(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->ivalue);
+ break;
case DRW_UNIFORM_INT:
GPU_shader_uniform_vector_int(
- shgroup->shader, uni->location, uni->length, uni->arraysize, data);
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue);
break;
case DRW_UNIFORM_FLOAT_COPY:
+ GPU_shader_uniform_vector(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->fvalue);
+ break;
case DRW_UNIFORM_FLOAT:
GPU_shader_uniform_vector(
- shgroup->shader, uni->location, uni->length, uni->arraysize, data);
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue);
break;
case DRW_UNIFORM_TEXTURE:
- tex = (GPUTexture *)uni->pvalue;
- BLI_assert(tex);
- bind_texture(tex, BIND_TEMP);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
- break;
- case DRW_UNIFORM_TEXTURE_PERSIST:
- tex = (GPUTexture *)uni->pvalue;
- BLI_assert(tex);
- bind_texture(tex, BIND_PERSIST);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
+ GPU_texture_bind_ex(uni->texture, uni->sampler_state, uni->location, false);
break;
case DRW_UNIFORM_TEXTURE_REF:
- tex = *((GPUTexture **)uni->pvalue);
- BLI_assert(tex);
- bind_texture(tex, BIND_TEMP);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
+ GPU_texture_bind_ex(*uni->texture_ref, uni->sampler_state, uni->location, false);
break;
case DRW_UNIFORM_BLOCK:
- ubo = (GPUUniformBuffer *)uni->pvalue;
- bind_ubo(ubo, BIND_TEMP);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ GPU_uniformbuffer_bind(uni->block, uni->location);
break;
- case DRW_UNIFORM_BLOCK_PERSIST:
- ubo = (GPUUniformBuffer *)uni->pvalue;
- bind_ubo(ubo, BIND_PERSIST);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ case DRW_UNIFORM_BLOCK_REF:
+ GPU_uniformbuffer_bind(*uni->block_ref, uni->location);
break;
case DRW_UNIFORM_BLOCK_OBMATS:
state->obmats_loc = uni->location;
- ubo = DST.vmempool->matrices_ubo[0];
- GPU_uniformbuffer_bind(ubo, 0);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[0], uni->location);
break;
case DRW_UNIFORM_BLOCK_OBINFOS:
state->obinfos_loc = uni->location;
- ubo = DST.vmempool->obinfos_ubo[0];
- GPU_uniformbuffer_bind(ubo, 1);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ GPU_uniformbuffer_bind(DST.vmempool->obinfos_ubo[0], uni->location);
break;
case DRW_UNIFORM_RESOURCE_CHUNK:
state->chunkid_loc = uni->location;
@@ -1001,9 +845,9 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
state->resourceid_loc = uni->location;
break;
case DRW_UNIFORM_TFEEDBACK_TARGET:
- BLI_assert(data && (*use_tfeedback == false));
- *use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
- ((GPUVertBuf *)data)->vbo_id);
+ BLI_assert(uni->pvalue && (*use_tfeedback == false));
+ *use_tfeedback = GPU_shader_transform_feedback_enable(
+ shgroup->shader, ((GPUVertBuf *)uni->pvalue)->vbo_id);
break;
/* Legacy/Fallback support. */
case DRW_UNIFORM_BASE_INSTANCE:
@@ -1015,9 +859,6 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
case DRW_UNIFORM_MODEL_MATRIX_INVERSE:
state->obinv_loc = uni->location;
break;
- case DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX:
- state->mvp_loc = uni->location;
- break;
}
}
}
@@ -1110,11 +951,11 @@ static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHa
}
if (state->obmats_loc != -1) {
GPU_uniformbuffer_unbind(DST.vmempool->matrices_ubo[state->resource_chunk]);
- GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[chunk], 0);
+ GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[chunk], state->obmats_loc);
}
if (state->obinfos_loc != -1) {
GPU_uniformbuffer_unbind(DST.vmempool->obinfos_ubo[state->resource_chunk]);
- GPU_uniformbuffer_bind(DST.vmempool->obinfos_ubo[chunk], 1);
+ GPU_uniformbuffer_bind(DST.vmempool->obinfos_ubo[chunk], state->obinfos_loc);
}
state->resource_chunk = chunk;
}
@@ -1153,10 +994,8 @@ static void draw_call_single_do(DRWShadingGroup *shgroup,
draw_call_resource_bind(state, &handle);
/* TODO This is Legacy. Need to be removed. */
- if (state->obmats_loc == -1 &&
- (state->obmat_loc != -1 || state->obinv_loc != -1 || state->mvp_loc != -1)) {
- draw_legacy_matrix_update(
- shgroup, &handle, state->obmat_loc, state->obinv_loc, state->mvp_loc);
+ if (state->obmats_loc == -1 && (state->obmat_loc != -1 || state->obinv_loc != -1)) {
+ draw_legacy_matrix_update(shgroup, &handle, state->obmat_loc, state->obinv_loc);
}
if (G.f & G_FLAG_PICKSEL) {
@@ -1262,7 +1101,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
.resourceid_loc = -1,
.obmat_loc = -1,
.obinv_loc = -1,
- .mvp_loc = -1,
.drw_state_enabled = 0,
.drw_state_disabled = 0,
};
@@ -1273,6 +1111,11 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
if (shader_changed) {
if (DST.shader) {
GPU_shader_unbind();
+
+ /* Unbinding can be costly. Skip in normal condition. */
+ if (G.debug & G_DEBUG_GPU) {
+ GPU_texture_unbind_all();
+ }
}
GPU_shader_bind(shgroup->shader);
DST.shader = shgroup->shader;
@@ -1283,9 +1126,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
DST.batch = NULL;
}
- release_ubo_slots(shader_changed);
- release_texture_slots(shader_changed);
-
draw_update_uniforms(shgroup, &state, &use_tfeedback);
drw_state_set(pass_state);
@@ -1426,6 +1266,11 @@ static void drw_draw_pass_ex(DRWPass *pass,
DRWShadingGroup *start_group,
DRWShadingGroup *end_group)
{
+ if (pass->original) {
+ start_group = pass->original->shgroups.first;
+ end_group = pass->original->shgroups.last;
+ }
+
if (start_group == NULL) {
return;
}
@@ -1462,22 +1307,6 @@ static void drw_draw_pass_ex(DRWPass *pass,
}
}
- /* Clear Bound textures */
- for (int i = 0; i < DST_MAX_SLOTS; i++) {
- if (DST.RST.bound_texs[i] != NULL) {
- GPU_texture_unbind(DST.RST.bound_texs[i]);
- DST.RST.bound_texs[i] = NULL;
- }
- }
-
- /* Clear Bound Ubos */
- for (int i = 0; i < DST_MAX_SLOTS; i++) {
- if (DST.RST.bound_ubos[i] != NULL) {
- GPU_uniformbuffer_unbind(DST.RST.bound_ubos[i]);
- DST.RST.bound_ubos[i] = NULL;
- }
- }
-
if (DST.shader) {
GPU_shader_unbind();
DST.shader = NULL;
@@ -1511,7 +1340,9 @@ static void drw_draw_pass_ex(DRWPass *pass,
void DRW_draw_pass(DRWPass *pass)
{
- drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last);
+ for (; pass; pass = pass->next) {
+ drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last);
+ }
}
/* Draw only a subset of shgroups. Used in special situations as grease pencil strokes */
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 0d6527421d0..6304b707cb9 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -343,27 +343,12 @@ GPUShader *DRW_shader_create_with_transform_feedback(const char *vert,
__func__);
}
-GPUShader *DRW_shader_create_2d(const char *frag, const char *defines)
-{
- return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines, __func__);
-}
-
-GPUShader *DRW_shader_create_3d(const char *frag, const char *defines)
-{
- return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines, __func__);
-}
-
GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines)
{
return GPU_shader_create(
datatoc_common_fullscreen_vert_glsl, frag, NULL, NULL, defines, __func__);
}
-GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig sh_cfg)
-{
- return GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_DEPTH_ONLY, sh_cfg);
-}
-
GPUMaterial *DRW_shader_find_from_world(World *wo,
const void *engine_type,
const int options,
@@ -398,6 +383,7 @@ GPUMaterial *DRW_shader_find_from_material(Material *ma,
GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
World *wo,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -408,7 +394,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
bool deferred)
{
GPUMaterial *mat = NULL;
- if (DRW_state_is_image_render()) {
+ if (DRW_state_is_image_render() || !deferred) {
mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options);
}
@@ -416,7 +402,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
mat = GPU_material_from_nodetree(scene,
NULL,
- wo->nodetree,
+ ntree,
&wo->gpumaterial,
engine_type,
options,
@@ -437,6 +423,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
Material *ma,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -447,7 +434,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
bool deferred)
{
GPUMaterial *mat = NULL;
- if (DRW_state_is_image_render()) {
+ if (DRW_state_is_image_render() || !deferred) {
mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options);
}
@@ -455,7 +442,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
mat = GPU_material_from_nodetree(scene,
ma,
- ma->nodetree,
+ ntree,
&ma->gpumaterial,
engine_type,
options,
diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c
index 810a2e9389b..77b0462303d 100644
--- a/source/blender/draw/intern/draw_manager_texture.c
+++ b/source/blender/draw/intern/draw_manager_texture.c
@@ -61,17 +61,17 @@ static bool drw_texture_format_supports_framebuffer(eGPUTextureFormat format)
void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags)
{
- GPU_texture_bind(tex, 0);
if (flags & DRW_TEX_MIPMAP) {
GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER);
+ GPU_texture_bind(tex, 0);
GPU_texture_generate_mipmap(tex);
+ GPU_texture_unbind(tex);
}
else {
GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER);
}
GPU_texture_wrap_mode(tex, flags & DRW_TEX_WRAP, true);
GPU_texture_compare_mode(tex, flags & DRW_TEX_COMPARE);
- GPU_texture_unbind(tex);
}
GPUTexture *DRW_texture_create_1d(int w,
diff --git a/source/blender/draw/intern/shaders/common_globals_lib.glsl b/source/blender/draw/intern/shaders/common_globals_lib.glsl
index 9dfd48cc21a..a479a87e14b 100644
--- a/source/blender/draw/intern/shaders/common_globals_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_globals_lib.glsl
@@ -140,3 +140,4 @@ layout(std140) uniform globalsBlock
#define EDGE_SEAM (1 << 4)
#define EDGE_SHARP (1 << 5)
#define EDGE_FREESTYLE (1 << 6)
+#define HANDLE_SELECTED (1 << 7)
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index cd17a490240..0947023e071 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -4959,7 +4959,9 @@ static void draw_setting_widget(bAnimContext *ac,
"Temporarily disable NLA stack evaluation (i.e. only the active action is evaluated)");
}
else if (ale->type == ANIMTYPE_GPLAYER) {
- tooltip = TIP_("Lock current frame displayed by layer (i.e. disable animation playback)");
+ tooltip = TIP_(
+ "Shows all keyframes during animation playback and enabled all frames for editing "
+ "(uncheck to use only the current keyframe during animation playback and editing)");
}
else {
tooltip = TIP_("Do channels contribute to result (toggle channel muting)");
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index a7ca84eb6c6..1ca3452e8d8 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -671,7 +671,7 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
}
/* free the F-Curve itself */
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
}
/* If the action has no F-Curves, unlink it from AnimData if it did not
@@ -1806,7 +1806,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* remove from group and action, then free */
action_groups_remove_channel(adt->action, fcu);
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
}
/* free the group itself */
@@ -1860,7 +1860,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* unlink and free the F-Curve */
BLI_remlink(&strip->fcurves, fcu);
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
tag_update_animation_element(ale);
break;
}
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 4203c2677b7..a2a1f7eb1d2 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -62,67 +62,6 @@
/* *************************************************** */
/* CURRENT FRAME DRAWING */
-/* Draw current frame number in a little green box beside the current frame indicator */
-void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag)
-{
- Scene *scene = CTX_data_scene(C);
- const float time = scene->r.cfra + scene->r.subframe;
- const float cfra = (float)(time * scene->r.framelen);
- const bool show_time = (flag & DRAWCFRA_UNIT_SECONDS) != 0;
-
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- uchar col[4];
- float color[4];
- float xscale, x, y;
- char numstr[32] = " t "; /* t is the character to start replacing from */
- float hlen;
- int slen;
-
- /* because the frame number text is subject to the same scaling as the contents of the view */
- UI_view2d_scale_get(v2d, &xscale, NULL);
- GPU_matrix_push();
- GPU_matrix_scale_2f(1.0f / xscale, 1.0f);
-
- /* get timecode string
- * - padding on str-buf passed so that it doesn't sit on the frame indicator
- */
- if (show_time) {
- BLI_timecode_string_from_time(
- &numstr[2], sizeof(numstr) - 2, 0, FRA2TIME(cfra), FPS, U.timecode_style);
- }
- else {
- BLI_timecode_string_from_time_seconds(&numstr[2], sizeof(numstr) - 2, 1, cfra);
- }
-
- slen = UI_fontstyle_string_width(fstyle, numstr) - 1;
- hlen = slen * 0.5f;
-
- /* get starting coordinates for drawing */
- x = cfra * xscale;
- y = -0.1f * U.widget_unit;
-
- /* draw green box around/behind text */
- UI_GetThemeColor4fv(TH_CFRAME, color);
- color[3] = 3.0f;
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(true,
- x - hlen - 0.1f * U.widget_unit,
- y + 3.0f,
- x + hlen + 0.1f * U.widget_unit,
- y - 3.0f + U.widget_unit,
- 0.1f * U.widget_unit,
- color);
-
- /* draw current frame number */
- UI_GetThemeColor4ubv(TH_TEXT_HI, col);
- UI_fontstyle_draw_simple(
- fstyle, x - hlen - 0.15f * U.widget_unit, y + 0.28f * U.widget_unit, numstr, col);
-
- /* restore view transform */
- GPU_matrix_pop();
-}
-
/* General call for drawing current frame indicator in animation editor */
void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
{
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 2b9dfe105bc..bd83bdae31b 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -988,7 +988,7 @@ static bAnimListElem *make_new_animlistelem(void *data,
* then free the MEM_alloc'd string
*/
if (rna_path) {
- ale->key_data = (void *)list_find_fcurve(&act->curves, rna_path, 0);
+ ale->key_data = (void *)BKE_fcurve_find(&act->curves, rna_path, 0);
MEM_freeN(rna_path);
}
}
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 82e24eaa6e3..328e435877c 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -92,7 +92,7 @@ FCurve *verify_driver_fcurve(ID *id,
* - add if not found and allowed to add one
* TODO: add auto-grouping support? how this works will need to be resolved
*/
- fcu = list_find_fcurve(&adt->drivers, rna_path, array_index);
+ fcu = BKE_fcurve_find(&adt->drivers, rna_path, array_index);
if (fcu == NULL && creation_mode != DRIVER_FCURVE_LOOKUP_ONLY) {
/* use default settings to make a F-Curve */
@@ -110,7 +110,7 @@ struct FCurve *alloc_driver_fcurve(const char rna_path[],
const int array_index,
eDriverFCurveCreationMode creation_mode)
{
- FCurve *fcu = MEM_callocN(sizeof(FCurve), "FCurve");
+ FCurve *fcu = BKE_fcurve_create();
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
fcu->auto_smoothing = U.auto_smoothing_new;
@@ -570,13 +570,13 @@ bool ANIM_remove_driver(ReportList *UNUSED(reports),
/* step through all drivers, removing all of those with the same base path */
FCurve *fcu_iter = adt->drivers.first;
- while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) {
+ while ((fcu = BKE_fcurve_iter_step(fcu_iter, rna_path)) != NULL) {
/* store the next fcurve for looping */
fcu_iter = fcu->next;
/* remove F-Curve from driver stack, then free it */
BLI_remlink(&adt->drivers, fcu);
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
/* done successfully */
success = true;
@@ -590,7 +590,7 @@ bool ANIM_remove_driver(ReportList *UNUSED(reports),
fcu = verify_driver_fcurve(id, rna_path, array_index, DRIVER_FCURVE_LOOKUP_ONLY);
if (fcu) {
BLI_remlink(&adt->drivers, fcu);
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
success = true;
}
@@ -611,7 +611,7 @@ void ANIM_drivers_copybuf_free(void)
{
/* free the buffer F-Curve if it exists, as if it were just another F-Curve */
if (channeldriver_copypaste_buf) {
- free_fcurve(channeldriver_copypaste_buf);
+ BKE_fcurve_free(channeldriver_copypaste_buf);
}
channeldriver_copypaste_buf = NULL;
}
@@ -662,7 +662,7 @@ bool ANIM_copy_driver(
fcu->rna_path = NULL;
/* make a copy of the F-Curve with */
- channeldriver_copypaste_buf = copy_fcurve(fcu);
+ channeldriver_copypaste_buf = BKE_fcurve_copy(fcu);
/* restore the path */
fcu->rna_path = tmp_path;
@@ -981,7 +981,8 @@ static bool add_driver_button_poll(bContext *C)
}
/* Don't do anything if there is an fcurve for animation without a driver. */
- FCurve *fcu = rna_get_fcurve_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
+ FCurve *fcu = BKE_fcurve_find_by_rna_context_ui(
+ C, &ptr, prop, index, NULL, NULL, &driven, &special);
return (fcu == NULL || fcu->driver);
}
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 04061ceea51..2aa8d468e2d 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -184,7 +184,7 @@ FCurve *ED_action_fcurve_find(struct bAction *act, const char rna_path[], const
if (ELEM(NULL, act, rna_path)) {
return NULL;
}
- return list_find_fcurve(&act->curves, rna_path, array_index);
+ return BKE_fcurve_find(&act->curves, rna_path, array_index);
}
/**
@@ -210,11 +210,11 @@ FCurve *ED_action_fcurve_ensure(struct Main *bmain,
* - add if not found and allowed to add one
* TODO: add auto-grouping support? how this works will need to be resolved
*/
- fcu = list_find_fcurve(&act->curves, rna_path, array_index);
+ fcu = BKE_fcurve_find(&act->curves, rna_path, array_index);
if (fcu == NULL) {
/* use default settings to make a F-Curve */
- fcu = MEM_callocN(sizeof(FCurve), "FCurve");
+ fcu = BKE_fcurve_create();
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
fcu->auto_smoothing = U.auto_smoothing_new;
@@ -1120,7 +1120,7 @@ static bool insert_keyframe_value(ReportList *reports,
eInsertKeyFlags flag)
{
/* F-Curve not editable? */
- if (fcurve_is_keyframable(fcu) == 0) {
+ if (BKE_fcurve_is_keyframable(fcu) == 0) {
BKE_reportf(
reports,
RPT_ERROR,
@@ -1827,7 +1827,7 @@ static int insert_key_exec(bContext *C, wmOperator *op)
* updated since the last switching to the edit mode will be keyframed correctly
*/
if (obedit && ANIM_keyingset_find_id(ks, (ID *)obedit->data)) {
- ED_object_mode_toggle(C, OB_MODE_EDIT);
+ ED_object_mode_set(C, OB_MODE_OBJECT);
ob_edit_mode = true;
}
@@ -1843,7 +1843,7 @@ static int insert_key_exec(bContext *C, wmOperator *op)
/* restore the edit mode if necessary */
if (ob_edit_mode) {
- ED_object_mode_toggle(C, OB_MODE_EDIT);
+ ED_object_mode_set(C, OB_MODE_EDIT);
}
/* report failure or do updates? */
@@ -2400,7 +2400,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
* not have any effect.
*/
NlaStrip *strip = ptr.data;
- FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
+ FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), index);
if (fcu) {
changed = insert_keyframe_direct(
@@ -2417,7 +2417,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
FCurve *fcu;
bool driven, special;
- fcu = rna_get_fcurve_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
+ fcu = BKE_fcurve_find_by_rna_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
if (fcu && driven) {
changed = insert_keyframe_direct(
@@ -2560,7 +2560,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
*/
ID *id = ptr.owner_id;
NlaStrip *strip = ptr.data;
- FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
+ FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), 0);
if (fcu) {
if (BKE_fcurve_is_protected(fcu)) {
@@ -3001,7 +3001,8 @@ bool ED_autokeyframe_property(
bool special;
bool changed = false;
- fcu = rna_get_fcurve_context_ui(C, ptr, prop, rnaindex, NULL, &action, &driven, &special);
+ fcu = BKE_fcurve_find_by_rna_context_ui(
+ C, ptr, prop, rnaindex, NULL, &action, &driven, &special);
if (fcu == NULL) {
return changed;
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index d941f8ce95f..895b4953992 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -516,11 +516,11 @@ static void updateDuplicateActionConstraintSettings(EditBone *dup_bone,
/* See if there is any channels that uses this bone */
ListBase ani_curves;
BLI_listbase_clear(&ani_curves);
- if (list_find_data_fcurves(&ani_curves, &act->curves, "pose.bones[", orig_bone->name)) {
+ if (BKE_fcurves_filter(&ani_curves, &act->curves, "pose.bones[", orig_bone->name)) {
/* Create a copy and mirror the animation */
for (LinkData *ld = ani_curves.first; ld; ld = ld->next) {
FCurve *old_curve = ld->data;
- FCurve *new_curve = copy_fcurve(old_curve);
+ FCurve *new_curve = BKE_fcurve_copy(old_curve);
bActionGroup *agrp;
char *old_path = new_curve->rna_path;
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index b946c19dbe5..8e03dbc7dc3 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -184,78 +184,74 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
for (i = 0; i < hits; i++) {
hitresult = buffer[3 + (i * 4)];
- if (!(hitresult & BONESEL_NOSEL)) {
- if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
- Base *base = NULL;
- bool sel;
-
- hitresult &= ~(BONESEL_ANY);
- /* Determine what the current bone is */
- if (is_editmode == false) {
- base = ED_armature_base_and_pchan_from_select_buffer(
- bases, bases_len, hitresult, &pchan);
- if (pchan != NULL) {
- if (findunsel) {
- sel = (pchan->bone->flag & BONE_SELECTED);
- }
- else {
- sel = !(pchan->bone->flag & BONE_SELECTED);
- }
-
- data = pchan;
+ if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
+ Base *base = NULL;
+ bool sel;
+
+ hitresult &= ~(BONESEL_ANY);
+ /* Determine what the current bone is */
+ if (is_editmode == false) {
+ base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, hitresult, &pchan);
+ if (pchan != NULL) {
+ if (findunsel) {
+ sel = (pchan->bone->flag & BONE_SELECTED);
}
else {
- data = NULL;
- sel = 0;
+ sel = !(pchan->bone->flag & BONE_SELECTED);
}
+
+ data = pchan;
}
else {
- base = ED_armature_base_and_ebone_from_select_buffer(
- bases, bases_len, hitresult, &ebone);
- if (findunsel) {
- sel = (ebone->flag & BONE_SELECTED);
+ data = NULL;
+ sel = 0;
+ }
+ }
+ else {
+ base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hitresult, &ebone);
+ if (findunsel) {
+ sel = (ebone->flag & BONE_SELECTED);
+ }
+ else {
+ sel = !(ebone->flag & BONE_SELECTED);
+ }
+
+ data = ebone;
+ }
+
+ if (data) {
+ if (sel) {
+ if (do_nearest) {
+ if (minsel > buffer[4 * i + 1]) {
+ firstSel = data;
+ firstSel_base = base;
+ minsel = buffer[4 * i + 1];
+ }
}
else {
- sel = !(ebone->flag & BONE_SELECTED);
+ if (!firstSel) {
+ firstSel = data;
+ firstSel_base = base;
+ }
+ takeNext = 1;
}
-
- data = ebone;
}
-
- if (data) {
- if (sel) {
- if (do_nearest) {
- if (minsel > buffer[4 * i + 1]) {
- firstSel = data;
- firstSel_base = base;
- minsel = buffer[4 * i + 1];
- }
- }
- else {
- if (!firstSel) {
- firstSel = data;
- firstSel_base = base;
- }
- takeNext = 1;
+ else {
+ if (do_nearest) {
+ if (minunsel > buffer[4 * i + 1]) {
+ firstunSel = data;
+ firstunSel_base = base;
+ minunsel = buffer[4 * i + 1];
}
}
else {
- if (do_nearest) {
- if (minunsel > buffer[4 * i + 1]) {
- firstunSel = data;
- firstunSel_base = base;
- minunsel = buffer[4 * i + 1];
- }
+ if (!firstunSel) {
+ firstunSel = data;
+ firstunSel_base = base;
}
- else {
- if (!firstunSel) {
- firstunSel = data;
- firstunSel_base = base;
- }
- if (takeNext) {
- *r_base = base;
- return data;
- }
+ if (takeNext) {
+ *r_base = base;
+ return data;
}
}
}
@@ -659,8 +655,8 @@ static EditBone *get_nearest_editbonepoint(
EditBone *ebone;
} *result = NULL,
- result_cycle = {.hitresult = BONESEL_NOSEL, .base = NULL, .ebone = NULL},
- result_bias = {.hitresult = BONESEL_NOSEL, .base = NULL, .ebone = NULL};
+ result_cycle = {.hitresult = -1, .base = NULL, .ebone = NULL},
+ result_bias = {.hitresult = -1, .base = NULL, .ebone = NULL};
/* find the bone after the current active bone, so as to bump up its chances in selection.
* this way overlapping bones will cycle selection state as with objects. */
@@ -732,11 +728,9 @@ cache_end:
/* See if there are any selected bones in this group */
if (hits > 0) {
if (hits == 1) {
- if (!(buffer[3] & BONESEL_NOSEL)) {
- result_bias.hitresult = buffer[3];
- result_bias.base = ED_armature_base_and_ebone_from_select_buffer(
- bases, bases_len, result_bias.hitresult, &result_bias.ebone);
- }
+ result_bias.hitresult = buffer[3];
+ result_bias.base = ED_armature_base_and_ebone_from_select_buffer(
+ bases, bases_len, result_bias.hitresult, &result_bias.ebone);
}
else {
int bias_max = INT_MIN;
@@ -774,84 +768,82 @@ cache_end:
for (int i = 0; i < hits; i++) {
const uint hitresult = buffer[3 + (i * 4)];
- if (!(hitresult & BONESEL_NOSEL)) {
- Base *base = NULL;
- EditBone *ebone;
- base = ED_armature_base_and_ebone_from_select_buffer(
- bases, bases_len, hitresult, &ebone);
- /* If this fails, selection code is setting the selection ID's incorrectly. */
- BLI_assert(base && ebone);
-
- /* Prioritized selection. */
- {
- int bias;
- /* clicks on bone points get advantage */
- if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
- /* but also the unselected one */
- if (findunsel) {
- if ((hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0) {
- bias = 4;
- }
- else if ((hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0) {
- bias = 4;
- }
- else {
- bias = 3;
- }
+
+ Base *base = NULL;
+ EditBone *ebone;
+ base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hitresult, &ebone);
+ /* If this fails, selection code is setting the selection ID's incorrectly. */
+ BLI_assert(base && ebone);
+
+ /* Prioritized selection. */
+ {
+ int bias;
+ /* clicks on bone points get advantage */
+ if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
+ /* but also the unselected one */
+ if (findunsel) {
+ if ((hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0) {
+ bias = 4;
}
- else {
+ else if ((hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0) {
bias = 4;
}
+ else {
+ bias = 3;
+ }
}
else {
- /* bone found */
- if (findunsel) {
- if ((ebone->flag & BONE_SELECTED) == 0) {
- bias = 2;
- }
- else {
- bias = 1;
- }
+ bias = 4;
+ }
+ }
+ else {
+ /* bone found */
+ if (findunsel) {
+ if ((ebone->flag & BONE_SELECTED) == 0) {
+ bias = 2;
}
else {
- bias = 2;
+ bias = 1;
}
}
+ else {
+ bias = 2;
+ }
+ }
- if (bias > bias_max) {
- bias_max = bias;
+ if (bias > bias_max) {
+ bias_max = bias;
- result_bias.hitresult = hitresult;
- result_bias.base = base;
- result_bias.ebone = ebone;
- }
+ result_bias.hitresult = hitresult;
+ result_bias.base = base;
+ result_bias.ebone = ebone;
}
+ }
- /* Cycle selected items (objects & bones). */
- if (use_cycle) {
- cycle_order.test.ob = hitresult & 0xFFFF;
- cycle_order.test.bone = (hitresult & ~BONESEL_ANY) >> 16;
- if (ebone == ebone_active_orig) {
- BLI_assert(cycle_order.test.ob == cycle_order.offset.ob);
- BLI_assert(cycle_order.test.bone == cycle_order.offset.bone);
- }
- /* Subtraction as a single value is needed to support cycling through bones
- * from multiple objects. So once the last bone is selected,
- * the bits for the bone index wrap into the object,
- * causing the next object to be stepped onto. */
- cycle_order.test.as_u32 -= cycle_order.offset.as_u32;
-
- /* Even though this logic avoids stepping onto the active bone,
- * always set the 'best' value for the first time.
- * Otherwise ensure the value is the smallest it can be,
- * relative to the active bone, as long as it's not the active bone. */
- if ((cycle_order.best.as_u32 == 0) ||
- (cycle_order.test.as_u32 && (cycle_order.test.as_u32 < cycle_order.best.as_u32))) {
- cycle_order.best = cycle_order.test;
- result_cycle.hitresult = hitresult;
- result_cycle.base = base;
- result_cycle.ebone = ebone;
- }
+ /* Cycle selected items (objects & bones). */
+ if (use_cycle) {
+ cycle_order.test.ob = hitresult & 0xFFFF;
+ cycle_order.test.bone = (hitresult & ~BONESEL_ANY) >> 16;
+ if (ebone == ebone_active_orig) {
+ BLI_assert(cycle_order.test.ob == cycle_order.offset.ob);
+ BLI_assert(cycle_order.test.bone == cycle_order.offset.bone);
+ }
+ /* Subtraction as a single value is needed to support cycling through bones
+ * from multiple objects. So once the last bone is selected,
+ * the bits for the bone index wrap into the object,
+ * causing the next object to be stepped onto. */
+ cycle_order.test.as_u32 -= cycle_order.offset.as_u32;
+
+ /* Even though this logic avoids stepping onto the active bone,
+ * always set the 'best' value for the first time.
+ * Otherwise ensure the value is the smallest it can be,
+ * relative to the active bone, as long as it's not the active bone. */
+ if ((cycle_order.best.as_u32 == 0) ||
+ (cycle_order.test.as_u32 && (cycle_order.test.as_u32 < cycle_order.best.as_u32))) {
+ cycle_order.best = cycle_order.test;
+ result_cycle.hitresult = hitresult;
+ result_cycle.base = base;
+ result_cycle.ebone = ebone;
}
}
}
@@ -859,7 +851,7 @@ cache_end:
result = (use_cycle && result_cycle.ebone) ? &result_cycle : &result_bias;
- if (!(result->hitresult & BONESEL_NOSEL)) {
+ if (result->hitresult != -1) {
*r_base = result->base;
*r_selmask = 0;
@@ -1213,8 +1205,8 @@ bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
ebone->temp.i = ebone->flag;
/* When there is a partial selection without both endpoints, only select an endpoint. */
- if ((is_inside_flag & BONESEL_BONE) && (is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) &&
- ((is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) != (BONESEL_ROOT | BONESEL_TIP))) {
+ if ((is_inside_flag & BONESEL_BONE) &&
+ ELEM(is_inside_flag & (BONESEL_ROOT | BONESEL_TIP), BONESEL_ROOT, BONESEL_TIP)) {
is_inside_flag &= ~BONESEL_BONE;
}
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index d6256f67066..4e1c07af001 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -936,13 +936,13 @@ static void fcurve_path_rename(AnimData *adt,
nextfcu = fcu->next;
if (STREQLEN(fcu->rna_path, orig_rna_path, len)) {
char *spath, *suffix = fcu->rna_path + len;
- nfcu = copy_fcurve(fcu);
+ nfcu = BKE_fcurve_copy(fcu);
spath = nfcu->rna_path;
nfcu->rna_path = BLI_sprintfN("%s%s", rna_path, suffix);
- /* copy_fcurve() sets nfcu->grp to NULL. To maintain the groups, we need to keep the pointer.
- * As a result, the group's 'channels' pointers will be wrong, which is fixed by calling
- * `action_groups_reconstruct(action)` later, after all fcurves have been renamed. */
+ /* BKE_fcurve_copy() sets nfcu->grp to NULL. To maintain the groups, we need to keep the
+ * pointer. As a result, the group's 'channels' pointers will be wrong, which is fixed by
+ * calling `action_groups_reconstruct(action)` later, after all fcurves have been renamed. */
nfcu->grp = fcu->grp;
BLI_addtail(curves, nfcu);
@@ -956,7 +956,7 @@ static void fcurve_path_rename(AnimData *adt,
BLI_remlink(&adt->drivers, fcu);
}
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
MEM_freeN(spath);
}
@@ -972,7 +972,7 @@ static void fcurve_remove(AnimData *adt, ListBase *orig_curves, FCurve *fcu)
action_groups_remove_channel(adt->action, fcu);
}
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
}
static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
@@ -4923,7 +4923,7 @@ bool ED_curve_editnurb_select_pick(
}
}
else {
- BKE_nurbList_flag_set(editnurb, 0);
+ BKE_nurbList_flag_set(editnurb, SELECT, false);
if (bezt) {
@@ -5635,7 +5635,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const float mval[2] = {UNPACK2(event->mval)};
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- vc.bmain, vc.scene, 0, vc.region, vc.v3d);
+ vc.scene, 0, vc.region, vc.v3d);
ED_transform_snap_object_project_view3d(
snap_context,
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index 91d5ea58361..bacdd5b69b5 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -138,7 +138,7 @@ Nurb *ED_curve_add_nurbs_primitive(
copy_v3_v3(zvec, rv3d->viewinv[2]);
}
- BKE_nurbList_flag_set(editnurb, 0);
+ BKE_nurbList_flag_set(editnurb, SELECT, false);
/* these types call this function to return a Nurb */
if (stype != CU_PRIM_TUBE && stype != CU_PRIM_DONUT) {
@@ -521,7 +521,7 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(
- C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/curve/editcurve_query.c b/source/blender/editors/curve/editcurve_query.c
index 0b15d9e55b9..132f7e58e71 100644
--- a/source/blender/editors/curve/editcurve_query.c
+++ b/source/blender/editors/curve/editcurve_query.c
@@ -44,8 +44,13 @@
/** \name Cursor Picking API
* \{ */
-static void ED_curve_pick_vert__do_closest(
- void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
+static void ED_curve_pick_vert__do_closest(void *userData,
+ Nurb *nu,
+ BPoint *bp,
+ BezTriple *bezt,
+ int beztindex,
+ bool handles_visible,
+ const float screen_co[2])
{
struct {
BPoint *bp;
@@ -64,6 +69,8 @@ static void ED_curve_pick_vert__do_closest(
flag = bp->f1;
}
else {
+ BLI_assert(handles_visible || beztindex == 1);
+
if (beztindex == 0) {
flag = bezt->f1;
}
@@ -92,6 +99,8 @@ static void ED_curve_pick_vert__do_closest(
data->hpoint = bezt ? beztindex : 0;
data->is_changed = true;
}
+
+ UNUSED_VARS_NDEBUG(handles_visible);
}
bool ED_curve_pick_vert(ViewContext *vc,
diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
index 9cf61d02677..9294bc6e91b 100644
--- a/source/blender/editors/curve/editcurve_select.c
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -590,8 +590,8 @@ static int de_select_all_exec(bContext *C, wmOperator *op)
changed = ED_curve_deselect_all(cu->editnurb);
break;
case SEL_INVERT:
- changed = ED_curve_select_swap(
- cu->editnurb, (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0);
+ changed = ED_curve_select_swap(cu->editnurb,
+ v3d->overlay.handle_display == CURVE_HANDLE_NONE);
break;
}
@@ -772,7 +772,7 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
if (last == bp) {
direction = 1 - direction;
- BKE_nurbList_flag_set(editnurb, 0);
+ BKE_nurbList_flag_set(editnurb, SELECT, false);
}
last = bp;
@@ -826,8 +826,10 @@ static int select_next_exec(bContext *C, wmOperator *UNUSED(op))
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
+
ListBase *editnurb = object_editcurve_get(obedit);
select_adjacent_cp(editnurb, 1, 0, SELECT);
+
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -861,8 +863,10 @@ static int select_previous_exec(bContext *C, wmOperator *UNUSED(op))
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
+
ListBase *editnurb = object_editcurve_get(obedit);
select_adjacent_cp(editnurb, -1, 0, SELECT);
+
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -1392,6 +1396,7 @@ static int select_nth_exec(bContext *C, wmOperator *op)
if (ed_curve_select_nth(obedit->data, &op_params) == true) {
changed = true;
+
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c
index af492de638b..1fd1e217649 100644
--- a/source/blender/editors/curve/editcurve_undo.c
+++ b/source/blender/editors/curve/editcurve_undo.c
@@ -88,12 +88,12 @@ static void undocurve_to_editcurve(Main *bmain, UndoCurve *ucu, Curve *cu, short
if (ad) {
if (ad->action) {
- free_fcurves(&ad->action->curves);
- copy_fcurves(&ad->action->curves, &ucu->fcurves);
+ BKE_fcurves_free(&ad->action->curves);
+ BKE_fcurves_copy(&ad->action->curves, &ucu->fcurves);
}
- free_fcurves(&ad->drivers);
- copy_fcurves(&ad->drivers, &ucu->drivers);
+ BKE_fcurves_free(&ad->drivers);
+ BKE_fcurves_copy(&ad->drivers, &ucu->drivers);
}
/* copy */
@@ -132,10 +132,10 @@ static void undocurve_from_editcurve(UndoCurve *ucu, Curve *cu, const short shap
if (ad) {
if (ad->action) {
- copy_fcurves(&ucu->fcurves, &ad->action->curves);
+ BKE_fcurves_copy(&ucu->fcurves, &ad->action->curves);
}
- copy_fcurves(&ucu->drivers, &ad->drivers);
+ BKE_fcurves_copy(&ucu->drivers, &ad->drivers);
}
/* copy */
@@ -167,8 +167,8 @@ static void undocurve_free_data(UndoCurve *uc)
BKE_curve_editNurb_keyIndex_free(&uc->undoIndex);
- free_fcurves(&uc->fcurves);
- free_fcurves(&uc->drivers);
+ BKE_fcurves_free(&uc->fcurves);
+ BKE_fcurves_free(&uc->drivers);
}
static Object *editcurve_object_from_context(bContext *C)
diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c
index af591e0c7c5..ef9bb7e0c88 100644
--- a/source/blender/editors/curve/editfont_undo.c
+++ b/source/blender/editors/curve/editfont_undo.c
@@ -359,7 +359,7 @@ static void font_undosys_step_decode(
struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final))
{
/* TODO(campbell): undo_system: use low-level API to set mode. */
- ED_object_mode_set(C, OB_MODE_EDIT);
+ ED_object_mode_set_ex(C, OB_MODE_EDIT, false, NULL);
BLI_assert(font_undosys_poll(C));
FontUndoStep *us = (FontUndoStep *)us_p;
diff --git a/source/blender/editors/gizmo_library/CMakeLists.txt b/source/blender/editors/gizmo_library/CMakeLists.txt
index 68a204c04a7..1f3edf31b19 100644
--- a/source/blender/editors/gizmo_library/CMakeLists.txt
+++ b/source/blender/editors/gizmo_library/CMakeLists.txt
@@ -53,6 +53,7 @@ set(SRC
gizmo_types/dial3d_gizmo.c
gizmo_types/move3d_gizmo.c
gizmo_types/primitive3d_gizmo.c
+ gizmo_types/snap3d_gizmo.c
)
set(LIB
diff --git a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
index 374b7b1f6a2..db57a33f543 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
@@ -382,7 +382,7 @@ static int gizmo_move_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
switch (area->spacetype) {
case SPACE_VIEW3D: {
inter->snap_context_v3d = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), 0, CTX_wm_region(C), CTX_wm_view3d(C));
+ CTX_data_scene(C), 0, CTX_wm_region(C), CTX_wm_view3d(C));
break;
}
default:
diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
new file mode 100644
index 00000000000..a3921791427
--- /dev/null
+++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
@@ -0,0 +1,560 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file snap3d_gizmo.c
+ * \ingroup edgizmolib
+ *
+ * \name Snap Gizmo
+ *
+ * 3D Gizmo
+ *
+ * \brief Snap gizmo which exposes the location, normal and index in the props.
+ */
+
+#include "BLI_math.h"
+
+#include "DNA_scene_types.h"
+
+#include "BKE_context.h"
+
+#include "GPU_immediate.h"
+#include "GPU_state.h"
+
+#include "ED_gizmo_library.h"
+#include "ED_screen.h"
+#include "ED_transform_snap_object_context.h"
+#include "ED_view3d.h"
+
+#include "UI_resources.h" /* icons */
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm.h"
+
+/* own includes */
+#include "../gizmo_geometry.h"
+#include "../gizmo_library_intern.h"
+
+typedef struct SnapGizmo3D {
+ wmGizmo gizmo;
+ PropertyRNA *prop_prevpoint;
+ PropertyRNA *prop_location;
+ PropertyRNA *prop_normal;
+ PropertyRNA *prop_elem_index;
+ PropertyRNA *prop_snap_force;
+
+ /* We could have other snap contexts, for now only support 3D view. */
+ SnapObjectContext *snap_context_v3d;
+ int mval[2];
+
+#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ wmKeyMap *keymap;
+ int snap_on;
+ bool invert_snap;
+#endif
+ int use_snap_override;
+ short snap_elem;
+} SnapGizmo3D;
+
+#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+static bool invert_snap(const wmGizmo *gz, const wmWindowManager *wm, const wmEvent *event)
+{
+ SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
+ wmKeyMap *keymap = WM_keymap_active(wm, gizmo_snap->keymap);
+
+ const int snap_on = gizmo_snap->snap_on;
+ for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ if (kmi->flag & KMI_INACTIVE) {
+ continue;
+ }
+
+ if (kmi->propvalue == snap_on) {
+ if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && event->ctrl) ||
+ (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && event->shift) ||
+ (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && event->alt) ||
+ ((kmi->type == EVT_OSKEY) && event->oskey)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+#endif
+
+/* -------------------------------------------------------------------- */
+/** \name ED_gizmo_library specific API
+ * \{ */
+
+void ED_gizmotypes_snap_3d_draw_util(RegionView3D *rv3d,
+ const float loc_prev[3],
+ const float loc_curr[3],
+ const float normal[3],
+ const uchar color_line[4],
+ const uchar color_point[4],
+ const short snap_elem_type)
+{
+ if (!loc_prev && !loc_curr) {
+ return;
+ }
+
+ float view_inv[4][4];
+ copy_m4_m4(view_inv, rv3d->viewinv);
+
+ /* The size of the circle is larger than the vertex size.
+ * This prevents a drawing overlaps the other. */
+ float radius = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (loc_curr) {
+ immUniformColor4ubv(color_point);
+ imm_drawcircball(loc_curr, ED_view3d_pixel_size(rv3d, loc_curr) * radius, view_inv, pos);
+
+ /* draw normal if needed */
+ if (normal) {
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, loc_curr);
+ immVertex3f(pos, loc_curr[0] + normal[0], loc_curr[1] + normal[1], loc_curr[2] + normal[2]);
+ immEnd();
+ }
+ }
+
+ if (loc_prev) {
+ /* Draw an "X" indicating where the previous snap point is.
+ * This is useful for indicating perpendicular snap. */
+
+ /* v1, v2, v3 and v4 indicate the coordinates of the ends of the "X". */
+ float vx[3], vy[3], v1[3], v2[3], v3[3], v4[4];
+
+ /* Multiply by 0.75f so that the final size of the "X" is close to that of
+ * the circle.
+ * (A closer value is 0.7071f, but we don't need to be exact here). */
+ float x_size = 0.75f * radius * ED_view3d_pixel_size(rv3d, loc_prev);
+
+ mul_v3_v3fl(vx, view_inv[0], x_size);
+ mul_v3_v3fl(vy, view_inv[1], x_size);
+
+ add_v3_v3v3(v1, vx, vy);
+ sub_v3_v3v3(v2, vx, vy);
+ negate_v3_v3(v3, v1);
+ negate_v3_v3(v4, v2);
+
+ add_v3_v3(v1, loc_prev);
+ add_v3_v3(v2, loc_prev);
+ add_v3_v3(v3, loc_prev);
+ add_v3_v3(v4, loc_prev);
+
+ immUniformColor4ubv(color_line);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex3fv(pos, v3);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v4);
+ immVertex3fv(pos, v2);
+ immEnd();
+
+ if (loc_curr && (snap_elem_type & SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
+ /* Dashed line. */
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ immUniform1f("dash_width", 6.0f * U.pixelsize);
+ immUniform1f("dash_factor", 1.0f / 4.0f);
+ immUniformColor4ubv(color_line);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, loc_prev);
+ immVertex3fv(pos, loc_curr);
+ immEnd();
+ }
+ }
+
+ immUnbindProgram();
+}
+
+SnapObjectContext *ED_gizmotypes_snap_3d_context_ensure(Scene *scene,
+ const ARegion *region,
+ const View3D *v3d,
+ wmGizmo *gz)
+{
+ SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
+ if (gizmo_snap->snap_context_v3d == NULL) {
+ gizmo_snap->snap_context_v3d = ED_transform_snap_object_context_create_view3d(
+ scene, 0, region, v3d);
+ }
+ return gizmo_snap->snap_context_v3d;
+}
+
+bool ED_gizmotypes_snap_3d_invert_snap_get(struct wmGizmo *gz)
+{
+ SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
+ return gizmo_snap->invert_snap;
+}
+void ED_gizmotypes_snap_3d_toggle_set(wmGizmo *gz, bool enable)
+{
+ SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
+ gizmo_snap->use_snap_override = (int)enable;
+}
+
+void ED_gizmotypes_snap_3d_toggle_clear(wmGizmo *gz)
+{
+ SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
+ gizmo_snap->use_snap_override = -1;
+}
+
+short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
+ struct Depsgraph *depsgraph,
+ const ARegion *region,
+ const View3D *v3d,
+ const wmWindowManager *wm,
+ const float mval_fl[2],
+ float r_loc[3],
+ float r_nor[3])
+{
+ SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
+ Scene *scene = DEG_get_input_scene(depsgraph);
+ float co[3], no[3];
+ short snap_elem = 0;
+ int snap_elem_index[3] = {-1, -1, -1};
+ int index = -1;
+
+ if (gizmo_snap->use_snap_override != -1) {
+ if (gizmo_snap->use_snap_override == false) {
+ gizmo_snap->snap_elem = 0;
+ return 0;
+ }
+ }
+
+#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ if (wm && wm->winactive) {
+ gizmo_snap->invert_snap = invert_snap(gz, wm, wm->winactive->eventstate);
+ }
+
+ if (gizmo_snap->use_snap_override == -1) {
+ const ToolSettings *ts = scene->toolsettings;
+ if (gizmo_snap->invert_snap != !(ts->snap_flag & SCE_SNAP)) {
+ gizmo_snap->snap_elem = 0;
+ return 0;
+ }
+ }
+#else
+ UNUSED_VARS(wm);
+#endif
+
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "snap_elements");
+ int snap_elements = RNA_property_enum_get(&gz_prop->ptr, gz_prop->prop);
+ if (gz_prop->prop != gizmo_snap->prop_snap_force) {
+ int snap_elements_force = RNA_property_enum_get(gz->ptr, gizmo_snap->prop_snap_force);
+ snap_elements |= snap_elements_force;
+ }
+ snap_elements &= (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
+ SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR);
+
+ if (snap_elements) {
+ float prev_co[3] = {0.0f};
+ if (RNA_property_is_set(gz->ptr, gizmo_snap->prop_prevpoint)) {
+ RNA_property_float_get_array(gz->ptr, gizmo_snap->prop_prevpoint, prev_co);
+ }
+ else {
+ snap_elements &= ~SCE_SNAP_MODE_EDGE_PERPENDICULAR;
+ }
+
+ float dist_px = 12.0f * U.pixelsize;
+
+ ED_gizmotypes_snap_3d_context_ensure(scene, region, v3d, gz);
+ snap_elem = ED_transform_snap_object_project_view3d_ex(gizmo_snap->snap_context_v3d,
+ depsgraph,
+ snap_elements,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ .use_occlusion_test = true,
+ },
+ mval_fl,
+ prev_co,
+ &dist_px,
+ co,
+ no,
+ &index,
+ NULL,
+ NULL);
+ }
+
+ if (snap_elem == 0) {
+ RegionView3D *rv3d = region->regiondata;
+ ED_view3d_win_to_3d(v3d, region, rv3d->ofs, mval_fl, co);
+ zero_v3(no);
+ }
+ else if (snap_elem == SCE_SNAP_MODE_VERTEX) {
+ snap_elem_index[0] = index;
+ }
+ else if (snap_elem &
+ (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
+ snap_elem_index[1] = index;
+ }
+ else if (snap_elem == SCE_SNAP_MODE_FACE) {
+ snap_elem_index[2] = index;
+ }
+
+ gizmo_snap->snap_elem = snap_elem;
+ RNA_property_float_set_array(gz->ptr, gizmo_snap->prop_location, co);
+ RNA_property_float_set_array(gz->ptr, gizmo_snap->prop_normal, no);
+ RNA_property_int_set_array(gz->ptr, gizmo_snap->prop_elem_index, snap_elem_index);
+
+ if (r_loc) {
+ copy_v3_v3(r_loc, co);
+ }
+ if (r_nor) {
+ copy_v3_v3(r_nor, no);
+ }
+
+ return snap_elem;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name GIZMO_GT_snap_3d
+ * \{ */
+
+static void gizmo_snap_setup(wmGizmo *gz)
+{
+ SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
+
+ /* For quick access to the props. */
+ gizmo_snap->prop_prevpoint = RNA_struct_find_property(gz->ptr, "prev_point");
+ gizmo_snap->prop_location = RNA_struct_find_property(gz->ptr, "location");
+ gizmo_snap->prop_normal = RNA_struct_find_property(gz->ptr, "normal");
+ gizmo_snap->prop_elem_index = RNA_struct_find_property(gz->ptr, "snap_elem_index");
+ gizmo_snap->prop_snap_force = RNA_struct_find_property(gz->ptr, "snap_elements_force");
+
+ gizmo_snap->use_snap_override = -1;
+
+ /* Prop fallback. */
+ WM_gizmo_target_property_def_rna(gz, "snap_elements", gz->ptr, "snap_elements_force", -1);
+
+ /* Flags. */
+ gz->flag |= WM_GIZMO_NO_TOOLTIP;
+}
+
+static void gizmo_snap_draw(const bContext *C, wmGizmo *gz)
+{
+ SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
+ if (gizmo_snap->snap_elem == 0) {
+ return;
+ }
+
+ ARegion *region = CTX_wm_region(C);
+ RegionView3D *rv3d = region->regiondata;
+
+ /* Ideally, we shouldn't assign values here.
+ * But `test_select` is not called during navigation.
+ * And `snap_elem` is not really useful in this case. */
+ if ((rv3d->rflag & RV3D_NAVIGATING) ||
+ (!(gz->state & WM_GIZMO_STATE_HIGHLIGHT) && !wm_gizmomap_modal_get(region->gizmo_map))) {
+ gizmo_snap->snap_elem = 0;
+ return;
+ }
+
+ float location[3], prev_point_stack[3], *prev_point = NULL;
+ uchar color_line[4], color_point[4];
+
+ RNA_property_float_get_array(gz->ptr, gizmo_snap->prop_location, location);
+
+ UI_GetThemeColor3ubv(TH_TRANSFORM, color_line);
+ color_line[3] = 128;
+
+ rgba_float_to_uchar(color_point, gz->color);
+
+ if (RNA_property_is_set(gz->ptr, gizmo_snap->prop_prevpoint)) {
+ RNA_property_float_get_array(gz->ptr, gizmo_snap->prop_prevpoint, prev_point_stack);
+ prev_point = prev_point_stack;
+ }
+
+ GPU_line_smooth(false);
+
+ GPU_line_width(1.0f);
+ ED_gizmotypes_snap_3d_draw_util(
+ rv3d, prev_point, location, NULL, color_line, color_point, gizmo_snap->snap_elem);
+}
+
+static int gizmo_snap_test_select(bContext *C, wmGizmo *gz, const int mval[2])
+{
+ SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
+
+#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (gizmo_snap->keymap == NULL) {
+ gizmo_snap->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map");
+ RNA_enum_value_from_id(gizmo_snap->keymap->modal_items, "SNAP_ON", &gizmo_snap->snap_on);
+ }
+
+ const bool invert = wm->winactive ? invert_snap(gz, wm, wm->winactive->eventstate) : false;
+ if (gizmo_snap->invert_snap == invert && gizmo_snap->mval[0] == mval[0] &&
+ gizmo_snap->mval[1] == mval[1]) {
+ /* Performance, do not update. */
+ return gizmo_snap->snap_elem ? 0 : -1;
+ }
+
+ gizmo_snap->invert_snap = invert;
+#else
+ if (gizmo_snap->mval[0] == mval[0] && gizmo_snap->mval[1] == mval[1]) {
+ /* Performance, do not update. */
+ return gizmo_snap->snap_elem ? 0 : -1;
+ }
+#endif
+ copy_v2_v2_int(gizmo_snap->mval, mval);
+
+ ARegion *region = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ const float mval_fl[2] = {UNPACK2(mval)};
+ short snap_elem = ED_gizmotypes_snap_3d_update(
+ gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, NULL, mval_fl, NULL, NULL);
+
+ if (snap_elem) {
+ ED_region_tag_redraw_editor_overlays(region);
+ return 0;
+ }
+
+ return -1;
+}
+
+static int gizmo_snap_modal(bContext *UNUSED(C),
+ wmGizmo *UNUSED(gz),
+ const wmEvent *UNUSED(event),
+ eWM_GizmoFlagTweak UNUSED(tweak_flag))
+{
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int gizmo_snap_invoke(bContext *UNUSED(C),
+ wmGizmo *UNUSED(gz),
+ const wmEvent *UNUSED(event))
+{
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void gizmo_snap_free(wmGizmo *gz)
+{
+ SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
+ if (gizmo_snap->snap_context_v3d) {
+ ED_transform_snap_object_context_destroy(gizmo_snap->snap_context_v3d);
+ gizmo_snap->snap_context_v3d = NULL;
+ }
+}
+
+static void GIZMO_GT_snap_3d(wmGizmoType *gzt)
+{
+ /* identifiers */
+ gzt->idname = "GIZMO_GT_snap_3d";
+
+ /* api callbacks */
+ gzt->setup = gizmo_snap_setup;
+ gzt->draw = gizmo_snap_draw;
+ gzt->test_select = gizmo_snap_test_select;
+ gzt->modal = gizmo_snap_modal;
+ gzt->invoke = gizmo_snap_invoke;
+ gzt->free = gizmo_snap_free;
+
+ gzt->struct_size = sizeof(SnapGizmo3D);
+
+ const EnumPropertyItem *rna_enum_snap_element_items;
+ {
+ /* Get Snap Element Items enum. */
+ bool free;
+ PointerRNA toolsettings_ptr;
+ RNA_pointer_create(NULL, &RNA_ToolSettings, NULL, &toolsettings_ptr);
+ PropertyRNA *prop = RNA_struct_find_property(&toolsettings_ptr, "snap_elements");
+ RNA_property_enum_items(
+ NULL, &toolsettings_ptr, prop, &rna_enum_snap_element_items, NULL, &free);
+
+ BLI_assert(free == false);
+ }
+
+ /* Setup. */
+ RNA_def_enum_flag(gzt->srna,
+ "snap_elements_force",
+ rna_enum_snap_element_items,
+ SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE,
+ "Snap Elements",
+ "");
+
+ RNA_def_float_vector(gzt->srna,
+ "prev_point",
+ 3,
+ NULL,
+ FLT_MIN,
+ FLT_MAX,
+ "Previous Point",
+ "Point that defines the location of the perpendicular snap",
+ FLT_MIN,
+ FLT_MAX);
+
+ /* Returns. */
+ RNA_def_float_vector(gzt->srna,
+ "location",
+ 3,
+ NULL,
+ FLT_MIN,
+ FLT_MAX,
+ "Location",
+ "Snap Point Location",
+ FLT_MIN,
+ FLT_MAX);
+
+ RNA_def_float_vector(gzt->srna,
+ "normal",
+ 3,
+ NULL,
+ FLT_MIN,
+ FLT_MAX,
+ "Normal",
+ "Snap Point Normal",
+ FLT_MIN,
+ FLT_MAX);
+
+ RNA_def_int_vector(gzt->srna,
+ "snap_elem_index",
+ 3,
+ NULL,
+ INT_MIN,
+ INT_MAX,
+ "Snap Element",
+ "Array index of face, edge and vert snapped",
+ INT_MIN,
+ INT_MAX);
+
+ /* Read/Write. */
+ WM_gizmotype_target_property_def(gzt, "snap_elements", PROP_ENUM, 1);
+}
+
+void ED_gizmotypes_snap_3d(void)
+{
+ WM_gizmotype_append(GIZMO_GT_snap_3d);
+}
+
+/** \} */
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index c53b90fbfee..723c7d214e3 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -1729,17 +1729,16 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
}
/* Turn brush cursor in 3D view on/off */
-static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable)
+static void gpencil_draw_toggle_eraser_cursor(tGPsdata *p, short enable)
{
if (p->erasercursor && !enable) {
/* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor);
+ WM_paint_cursor_end(p->erasercursor);
p->erasercursor = NULL;
}
else if (enable && !p->erasercursor) {
/* enable cursor */
- p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
+ p->erasercursor = WM_paint_cursor_activate(SPACE_TYPE_ANY,
RGN_TYPE_ANY,
NULL, /* XXX */
gpencil_draw_eraser,
@@ -1794,17 +1793,17 @@ static void gpencil_draw_stabilizer(bContext *C, int x, int y, void *p_ptr)
}
/* Turn *stabilizer* brush cursor in 3D view on/off */
-static void gpencil_draw_toggle_stabilizer_cursor(bContext *C, tGPsdata *p, short enable)
+static void gpencil_draw_toggle_stabilizer_cursor(tGPsdata *p, short enable)
{
if (p->stabilizer_cursor && !enable) {
/* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), p->stabilizer_cursor);
+ WM_paint_cursor_end(p->stabilizer_cursor);
p->stabilizer_cursor = NULL;
}
else if (enable && !p->stabilizer_cursor) {
/* enable cursor */
p->stabilizer_cursor = WM_paint_cursor_activate(
- CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p);
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p);
}
}
@@ -1828,10 +1827,10 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
/* check size of buffer before cleanup, to determine if anything happened here */
if (p->paintmode == GP_PAINTMODE_ERASER) {
/* turn off radial brush cursor */
- gpencil_draw_toggle_eraser_cursor(C, p, false);
+ gpencil_draw_toggle_eraser_cursor(p, false);
}
else if (p->paintmode == GP_PAINTMODE_DRAW) {
- gpencil_draw_toggle_stabilizer_cursor(C, p, false);
+ gpencil_draw_toggle_stabilizer_cursor(p, false);
}
/* always store the new eraser size to be used again next time
@@ -2039,7 +2038,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph
/* handle draw event */
static void annotation_draw_apply_event(
- bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y)
+ wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y)
{
tGPsdata *p = op->customdata;
PointerRNA itemptr;
@@ -2056,14 +2055,14 @@ static void annotation_draw_apply_event(
/* Using permanent stabilization, shift will deactivate the flag. */
if (p->flags & (GP_PAINTFLAG_USE_STABILIZER)) {
if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) {
- gpencil_draw_toggle_stabilizer_cursor(C, p, false);
+ gpencil_draw_toggle_stabilizer_cursor(p, false);
p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP;
}
}
/* Not using any stabilization flag. Activate temporal one. */
else if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) {
p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP;
- gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ gpencil_draw_toggle_stabilizer_cursor(p, true);
}
}
/* verify key status for straight lines */
@@ -2092,7 +2091,7 @@ static void annotation_draw_apply_event(
so activate the temp flag back again. */
if (p->flags & GP_PAINTFLAG_USE_STABILIZER) {
if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) {
- gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ gpencil_draw_toggle_stabilizer_cursor(p, true);
p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP;
}
}
@@ -2102,7 +2101,7 @@ static void annotation_draw_apply_event(
else if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) {
/* Reset temporal stabilizer flag and remove cursor. */
p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP;
- gpencil_draw_toggle_stabilizer_cursor(C, p, false);
+ gpencil_draw_toggle_stabilizer_cursor(p, false);
}
}
@@ -2296,7 +2295,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
/* if eraser is on, draw radial aid */
if (p->paintmode == GP_PAINTMODE_ERASER) {
- gpencil_draw_toggle_eraser_cursor(C, p, true);
+ gpencil_draw_toggle_eraser_cursor(p, true);
}
else if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
if (RNA_enum_get(op->ptr, "arrowstyle_start") != GP_STROKE_ARROWSTYLE_NONE) {
@@ -2313,11 +2312,11 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
p->stabilizer_radius = RNA_int_get(op->ptr, "stabilizer_radius");
if (RNA_boolean_get(op->ptr, "use_stabilizer")) {
p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP;
- gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ gpencil_draw_toggle_stabilizer_cursor(p, true);
}
else if (event->shift > 0) {
p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP;
- gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ gpencil_draw_toggle_stabilizer_cursor(p, true);
}
}
/* set cursor
@@ -2333,7 +2332,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
p->status = GP_STATUS_PAINTING;
/* handle the initial drawing - i.e. for just doing a simple dot */
- annotation_draw_apply_event(C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
+ annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
op->flag |= OP_IS_MODAL_CURSOR_REGION;
}
else {
@@ -2425,7 +2424,7 @@ static void annotation_add_missing_events(bContext *C,
interp_v2_v2v2(pt, a, b, 0.5f);
sub_v2_v2v2(pt, b, pt);
/* create fake event */
- annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]);
+ annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]);
}
else if (dist >= factor) {
int slices = 2 + (int)((dist - 1.0) / factor);
@@ -2434,7 +2433,7 @@ static void annotation_add_missing_events(bContext *C,
interp_v2_v2v2(pt, a, b, n * i);
sub_v2_v2v2(pt, b, pt);
/* create fake event */
- annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]);
+ annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]);
}
}
}
@@ -2562,7 +2561,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* Just hiding this makes it seem like
* you can paint again...
*/
- gpencil_draw_toggle_eraser_cursor(C, p, false);
+ gpencil_draw_toggle_eraser_cursor(p, false);
}
}
@@ -2647,7 +2646,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
p->paintmode = RNA_enum_get(op->ptr, "mode");
}
- gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
+ gpencil_draw_toggle_eraser_cursor(p, p->paintmode == GP_PAINTMODE_ERASER);
/* not painting, so start stroke (this should be mouse-button down) */
p = gpencil_stroke_begin(C, op);
@@ -2681,8 +2680,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* TODO(sergey): Possibly evaluating dependency graph from modal operator? */
- annotation_draw_apply_event(
- C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
+ annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
/* finish painting operation if anything went wrong just now */
if (p->status == GP_STATUS_ERROR) {
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 4444396558b..8771fcb0c8d 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -354,10 +354,6 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op)
/* set mode */
if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
mode = OB_MODE_PAINT_GPENCIL;
- BKE_brush_gpencil_paint_presets(bmain, ts, false);
-
- /* Ensure Palette by default. */
- BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C));
}
else {
mode = OB_MODE_OBJECT;
@@ -373,8 +369,16 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op)
}
if (mode == OB_MODE_PAINT_GPENCIL) {
- /* be sure we have brushes */
+ /* Be sure we have brushes and Paint settings.
+ * Need Draw and Vertex (used for Tint). */
BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
+ BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint);
+
+ BKE_brush_gpencil_paint_presets(bmain, ts, false);
+
+ /* Ensure Palette by default. */
+ BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C));
+
Paint *paint = &ts->gp_paint->paint;
/* if not exist, create a new one */
if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
@@ -466,7 +470,6 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
/* set mode */
if (gpd->flag & GP_DATA_STROKE_SCULPTMODE) {
mode = OB_MODE_SCULPT_GPENCIL;
- BKE_brush_gpencil_sculpt_presets(bmain, ts, false);
}
else {
mode = OB_MODE_OBJECT;
@@ -482,8 +485,12 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
}
if (mode == OB_MODE_SCULPT_GPENCIL) {
- /* be sure we have brushes */
+ /* Be sure we have brushes. */
BKE_paint_ensure(ts, (Paint **)&ts->gp_sculptpaint);
+
+ const bool reset_mode = (ts->gp_sculptpaint->paint.brush == NULL);
+ BKE_brush_gpencil_sculpt_presets(bmain, ts, reset_mode);
+
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_sculptpaint->paint);
}
@@ -572,7 +579,6 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
/* set mode */
if (gpd->flag & GP_DATA_STROKE_WEIGHTMODE) {
mode = OB_MODE_WEIGHT_GPENCIL;
- BKE_brush_gpencil_weight_presets(bmain, ts, false);
}
else {
mode = OB_MODE_OBJECT;
@@ -588,8 +594,12 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
}
if (mode == OB_MODE_WEIGHT_GPENCIL) {
- /* be sure we have brushes */
+ /* Be sure we have brushes. */
BKE_paint_ensure(ts, (Paint **)&ts->gp_weightpaint);
+
+ const bool reset_mode = (ts->gp_weightpaint->paint.brush == NULL);
+ BKE_brush_gpencil_weight_presets(bmain, ts, reset_mode);
+
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_weightpaint->paint);
}
@@ -675,10 +685,6 @@ static int gpencil_vertexmode_toggle_exec(bContext *C, wmOperator *op)
/* set mode */
if (gpd->flag & GP_DATA_STROKE_VERTEXMODE) {
mode = OB_MODE_VERTEX_GPENCIL;
- BKE_brush_gpencil_vertex_presets(bmain, ts, false);
-
- /* Ensure Palette by default. */
- BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C));
}
else {
mode = OB_MODE_OBJECT;
@@ -694,9 +700,16 @@ static int gpencil_vertexmode_toggle_exec(bContext *C, wmOperator *op)
}
if (mode == OB_MODE_VERTEX_GPENCIL) {
- /* be sure we have brushes */
+ /* Be sure we have brushes. */
BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint);
+
+ const bool reset_mode = (ts->gp_vertexpaint->paint.brush == NULL);
+ BKE_brush_gpencil_vertex_presets(bmain, ts, reset_mode);
+
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_vertexpaint->paint);
+
+ /* Ensure Palette by default. */
+ BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C));
}
/* setup other modes */
@@ -3656,7 +3669,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
int cfra_prv = INT_MIN;
/* init snap context for geometry projection */
- sctx = ED_transform_snap_object_context_create_view3d(bmain, scene, 0, region, CTX_wm_view3d(C));
+ sctx = ED_transform_snap_object_context_create_view3d(scene, 0, region, CTX_wm_view3d(C));
/* Go through each editable + selected stroke, adjusting each of its points one by one... */
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 4e83c4fb11c..06079c34d12 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -2299,18 +2299,17 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
}
/* Turn brush cursor in 3D view on/off */
-static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable)
+static void gpencil_draw_toggle_eraser_cursor(tGPsdata *p, short enable)
{
if (p->erasercursor && !enable) {
/* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor);
+ WM_paint_cursor_end(p->erasercursor);
p->erasercursor = NULL;
}
else if (enable && !p->erasercursor) {
ED_gpencil_toggle_brush_cursor(p->C, false, NULL);
/* enable cursor */
- p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
+ p->erasercursor = WM_paint_cursor_activate(SPACE_TYPE_ANY,
RGN_TYPE_ANY,
NULL, /* XXX */
gpencil_draw_eraser,
@@ -2335,7 +2334,7 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
/* check size of buffer before cleanup, to determine if anything happened here */
if (p->paintmode == GP_PAINTMODE_ERASER) {
/* turn off radial brush cursor */
- gpencil_draw_toggle_eraser_cursor(C, p, false);
+ gpencil_draw_toggle_eraser_cursor(p, false);
}
/* always store the new eraser size to be used again next time
@@ -3154,7 +3153,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
/* TODO: set any additional settings that we can take from the events?
* if eraser is on, draw radial aid */
if (p->paintmode == GP_PAINTMODE_ERASER) {
- gpencil_draw_toggle_eraser_cursor(C, p, true);
+ gpencil_draw_toggle_eraser_cursor(p, true);
}
else {
ED_gpencil_toggle_brush_cursor(C, true, NULL);
@@ -3700,7 +3699,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
p->paintmode = RNA_enum_get(op->ptr, "mode");
}
- gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
+ gpencil_draw_toggle_eraser_cursor(p, p->paintmode == GP_PAINTMODE_ERASER);
/* not painting, so start stroke (this should be mouse-button down) */
p = gpencil_stroke_begin(C, op);
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 69d22b52ded..c41b2993a80 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -43,6 +43,7 @@
#include "BKE_context.h"
#include "BKE_gpencil.h"
+#include "BKE_material.h"
#include "BKE_report.h"
#include "UI_interface.h"
@@ -1118,10 +1119,8 @@ typedef bool (*GPencilTestFn)(bGPDstroke *gps,
const float diff_mat[4][4],
void *user_data);
-static int gpencil_generic_select_exec(bContext *C,
- wmOperator *op,
- GPencilTestFn is_inside_fn,
- void *user_data)
+static int gpencil_generic_select_exec(
+ bContext *C, wmOperator *op, GPencilTestFn is_inside_fn, rcti box, void *user_data)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
@@ -1143,7 +1142,6 @@ static int gpencil_generic_select_exec(bContext *C,
((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0));
const bool segmentmode = ((selectmode == GP_SELECTMODE_SEGMENT) &&
((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0));
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
const float scale = ts->gp_sculpt.isect_threshold;
@@ -1180,15 +1178,13 @@ static int gpencil_generic_select_exec(bContext *C,
/* select/deselect points */
GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
+ bool whole = false;
bGPDspoint *pt;
int i;
bool hit = false;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->runtime.pt_orig == NULL) {
- continue;
- }
- bGPDspoint *pt_active = pt->runtime.pt_orig;
+ bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
/* convert point coords to screenspace */
const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
@@ -1198,9 +1194,10 @@ static int gpencil_generic_select_exec(bContext *C,
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(pt_active->flag, sel_op_result, GP_SPOINT_SELECT);
changed = true;
+ hit = true;
- /* expand selection to segment */
- if ((sel_op_result != -1) && (segmentmode)) {
+ /* Expand selection to segment. */
+ if (segmentmode) {
bool hit_select = (bool)(pt_active->flag & GP_SPOINT_SELECT);
float r_hita[3], r_hitb[3];
ED_gpencil_select_stroke_segment(
@@ -1216,16 +1213,28 @@ static int gpencil_generic_select_exec(bContext *C,
}
}
- /* if stroke mode expand selection */
- if (strokemode) {
- const bool is_select = BKE_gpencil_stroke_select_check(gps_active);
- const bool is_inside = hit;
+ /* If nothing hit, check if the mouse is inside a filled stroke using the center or
+ * Box or lasso area. */
+ if (!hit) {
+ /* Only check filled strokes. */
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) {
+ continue;
+ }
+ int mval[2];
+ mval[0] = (box.xmax + box.xmin) / 2;
+ mval[1] = (box.ymax + box.ymin) / 2;
+
+ whole = ED_gpencil_stroke_point_is_inside(gps_active, &gsc, mval, gpstroke_iter.diff_mat);
+ }
+
+ /* if stroke mode expand selection. */
+ if ((strokemode) || (whole)) {
+ const bool is_select = BKE_gpencil_stroke_select_check(gps_active) || whole;
+ const bool is_inside = hit || whole;
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
- continue;
- }
bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
if (sel_op_result) {
@@ -1261,7 +1270,6 @@ static int gpencil_generic_select_exec(bContext *C,
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
}
-
return OPERATOR_FINISHED;
}
@@ -1293,7 +1301,8 @@ static int gpencil_box_select_exec(bContext *C, wmOperator *op)
{
struct GP_SelectBoxUserData data = {0};
WM_operator_properties_border_to_rcti(op, &data.rect);
- return gpencil_generic_select_exec(C, op, gpencil_test_box, &data);
+ rcti rect = data.rect;
+ return gpencil_generic_select_exec(C, op, gpencil_test_box, rect, &data);
}
void GPENCIL_OT_select_box(wmOperatorType *ot)
@@ -1360,7 +1369,8 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op)
/* Compute boundbox of lasso (for faster testing later). */
BLI_lasso_boundbox(&data.rect, data.mcoords, data.mcoords_len);
- int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, &data);
+ rcti rect = data.rect;
+ int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, rect, &data);
MEM_freeN((void *)data.mcoords);
@@ -1424,7 +1434,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
/* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */
- const float radius = 0.50f * U.widget_unit;
+ const float radius = 0.4f * U.widget_unit;
const int radius_squared = (int)(radius * radius);
const bool use_shift_extend = RNA_boolean_get(op->ptr, "use_shift_extend");
@@ -1469,12 +1479,19 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
RNA_int_get_array(op->ptr, "location", mval);
/* First Pass: Find stroke point which gets hit */
- /* XXX: maybe we should go from the top of the stack down instead... */
GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt;
int i;
+ /* Check boundbox to speedup. */
+ float fmval[2];
+ copy_v2fl_v2i(fmval, mval);
+ if (!ED_gpencil_stroke_check_collision(
+ &gsc, gps_active, fmval, radius, gpstroke_iter.diff_mat)) {
+ continue;
+ }
+
/* firstly, check for hit-point */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
int xy[2];
@@ -1502,11 +1519,27 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
}
}
}
+ if (ELEM(NULL, hit_stroke, hit_point)) {
+ /* If nothing hit, check if the mouse is inside any filled stroke.
+ * Only check filling materials. */
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) {
+ continue;
+ }
+ bool hit_fill = ED_gpencil_stroke_point_is_inside(gps, &gsc, mval, gpstroke_iter.diff_mat);
+ if (hit_fill) {
+ hit_stroke = gps_active;
+ hit_point = &gps_active->points[0];
+ /* Extend selection to all stroke. */
+ whole = true;
+ }
+ }
}
GP_EVALUATED_STROKES_END(gpstroke_iter);
/* Abort if nothing hit... */
if (ELEM(NULL, hit_stroke, hit_point)) {
+
if (deselect_all) {
/* since left mouse select change, deselect all if click outside any hit */
deselect_all_selected(C);
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 3cab26eab44..876fa7c9874 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -31,6 +31,7 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_hash.h"
+#include "BLI_lasso_2d.h"
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_utildefines.h"
@@ -1871,19 +1872,18 @@ void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata)
if (gset->paintcursor && !enable) {
/* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
+ WM_paint_cursor_end(gset->paintcursor);
gset->paintcursor = NULL;
}
else if (enable) {
/* in some situations cursor could be duplicated, so it is better disable first if exist */
if (gset->paintcursor) {
/* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
+ WM_paint_cursor_end(gset->paintcursor);
gset->paintcursor = NULL;
}
/* enable cursor */
- gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
+ gset->paintcursor = WM_paint_cursor_activate(SPACE_TYPE_ANY,
RGN_TYPE_ANY,
gp_brush_cursor_poll,
gp_brush_cursor_draw,
@@ -2800,3 +2800,49 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc,
/* Check collision between both rectangles. */
return BLI_rcti_isect(&rect_stroke, &rect_mouse, NULL);
}
+
+/**
+ * Check if a point is inside of the stroke
+ * \param gps: Stroke to check
+ * \param gsc: SpaceConversion data
+ * \param mouse: Mouse position
+ * \param diff_mat: View matrix
+ * \return True if the point is inside
+ */
+bool ED_gpencil_stroke_point_is_inside(bGPDstroke *gps,
+ GP_SpaceConversion *gsc,
+ int mouse[2],
+ const float diff_mat[4][4])
+{
+ bool hit = false;
+ if (gps->totpoints == 0) {
+ return hit;
+ }
+
+ int(*mcoords)[2] = NULL;
+ int len = gps->totpoints;
+ mcoords = MEM_mallocN(sizeof(int) * 2 * len, __func__);
+
+ /* Convert stroke to 2D array of points. */
+ bGPDspoint *pt;
+ int i;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ bGPDspoint pt2;
+ gp_point_to_parent_space(pt, diff_mat, &pt2);
+ gp_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]);
+ }
+
+ /* Compute boundbox of lasso (for faster testing later). */
+ rcti rect;
+ BLI_lasso_boundbox(&rect, mcoords, len);
+
+ /* Test if point inside stroke. */
+ hit = ((!ELEM(V2D_IS_CLIPPED, mouse[0], mouse[1])) &&
+ BLI_rcti_isect_pt(&rect, mouse[0], mouse[1]) &&
+ BLI_lasso_is_point_inside(mcoords, len, mouse[0], mouse[1], INT_MAX));
+
+ /* Free memory. */
+ MEM_SAFE_FREE(mcoords);
+
+ return hit;
+}
diff --git a/source/blender/editors/gpencil/gpencil_uv.c b/source/blender/editors/gpencil/gpencil_uv.c
index 2238d768bcd..0dfc7e0728e 100644
--- a/source/blender/editors/gpencil/gpencil_uv.c
+++ b/source/blender/editors/gpencil/gpencil_uv.c
@@ -59,8 +59,8 @@ typedef struct GpUvData {
float ob_scale;
float initial_length;
+ float initial_transform[2];
float pixel_size; /* use when mouse input is interpreted as spatial distance */
- bool is_modal;
/* Arrays of original loc/rot/scale by stroke. */
float (*array_loc)[2];
@@ -140,19 +140,12 @@ static void gpencil_stroke_center(bGPDstroke *gps, float r_center[3])
}
}
-static bool gpencil_uv_transform_init(bContext *C, wmOperator *op, const bool is_modal)
+static bool gpencil_uv_transform_init(bContext *C, wmOperator *op)
{
GpUvData *opdata;
- if (is_modal) {
- float zero[2] = {0.0f};
- RNA_float_set_array(op->ptr, "location", zero);
- RNA_float_set(op->ptr, "rotation", 0.0f);
- RNA_float_set(op->ptr, "scale", 1.0f);
- }
op->customdata = opdata = MEM_mallocN(sizeof(GpUvData), __func__);
- opdata->is_modal = is_modal;
opdata->ob = CTX_data_active_object(C);
opdata->gpd = (bGPdata *)opdata->ob->data;
gp_point_conversion_init(C, &opdata->gsc);
@@ -164,12 +157,10 @@ static bool gpencil_uv_transform_init(bContext *C, wmOperator *op, const bool is
opdata->vinit_rotation[0] = 1.0f;
opdata->vinit_rotation[1] = 0.0f;
- if (is_modal) {
- ARegion *region = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- opdata->draw_handle_pixel = ED_region_draw_cb_activate(
- region->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
- }
+ opdata->draw_handle_pixel = ED_region_draw_cb_activate(
+ region->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
/* Calc selected strokes center. */
zero_v2(opdata->mcenter);
@@ -205,7 +196,7 @@ static bool gpencil_uv_transform_init(bContext *C, wmOperator *op, const bool is
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
}
- /* convert to 2D */
+ /* Convert to 2D. */
gp_point_3d_to_xy(&opdata->gsc, GP_STROKE_3DSPACE, center, opdata->mcenter);
return true;
@@ -218,11 +209,9 @@ static void gpencil_uv_transform_exit(bContext *C, wmOperator *op)
opdata = op->customdata;
- if (opdata->is_modal) {
- ARegion *region = CTX_wm_region(C);
+ ARegion *region = CTX_wm_region(C);
- ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel);
- }
+ ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel);
WM_cursor_set(CTX_wm_window(C), WM_CURSOR_DEFAULT);
@@ -253,66 +242,54 @@ static bool gpencil_uv_transform_calc(bContext *C, wmOperator *op)
const int mode = RNA_enum_get(op->ptr, "mode");
GpUvData *opdata = op->customdata;
bGPdata *gpd = opdata->gpd;
+
bool changed = false;
/* Get actual vector. */
float vr[2];
+ float mdiff[2];
+
sub_v2_v2v2(vr, opdata->mouse, opdata->mcenter);
normalize_v2(vr);
- float location[2];
- RNA_float_get_array(op->ptr, "location", location);
-
- float uv_rotation = (opdata->is_modal) ? angle_signed_v2v2(opdata->vinit_rotation, vr) :
- RNA_float_get(op->ptr, "rotation");
- uv_rotation *= SMOOTH_FACTOR;
-
- if (opdata->is_modal) {
- RNA_float_set(op->ptr, "rotation", uv_rotation);
- }
+ float uv_rotation = angle_signed_v2v2(opdata->vinit_rotation, vr);
int i = 0;
- /* Apply transformations to all strokes. */
- if ((mode == GP_UV_TRANSLATE) || (!opdata->is_modal)) {
- float mdiff[2];
- mdiff[0] = opdata->mcenter[0] - opdata->mouse[0];
- mdiff[1] = opdata->mcenter[1] - opdata->mouse[1];
+ /* Translate. */
+ if (mode == GP_UV_TRANSLATE) {
+
+ mdiff[0] = opdata->mouse[0] - opdata->initial_transform[0];
+ /* Y axis is inverted. */
+ mdiff[1] = (opdata->mouse[1] - opdata->initial_transform[1]) * -1.0f;
/* Apply a big amount of smooth always for translate to get smooth result. */
- mul_v2_fl(mdiff, 0.006f);
+ mul_v2_fl(mdiff, 0.002f);
+ RNA_float_set_array(op->ptr, "location", mdiff);
- /* Apply angle in translation. */
- mdiff[0] *= cos(uv_rotation);
- mdiff[1] *= sin(uv_rotation);
- if (opdata->is_modal) {
- RNA_float_set_array(op->ptr, "location", mdiff);
- }
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (gps->flag & GP_STROKE_SELECT) {
- changed = (bool)((mdiff[0] != 0.0f) || (mdiff[1] != 0.0f));
- if (changed) {
- GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
- if (gps->flag & GP_STROKE_SELECT) {
- if (opdata->is_modal) {
- add_v2_v2v2(gps->uv_translation, opdata->array_loc[i], mdiff);
- }
- else {
- copy_v2_v2(gps->uv_translation, location);
- }
- /* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(gps);
- i++;
- }
+ sub_v2_v2v2(gps->uv_translation, opdata->array_loc[i], mdiff);
+ changed = true;
+
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+ i++;
}
- GP_EDITABLE_STROKES_END(gpstroke_iter);
}
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
}
- if ((mode == GP_UV_ROTATE) || (!opdata->is_modal)) {
- changed = (bool)(uv_rotation != 0.0f);
+ /* Rotate. */
+ if (mode == GP_UV_ROTATE) {
+ changed |= (bool)(uv_rotation != 0.0f);
+ RNA_float_set(op->ptr, "rotation", uv_rotation);
+
if (changed) {
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
- gps->uv_rotation = (opdata->is_modal) ? opdata->array_rot[i] + uv_rotation : uv_rotation;
+ gps->uv_rotation = opdata->array_rot[i] - uv_rotation;
+
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
i++;
@@ -322,25 +299,22 @@ static bool gpencil_uv_transform_calc(bContext *C, wmOperator *op)
}
}
- if ((mode == GP_UV_SCALE) || (!opdata->is_modal)) {
- float mdiff[2];
+ /* Scale. */
+ if (mode == GP_UV_SCALE) {
mdiff[0] = opdata->mcenter[0] - opdata->mouse[0];
mdiff[1] = opdata->mcenter[1] - opdata->mouse[1];
- float scale = (opdata->is_modal) ?
- ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size) /
- opdata->ob_scale :
- RNA_float_get(op->ptr, "scale");
+ float scale = ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size) /
+ opdata->ob_scale;
+
scale *= SMOOTH_FACTOR;
+ RNA_float_set(op->ptr, "scale", scale);
- if (opdata->is_modal) {
- RNA_float_set(op->ptr, "scale", scale);
- }
+ changed |= (bool)(scale != 0.0f);
- changed = (bool)(scale != 0.0f);
if (changed) {
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
- gps->uv_scale = (opdata->is_modal) ? opdata->array_scale[i] + scale : scale;
+ gps->uv_scale = opdata->array_scale[i] + scale;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
i++;
@@ -350,7 +324,7 @@ static bool gpencil_uv_transform_calc(bContext *C, wmOperator *op)
}
}
- if ((!opdata->is_modal) || (changed)) {
+ if (changed) {
/* Update cursor line. */
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, NULL);
@@ -360,21 +334,6 @@ static bool gpencil_uv_transform_calc(bContext *C, wmOperator *op)
return changed;
}
-static int gpencil_transform_fill_exec(bContext *C, wmOperator *op)
-{
- if (!gpencil_uv_transform_init(C, op, false)) {
- return OPERATOR_CANCELLED;
- }
-
- if (!gpencil_uv_transform_calc(C, op)) {
- gpencil_uv_transform_exit(C, op);
- return OPERATOR_CANCELLED;
- }
-
- gpencil_uv_transform_exit(C, op);
- return OPERATOR_FINISHED;
-}
-
static bool gpencil_transform_fill_poll(bContext *C)
{
if (!ED_operator_view3d_active(C)) {
@@ -404,7 +363,7 @@ static int gpencil_transform_fill_invoke(bContext *C, wmOperator *op, const wmEv
float mlen[2];
float center_3d[3];
- if (!gpencil_uv_transform_init(C, op, true)) {
+ if (!gpencil_uv_transform_init(C, op)) {
return OPERATOR_CANCELLED;
}
@@ -414,16 +373,22 @@ static int gpencil_transform_fill_invoke(bContext *C, wmOperator *op, const wmEv
opdata->mouse[1] = event->mval[1];
copy_v3_v3(center_3d, opdata->ob->loc);
- mlen[0] = opdata->mcenter[0] - event->mval[0];
- mlen[1] = opdata->mcenter[1] - event->mval[1];
+ mlen[0] = event->mval[0] - opdata->mcenter[0];
+ mlen[1] = event->mval[1] - opdata->mcenter[1];
opdata->initial_length = len_v2(mlen);
- opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
+ /* Consider initial offset as zero position. */
+ copy_v2fl_v2i(opdata->initial_transform, event->mval);
+
+ /* Consider initial position as the orientation vector. */
+ const int mode = RNA_enum_get(op->ptr, "mode");
+ if (mode == GP_UV_ROTATE) {
+ opdata->vinit_rotation[0] = mlen[0];
+ opdata->vinit_rotation[1] = mlen[1];
+ normalize_v2(opdata->vinit_rotation);
+ }
- /* Calc init rotation vector. */
- float mouse[2] = {event->mval[0], event->mval[1]};
- sub_v2_v2v2(opdata->vinit_rotation, mouse, opdata->mcenter);
- normalize_v2(opdata->vinit_rotation);
+ opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
gpencil_uv_transform_calc(C, op);
@@ -492,7 +457,6 @@ void GPENCIL_OT_transform_fill(wmOperatorType *ot)
/* api callbacks */
ot->invoke = gpencil_transform_fill_invoke;
ot->modal = gpencil_transform_fill_modal;
- ot->exec = gpencil_transform_fill_exec;
ot->cancel = gpencil_transform_fill_cancel;
ot->poll = gpencil_transform_fill_poll;
diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c
index 10867bd1e0d..581a5d977c2 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_paint.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c
@@ -36,6 +36,7 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
+#include "BKE_material.h"
#include "BKE_report.h"
#include "WM_api.h"
@@ -433,10 +434,9 @@ static bool brush_tint_apply(tGP_BrushVertexpaintData *gso,
CLAMP(inf, 0.0f, 1.0f);
CLAMP(inf_fill, 0.0f, 1.0f);
- bGPDspoint *pt = &gps->points[pt_index];
-
/* Apply color to Stroke point. */
- if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
+ if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush) && (pt_index > -1)) {
+ bGPDspoint *pt = &gps->points[pt_index];
if (brush_invert_check(gso)) {
pt->vert_color[3] -= inf;
CLAMP_MIN(pt->vert_color[3], 0.0f);
@@ -813,15 +813,18 @@ static void gp_save_selected_point(tGP_BrushVertexpaintData *gso,
selected = &gso->pbuffer[gso->pbuffer_used];
selected->gps = gps;
selected->pt_index = index;
- copy_v2_v2_int(selected->pc, pc);
- copy_v4_v4(selected->color, pt->vert_color);
-
+ /* Check the index is not a special case for fill. */
+ if (index > -1) {
+ copy_v2_v2_int(selected->pc, pc);
+ copy_v4_v4(selected->color, pt->vert_color);
+ }
gso->pbuffer_used++;
}
/* Select points in this stroke and add to an array to be used later. */
static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
bGPDstroke *gps,
+ const char tool,
const float diff_mat[4][4])
{
GP_SpaceConversion *gsc = &gso->gsc;
@@ -869,6 +872,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
/* Loop over the points in the stroke, checking for intersections
* - an intersection means that we touched the stroke
*/
+ bool hit = false;
for (i = 0; (i + 1) < gps->totpoints; i++) {
/* Get points to work with */
pt1 = gps->points + i;
@@ -904,6 +908,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
if (pt_active != NULL) {
+ hit = true;
gp_save_selected_point(gso, gps_active, index, pc1);
}
@@ -920,6 +925,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1;
if (pt_active != NULL) {
+ hit = true;
gp_save_selected_point(gso, gps_active, index, pc2);
include_last = false;
}
@@ -938,6 +944,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
if (pt_active != NULL) {
+ hit = true;
gp_save_selected_point(gso, gps_active, index, pc1);
include_last = false;
@@ -945,6 +952,24 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
}
}
}
+
+ /* If nothing hit, check if the mouse is inside any filled stroke. */
+ if ((!hit) && (ELEM(tool, GPAINT_TOOL_TINT, GPVERTEX_TOOL_DRAW))) {
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(gso->object,
+ gps_active->mat_nr + 1);
+ if (gp_style->flag & GP_MATERIAL_FILL_SHOW) {
+ int mval[2];
+ round_v2i_v2fl(mval, gso->mval);
+ bool hit_fill = ED_gpencil_stroke_point_is_inside(gps_active, gsc, mval, diff_mat);
+ if (hit_fill) {
+ /* Need repeat the effect because if we don't do that the tint process
+ * is very slow. */
+ for (int repeat = 0; repeat < 50; repeat++) {
+ gp_save_selected_point(gso, gps_active, -1, NULL);
+ }
+ }
+ }
+ }
}
}
@@ -956,8 +981,8 @@ static bool gp_vertexpaint_brush_do_frame(bContext *C,
const float diff_mat[4][4])
{
Object *ob = CTX_data_active_object(C);
- char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool :
- gso->brush->gpencil_tool;
+ const char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool :
+ gso->brush->gpencil_tool;
const int radius = (gso->brush->flag & GP_BRUSH_USE_PRESSURE) ?
gso->brush->size * gso->pressure :
gso->brush->size;
@@ -980,7 +1005,7 @@ static bool gp_vertexpaint_brush_do_frame(bContext *C,
}
/* Check points below the brush. */
- gp_vertexpaint_select_stroke(gso, gps, diff_mat);
+ gp_vertexpaint_select_stroke(gso, gps, tool, diff_mat);
}
/* For Average tool, need calculate the average resulting color from all colors
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 7d38792f332..426a470b128 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -652,9 +652,6 @@ enum eAnimEditDraw_CurrentFrame {
/* main call to draw current-frame indicator in an Animation Editor */
void ANIM_draw_cfra(const struct bContext *C, struct View2D *v2d, short flag);
-/* main call to draw "number box" in scrollbar for current frame indicator */
-void ANIM_draw_cfra_number(const struct bContext *C, struct View2D *v2d, short flag);
-
/* ------------- Preview Range Drawing -------------- */
/* main call to draw preview range curtains */
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 102c0dc0659..ac9eb415b23 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -120,13 +120,11 @@ typedef struct EditBone {
} temp;
} EditBone;
-#define BONESEL_ROOT (1 << 28)
-#define BONESEL_TIP (1 << 29)
-#define BONESEL_BONE (1 << 30)
+#define BONESEL_ROOT (2 << 29u)
+#define BONESEL_TIP (1 << 30u)
+#define BONESEL_BONE (1 << 31u)
#define BONESEL_ANY (BONESEL_TIP | BONESEL_ROOT | BONESEL_BONE)
-#define BONESEL_NOSEL (1u << 31u)
-
/* useful macros */
#define EBONE_VISIBLE(arm, ebone) \
(CHECK_TYPE_INLINE(arm, bArmature *), \
diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h
index 07eade23506..a1a5d65b61d 100644
--- a/source/blender/editors/include/ED_gizmo_library.h
+++ b/source/blender/editors/include/ED_gizmo_library.h
@@ -40,9 +40,15 @@ void ED_gizmotypes_facemap_3d(void);
void ED_gizmotypes_preselect_3d(void);
void ED_gizmotypes_primitive_3d(void);
void ED_gizmotypes_blank_3d(void);
+void ED_gizmotypes_snap_3d(void);
-struct Object;
+struct ARegion;
struct bContext;
+struct Depsgraph;
+struct Object;
+struct SnapObjectContext;
+struct wmWindowManager;
+struct View3D;
struct wmGizmo;
/* -------------------------------------------------------------------- */
@@ -223,8 +229,9 @@ enum {
};
/* -------------------------------------------------------------------- */
-/* Gizmo Drawing Functions */
+/* Specific gizmos utils */
+/* dial3d_gizmo.c */
struct Dial3dParams {
int draw_options;
float angle_ofs;
@@ -241,6 +248,33 @@ void ED_gizmotypes_dial_3d_draw_util(const float matrix_basis[4][4],
const bool select,
struct Dial3dParams *params);
+/* snap3d_gizmo.c */
+#define USE_SNAP_DETECT_FROM_KEYMAP_HACK
+void ED_gizmotypes_snap_3d_draw_util(struct RegionView3D *rv3d,
+ const float loc_prev[3],
+ const float loc_curr[3],
+ const float normal[3],
+ const uchar color_line[4],
+ const uchar color_point[4],
+ const short snap_elem_type);
+struct SnapObjectContext *ED_gizmotypes_snap_3d_context_ensure(struct Scene *scene,
+ const struct ARegion *region,
+ const struct View3D *v3d,
+ struct wmGizmo *gz);
+
+bool ED_gizmotypes_snap_3d_invert_snap_get(struct wmGizmo *gz);
+void ED_gizmotypes_snap_3d_toggle_set(struct wmGizmo *gz, bool enable);
+void ED_gizmotypes_snap_3d_toggle_clear(struct wmGizmo *gz);
+
+short ED_gizmotypes_snap_3d_update(struct wmGizmo *gz,
+ struct Depsgraph *depsgraph,
+ const struct ARegion *region,
+ const struct View3D *v3d,
+ const struct wmWindowManager *wm,
+ const float mval_fl[2],
+ float r_loc[3],
+ float r_nor[3]);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 2dbd979564e..0c228fc962b 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -34,13 +34,13 @@ struct PointerRNA;
struct Brush;
struct GP_SpaceConversion;
+struct GpRandomSettings;
struct bGPDframe;
struct bGPDlayer;
struct bGPDspoint;
struct bGPDstroke;
struct bGPdata;
struct tGPspoint;
-struct GpRandomSettings;
struct ARegion;
struct Depsgraph;
@@ -317,6 +317,10 @@ bool ED_gpencil_stroke_check_collision(struct GP_SpaceConversion *gsc,
float mouse[2],
const int radius,
const float diff_mat[4][4]);
+bool ED_gpencil_stroke_point_is_inside(struct bGPDstroke *gps,
+ struct GP_SpaceConversion *gsc,
+ int mouse[2],
+ const float diff_mat[4][4]);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 1dc98cfee2f..3471f9dcce9 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -107,7 +107,10 @@ void ED_node_texture_default(const struct bContext *C, struct Tex *tex);
bool ED_node_select_check(ListBase *lb);
void ED_node_select_all(ListBase *lb, int action);
void ED_node_post_apply_transform(struct bContext *C, struct bNodeTree *ntree);
-void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
+void ED_node_set_active(struct Main *bmain,
+ struct bNodeTree *ntree,
+ struct bNode *node,
+ bool *r_active_texture_changed);
void ED_node_composite_job(const struct bContext *C,
struct bNodeTree *nodetree,
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 146dd3eb8b8..f25f8225976 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -212,13 +212,11 @@ bool ED_object_editmode_load(struct Main *bmain, struct Object *obedit);
void ED_object_vpaintmode_enter_ex(struct Main *bmain,
struct Depsgraph *depsgraph,
- struct wmWindowManager *wm,
struct Scene *scene,
struct Object *ob);
void ED_object_vpaintmode_enter(struct bContext *C, struct Depsgraph *depsgraph);
void ED_object_wpaintmode_enter_ex(struct Main *bmain,
struct Depsgraph *depsgraph,
- struct wmWindowManager *wm,
struct Scene *scene,
struct Object *ob);
void ED_object_wpaintmode_enter(struct bContext *C, struct Depsgraph *depsgraph);
@@ -228,6 +226,20 @@ void ED_object_vpaintmode_exit(struct bContext *C);
void ED_object_wpaintmode_exit_ex(struct Object *ob);
void ED_object_wpaintmode_exit(struct bContext *C);
+void ED_object_texture_paint_mode_enter_ex(struct Main *bmain, struct Scene *scene, Object *ob);
+void ED_object_texture_paint_mode_enter(struct bContext *C);
+
+void ED_object_texture_paint_mode_exit_ex(struct Main *bmain, struct Scene *scene, Object *ob);
+void ED_object_texture_paint_mode_exit(struct bContext *C);
+
+void ED_object_particle_edit_mode_enter_ex(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ Object *ob);
+void ED_object_particle_edit_mode_enter(struct bContext *C);
+
+void ED_object_particle_edit_mode_exit_ex(struct Scene *scene, Object *ob);
+void ED_object_particle_edit_mode_exit(struct bContext *C);
+
void ED_object_sculptmode_enter_ex(struct Main *bmain,
struct Depsgraph *depsgraph,
struct Scene *scene,
@@ -269,6 +281,7 @@ bool ED_object_add_generic_get_opts(struct bContext *C,
const char view_align_axis,
float loc[3],
float rot[3],
+ float scale[3],
bool *enter_editmode,
unsigned short *local_view_bits,
bool *is_view_aligned);
@@ -303,15 +316,15 @@ void ED_objects_recalculate_paths(struct bContext *C,
eObjectPathCalcRange range);
/* constraints */
-struct ListBase *get_active_constraints(struct Object *ob);
-struct ListBase *get_constraint_lb(struct Object *ob,
- struct bConstraint *con,
- struct bPoseChannel **r_pchan);
-struct bConstraint *get_active_constraint(struct Object *ob);
+struct ListBase *ED_object_constraint_list_from_context(struct Object *ob);
+struct ListBase *ED_object_constraint_list_from_constraint(struct Object *ob,
+ struct bConstraint *con,
+ struct bPoseChannel **r_pchan);
+struct bConstraint *ED_object_constraint_active_get(struct Object *ob);
void object_test_constraints(struct Main *bmain, struct Object *ob);
-void ED_object_constraint_set_active(struct Object *ob, struct bConstraint *con);
+void ED_object_constraint_active_set(struct Object *ob, struct bConstraint *con);
void ED_object_constraint_update(struct Main *bmain, struct Object *ob);
void ED_object_constraint_dependency_update(struct Main *bmain, struct Object *ob);
@@ -328,11 +341,12 @@ bool ED_object_mode_compat_set(struct bContext *C,
struct Object *ob,
eObjectMode mode,
struct ReportList *reports);
-void ED_object_mode_toggle(struct bContext *C, eObjectMode mode);
-void ED_object_mode_set(struct bContext *C, eObjectMode mode);
-void ED_object_mode_exit(struct bContext *C, struct Depsgraph *depsgraph);
+bool ED_object_mode_set_ex(struct bContext *C,
+ eObjectMode mode,
+ bool use_undo,
+ struct ReportList *reports);
+bool ED_object_mode_set(struct bContext *C, eObjectMode mode);
-bool ED_object_mode_generic_enter(struct bContext *C, eObjectMode object_mode);
void ED_object_mode_generic_exit(struct Main *bmain,
struct Depsgraph *depsgraph,
struct Scene *scene,
diff --git a/source/blender/editors/include/ED_outliner.h b/source/blender/editors/include/ED_outliner.h
index d3fc5174dd9..0325ad9fdba 100644
--- a/source/blender/editors/include/ED_outliner.h
+++ b/source/blender/editors/include/ED_outliner.h
@@ -29,6 +29,7 @@ extern "C" {
struct Base;
struct ListBase;
+struct SpaceOutliner;
struct bContext;
bool ED_outliner_collections_editor_poll(struct bContext *C);
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 9969acd04b7..a62deb9d69f 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -162,6 +162,19 @@ int BIF_countTransformOrientation(const struct bContext *C);
void Transform_Properties(struct wmOperatorType *ot, int flags);
+/* *** transform_orientations.c *** */
+void ED_transform_calc_orientation_from_type(const struct bContext *C, float r_mat[3][3]);
+short ED_transform_calc_orientation_from_type_ex(const struct bContext *C,
+ float r_mat[3][3],
+ /* extra args */
+ struct Scene *scene,
+ struct RegionView3D *rv3d,
+ struct Object *ob,
+ struct Object *obedit,
+ const short orientation_type,
+ int orientation_index_custom,
+ const int pivot_point);
+
/* transform gizmos */
void VIEW3D_GGT_xform_gizmo(struct wmGizmoGroupType *gzgt);
@@ -180,18 +193,6 @@ void ED_widgetgroup_gizmo2d_rotate_callbacks_set(struct wmGizmoGroupType *gzgt);
#define SNAP_INCREMENTAL_ANGLE DEG2RAD(5.0)
-void ED_transform_calc_orientation_from_type(const struct bContext *C, float r_mat[3][3]);
-void ED_transform_calc_orientation_from_type_ex(const struct bContext *C,
- float r_mat[3][3],
- /* extra args */
- struct Scene *scene,
- struct RegionView3D *rv3d,
- struct Object *ob,
- struct Object *obedit,
- const short orientation_type,
- int orientation_index_custom,
- const int pivot_point);
-
struct TransformBounds {
float center[3]; /* Center for transform widget. */
float min[3], max[3]; /* Boundbox of selection for transform widget. */
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index b998ac87819..8feb73436a6 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -77,11 +77,8 @@ struct SnapObjectParams {
};
typedef struct SnapObjectContext SnapObjectContext;
-SnapObjectContext *ED_transform_snap_object_context_create(struct Main *bmain,
- struct Scene *scene,
- int flag);
-SnapObjectContext *ED_transform_snap_object_context_create_view3d(struct Main *bmain,
- struct Scene *scene,
+SnapObjectContext *ED_transform_snap_object_context_create(struct Scene *scene, int flag);
+SnapObjectContext *ED_transform_snap_object_context_create_view3d(struct Scene *scene,
int flag,
/* extra args for view3d */
const struct ARegion *region,
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 8c565536c71..f656aaf9c07 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -50,20 +50,17 @@ void ED_operatortypes_uvedit(void);
void ED_keymap_uvedit(struct wmKeyConfig *keyconf);
bool ED_uvedit_minmax(const struct Scene *scene,
- struct Image *ima,
struct Object *obedit,
float min[2],
float max[2]);
void ED_uvedit_select_all(struct BMesh *bm);
bool ED_uvedit_minmax_multi(const struct Scene *scene,
- struct Image *ima,
struct Object **objects_edit,
uint objects_len,
float r_min[2],
float r_max[2]);
bool ED_uvedit_center_multi(const struct Scene *scene,
- Image *ima,
struct Object **objects_edit,
uint objects_len,
float r_cent[2],
@@ -95,11 +92,7 @@ void ED_object_assign_active_image(struct Main *bmain,
bool ED_uvedit_test(struct Object *obedit);
/* visibility and selection */
-bool uvedit_face_visible_nolocal_ex(const struct ToolSettings *ts, struct BMFace *efa);
-bool uvedit_face_visible_test_ex(const struct ToolSettings *ts,
- struct Object *obedit,
- struct Image *ima,
- struct BMFace *efa);
+bool uvedit_face_visible_test_ex(const struct ToolSettings *ts, struct BMFace *efa);
bool uvedit_face_select_test_ex(const struct ToolSettings *ts,
struct BMFace *efa,
const int cd_loop_uv_offset);
@@ -110,11 +103,7 @@ bool uvedit_uv_select_test_ex(const struct ToolSettings *ts,
struct BMLoop *l,
const int cd_loop_uv_offset);
-bool uvedit_face_visible_nolocal(const struct Scene *scene, struct BMFace *efa);
-bool uvedit_face_visible_test(const struct Scene *scene,
- struct Object *obedit,
- struct Image *ima,
- struct BMFace *efa);
+bool uvedit_face_visible_test(const struct Scene *scene, struct BMFace *efa);
bool uvedit_face_select_test(const struct Scene *scene,
struct BMFace *efa,
const int cd_loop_uv_offset);
@@ -175,12 +164,10 @@ void uvedit_uv_select_disable(struct BMEditMesh *em,
bool ED_uvedit_nearest_uv(const struct Scene *scene,
struct Object *obedit,
- struct Image *ima,
const float co[2],
float *dist_sq,
float r_uv[2]);
bool ED_uvedit_nearest_uv_multi(const struct Scene *scene,
- struct Image *ima,
struct Object **objects,
const uint objects_len,
const float co[2],
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 668ca3c6437..beca517f0a6 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -129,6 +129,9 @@ enum eV3DCursorOrient {
void ED_view3d_background_color_get(const struct Scene *scene,
const struct View3D *v3d,
float r_color[3]);
+bool ED_view3d_has_workbench_in_texture_color(const struct Scene *scene,
+ const struct Object *ob,
+ const struct View3D *v3d);
void ED_view3d_cursor3d_position(struct bContext *C,
const int mval[2],
const bool use_depth,
@@ -246,6 +249,7 @@ void nurbs_foreachScreenVert(struct ViewContext *vc,
struct BPoint *bp,
struct BezTriple *bezt,
int beztindex,
+ bool handle_visible,
const float screen_co[2]),
void *userData,
const eV3DProjTest clip_flag);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index cb4325d7851..09cde4df8a8 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1938,7 +1938,7 @@ uiLayout *uiLayoutRadial(uiLayout *layout);
/* templates */
void uiTemplateHeader(uiLayout *layout, struct bContext *C);
void uiTemplateID(uiLayout *layout,
- struct bContext *C,
+ const struct bContext *C,
struct PointerRNA *ptr,
const char *propname,
const char *newop,
@@ -2113,7 +2113,7 @@ void uiTemplateComponentMenu(uiLayout *layout,
const char *name);
void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
void uiTemplateCacheFile(uiLayout *layout,
- struct bContext *C,
+ const struct bContext *C,
struct PointerRNA *ptr,
const char *propname);
@@ -2146,7 +2146,7 @@ void uiTemplateNodeView(uiLayout *layout,
struct bNodeSocket *input);
void uiTemplateTextureUser(uiLayout *layout, struct bContext *C);
void uiTemplateTextureShow(uiLayout *layout,
- struct bContext *C,
+ const struct bContext *C,
struct PointerRNA *ptr,
struct PropertyRNA *prop);
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index c2c27af9770..e4fb0631f06 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -68,9 +68,9 @@ set(SRC
interface_region_tooltip.c
interface_regions.c
interface_style.c
- interface_templates.c
interface_template_search_menu.c
interface_template_search_operator.c
+ interface_templates.c
interface_undo.c
interface_utils.c
interface_widgets.c
diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c
index 6529bf8fc5d..32cae609395 100644
--- a/source/blender/editors/interface/interface_align.c
+++ b/source/blender/editors/interface/interface_align.c
@@ -124,7 +124,11 @@ bool ui_but_can_align(const uiBut *but)
int ui_but_align_opposite_to_area_align_get(const ARegion *region)
{
- switch (RGN_ALIGN_ENUM_FROM_MASK(region->alignment)) {
+ const ARegion *align_region = (region->alignment & RGN_SPLIT_PREV && region->prev) ?
+ region->prev :
+ region;
+
+ switch (RGN_ALIGN_ENUM_FROM_MASK(align_region->alignment)) {
case RGN_ALIGN_TOP:
return UI_BUT_ALIGN_DOWN;
case RGN_ALIGN_BOTTOM:
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 8c9768f523d..5bf2147aff5 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -61,7 +61,7 @@ static FCurve *ui_but_get_fcurve(
* but works well enough in typical cases */
int rnaindex = (but->rnaindex == -1) ? 0 : but->rnaindex;
- return rna_get_fcurve_context_ui(
+ return BKE_fcurve_find_by_rna_context_ui(
but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, adt, action, r_driven, r_special);
}
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index ace367fd513..c917ffb3f3e 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -138,11 +138,26 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
{
/* we could use some clever */
Main *bmain = CTX_data_main(C);
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+ wmWindowManager *wm = CTX_wm_manager(C);
const char *display_device = CTX_data_scene(C)->display_settings.display_device;
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+ if (area == NULL) {
+ int mval[2] = {mx, my};
+ if (WM_window_find_under_cursor(wm, NULL, win, mval, &win, mval)) {
+ mx = mval[0];
+ my = mval[1];
+ screen = WM_window_get_active_screen(win);
+ area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+ }
+ else {
+ win = NULL;
+ }
+ }
+
if (area) {
if (area->spacetype == SPACE_IMAGE) {
ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my);
@@ -179,12 +194,15 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
}
}
- /* fallback to simple opengl picker */
- glReadBuffer(GL_FRONT);
- glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col);
- glReadBuffer(GL_BACK);
-
- IMB_colormanagement_display_to_scene_linear_v3(r_col, display);
+ if (win) {
+ /* Fallback to simple opengl picker. */
+ int mval[2] = {mx, my};
+ WM_window_pixel_sample_read(wm, win, mval, r_col);
+ IMB_colormanagement_display_to_scene_linear_v3(r_col, display);
+ }
+ else {
+ zero_v3(r_col);
+ }
}
/* sets the sample color RGB, maintaining A */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 6db21ea93a5..eb99d044e17 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -5559,7 +5559,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
else if (but->type == UI_BTYPE_MENU) {
if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
- const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1;
+ const int direction = (event->type == WHEELDOWNMOUSE) ? 1 : -1;
data->value = ui_but_menu_step(but, direction);
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index c94a95890c0..deea3028354 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1603,8 +1603,8 @@ static void icon_draw_cache_texture_flush_ex(GLuint texture,
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR);
GPU_shader_bind(shader);
- int img_loc = GPU_shader_get_uniform_ensure(shader, "image");
- int data_loc = GPU_shader_get_uniform_ensure(shader, "calls_data[0]");
+ int img_loc = GPU_shader_get_uniform(shader, "image");
+ int data_loc = GPU_shader_get_uniform(shader, "calls_data");
glUniform1i(img_loc, 0);
glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)texture_draw_calls->drawcall_cache);
@@ -1750,9 +1750,9 @@ static void icon_draw_texture(float x,
GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
}
- glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0);
- glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), x1, y1, x2, y2);
- glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), x, y, x + w, y + h);
+ glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), x1, y1, x2, y2);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x, y, x + w, y + h);
GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index e0a202e0bd9..33f600f30a1 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -107,6 +107,7 @@ typedef struct uiHandlePanelData {
int startx, starty;
int startofsx, startofsy;
int startsizex, startsizey;
+ float start_cur_xmin, start_cur_ymin;
} uiHandlePanelData;
typedef struct PanelSort {
@@ -373,8 +374,8 @@ void UI_panels_free_instanced(bContext *C, ARegion *region)
* don't match in any way.
*
* \param data: The list of data to check against the instanced panels.
- * \param panel_type_func: Function to find the panel type idname for each item in the data list.
- * For a readabilty and generality, this lookup happens separately for each type of panel list.
+ * \param panel_idname_func: Function to find the panel type idname for each item in the data list.
+ * For a readability and generality, this lookup happens separately for each type of panel list.
*/
bool UI_panel_list_matches_data(ARegion *region,
ListBase *data,
@@ -997,7 +998,7 @@ void ui_draw_aligned_panel(uiStyle *style,
rcti box_rect = {rect->xmin,
rect->xmax,
(is_closed_x || is_closed_y) ? headrect.ymin : rect->ymin,
- headrect.ymax};
+ headrect.ymax + U.pixelsize};
ui_draw_box_opaque(&box_rect, UI_CNR_ALL);
/* Mimick the border between aligned box widgets for the bottom of the header. */
@@ -1143,8 +1144,8 @@ void ui_draw_aligned_panel(uiStyle *style,
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
GPU_blend(true);
- /* Draw panel backdrop if it wasn't aleady been drawn by the single opauque round box earlier.
- * Note: Subpanels blend with panels, so they can't be opaque. */
+ /* Draw panel backdrop if it wasn't already been drawn by the single opaque round box earlier.
+ * Note: Sub-panels blend with panels, so they can't be opaque. */
if (show_background && !(draw_box_style && !is_subpanel)) {
/* Draw the bottom subpanels . */
if (draw_box_style) {
@@ -1448,7 +1449,7 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co
ps->panel->ofsx = 0;
ps->panel->ofsy = -get_panel_size_y(ps->panel);
ps->panel->ofsx += ps->panel->runtime.region_ofsx;
- /* Extra margin if the panel happens to be a instanced panel. */
+ /* Extra margin if the panel is a box style panel. */
if (ps->panel->type && ps->panel->type->flag & PNL_DRAW_BOX) {
ps->panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN;
ps->panel->ofsy -= UI_PANEL_BOX_STYLE_MARGIN;
@@ -1731,21 +1732,22 @@ static void check_panel_overlap(ARegion *region, Panel *panel)
/************************ panel dragging ****************************/
+#define DRAG_REGION_PAD (PNL_HEADER * 0.5)
static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
{
uiHandlePanelData *data = panel->activedata;
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
- short align = panel_aligned(area, region), dx = 0, dy = 0;
+ short align = panel_aligned(area, region);
- /* first clip for window, no dragging outside */
- if (!BLI_rcti_isect_pt_v(&region->winrct, &event->x)) {
- return;
- }
+ /* Keep the drag position in the region with a small pad to keep the panel visible. */
+ int x = clamp_i(event->x, region->winrct.xmin, region->winrct.xmax + DRAG_REGION_PAD);
+ int y = clamp_i(event->y, region->winrct.ymin, region->winrct.ymax + DRAG_REGION_PAD);
- dx = (event->x - data->startx);
- dy = (event->y - data->starty);
+ float dx = (float)(x - data->startx);
+ float dy = (float)(y - data->starty);
+ /* Adjust for region zoom. */
dx *= (float)BLI_rctf_size_x(&region->v2d.cur) / (float)BLI_rcti_size_x(&region->winrct);
dy *= (float)BLI_rctf_size_y(&region->v2d.cur) / (float)BLI_rcti_size_y(&region->winrct);
@@ -1763,17 +1765,21 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
/* reset the panel snapping, to allow dragging away from snapped edges */
panel->snap = PNL_SNAP_NONE;
- panel->ofsx = data->startofsx + dx;
- panel->ofsy = data->startofsy + dy;
+ /* Add the movement of the view due to edge scrolling while dragging. */
+ dx += ((float)region->v2d.cur.xmin - data->start_cur_xmin);
+ dy += ((float)region->v2d.cur.ymin - data->start_cur_ymin);
+ panel->ofsx = data->startofsx + round_fl_to_int(dx);
+ panel->ofsy = data->startofsy + round_fl_to_int(dy);
check_panel_overlap(region, panel);
if (align) {
- uiAlignPanelStep(area, region, 0.2, true);
+ uiAlignPanelStep(area, region, 0.2f, true);
}
}
ED_region_tag_redraw(region);
}
+#undef DRAG_REGION_PAD
/******************* region level panel interaction *****************/
@@ -2967,6 +2973,12 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS
data->animtimer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, ANIMATION_INTERVAL);
}
+ /* Initiate edge panning during drags so we can move beyond the initial region view. */
+ if (state == PANEL_STATE_DRAG) {
+ wmOperatorType *ot = WM_operatortype_find("VIEW2D_OT_edge_pan", true);
+ ui_handle_afterfunc_add_operator(ot, WM_OP_INVOKE_DEFAULT, true);
+ }
+
data->state = state;
data->startx = win->eventstate->x;
data->starty = win->eventstate->y;
@@ -2974,6 +2986,8 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS
data->startofsy = panel->ofsy;
data->startsizex = panel->sizex;
data->startsizey = panel->sizey;
+ data->start_cur_xmin = region->v2d.cur.xmin;
+ data->start_cur_ymin = region->v2d.cur.ymin;
data->starttime = PIL_check_seconds_timer();
/* Remember drag drop state even when animating to the aligned position after dragging. */
diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c
index 34ac58c1dca..1f8af7b9e6e 100644
--- a/source/blender/editors/interface/interface_region_hud.c
+++ b/source/blender/editors/interface/interface_region_hud.c
@@ -177,11 +177,13 @@ static void hud_region_layout(const bContext *C, ARegion *region)
return;
}
+ ScrArea *area = CTX_wm_area(C);
int size_y = region->sizey;
ED_region_panels_layout(C, region);
- if (region->panels.first && (region->sizey != size_y)) {
+ if (region->panels.first &&
+ ((area->flag & AREA_FLAG_REGION_SIZE_UPDATE) || (region->sizey != size_y))) {
int winx_new = UI_DPI_FAC * (region->sizex + 0.5f);
int winy_new = UI_DPI_FAC * (region->sizey + 0.5f);
View2D *v2d = &region->v2d;
@@ -339,6 +341,7 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area)
}
else {
if (region->flag & RGN_FLAG_HIDDEN) {
+ /* Also forces recalculating HUD size in hud_region_layout(). */
area->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
}
region->flag &= ~RGN_FLAG_HIDDEN;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 46a0fd43a7f..0661dce1869 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -799,7 +799,7 @@ static uiBut *template_id_def_new_but(uiBlock *block,
return but;
}
-static void template_ID(bContext *C,
+static void template_ID(const bContext *C,
uiLayout *layout,
TemplateID *template_ui,
StructRNA *type,
@@ -1140,7 +1140,7 @@ ID *UI_context_active_but_get_tab_ID(bContext *C)
}
}
-static void template_ID_tabs(bContext *C,
+static void template_ID_tabs(const bContext *C,
uiLayout *layout,
TemplateID *template,
StructRNA *type,
@@ -1150,7 +1150,7 @@ static void template_ID_tabs(bContext *C,
{
const ARegion *region = CTX_wm_region(C);
const PointerRNA active_ptr = RNA_property_pointer_get(&template->ptr, template->prop);
- MenuType *mt = WM_menutype_find(menu, false);
+ MenuType *mt = menu ? WM_menutype_find(menu, false) : NULL;
const int but_align = ui_but_align_opposite_to_area_align_get(region);
const int but_height = UI_UNIT_Y * 1.1;
@@ -1214,12 +1214,14 @@ static void template_ID_tabs(bContext *C,
}
static void ui_template_id(uiLayout *layout,
- bContext *C,
+ const bContext *C,
PointerRNA *ptr,
const char *propname,
const char *newop,
const char *openop,
const char *unlinkop,
+ /* Only respected by tabs (use_tabs). */
+ const char *menu,
const char *text,
int flag,
int prv_rows,
@@ -1274,7 +1276,7 @@ static void ui_template_id(uiLayout *layout,
if (template_ui->idlb) {
if (use_tabs) {
layout = uiLayoutRow(layout, true);
- template_ID_tabs(C, layout, template_ui, type, flag, newop, unlinkop);
+ template_ID_tabs(C, layout, template_ui, type, flag, newop, menu);
}
else {
layout = uiLayoutRow(layout, true);
@@ -1296,7 +1298,7 @@ static void ui_template_id(uiLayout *layout,
}
void uiTemplateID(uiLayout *layout,
- bContext *C,
+ const bContext *C,
PointerRNA *ptr,
const char *propname,
const char *newop,
@@ -1313,6 +1315,7 @@ void uiTemplateID(uiLayout *layout,
newop,
openop,
unlinkop,
+ NULL,
text,
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE,
0,
@@ -1341,6 +1344,7 @@ void uiTemplateIDBrowse(uiLayout *layout,
newop,
openop,
unlinkop,
+ NULL,
text,
UI_ID_BROWSE | UI_ID_RENAME,
0,
@@ -1372,6 +1376,7 @@ void uiTemplateIDPreview(uiLayout *layout,
openop,
unlinkop,
NULL,
+ NULL,
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS,
rows,
cols,
@@ -1399,6 +1404,7 @@ void uiTemplateGpencilColorPreview(uiLayout *layout,
NULL,
NULL,
NULL,
+ NULL,
UI_ID_BROWSE | UI_ID_PREVIEWS | UI_ID_DELETE,
rows,
cols,
@@ -1417,7 +1423,7 @@ void uiTemplateIDTabs(uiLayout *layout,
PointerRNA *ptr,
const char *propname,
const char *newop,
- const char *unlinkop,
+ const char *menu,
int filter)
{
ui_template_id(layout,
@@ -1426,7 +1432,8 @@ void uiTemplateIDTabs(uiLayout *layout,
propname,
newop,
NULL,
- unlinkop,
+ NULL,
+ menu,
NULL,
UI_ID_BROWSE | UI_ID_RENAME,
0,
@@ -1824,7 +1831,15 @@ void uiTemplateModifiers(uiLayout *UNUSED(layout), bContext *C)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
- Object *ob = CTX_data_active_object(C);
+
+ Object *ob;
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ if (sbuts != NULL && (sbuts->pinid != NULL) && GS(sbuts->pinid->name) == ID_OB) {
+ ob = (Object *)sbuts->pinid;
+ }
+ else {
+ ob = CTX_data_active_object(C);
+ }
ListBase *modifiers = &ob->modifiers;
bool panels_match = UI_panel_list_matches_data(region, modifiers, modifier_panel_id);
@@ -2337,7 +2352,7 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C)
static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
{
- ED_object_constraint_set_active(ob_v, con_v);
+ ED_object_constraint_active_set(ob_v, con_v);
}
static void draw_constraint_header(uiLayout *layout, Object *ob, bConstraint *con)
@@ -7055,7 +7070,10 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
/** \name Cache File Template
* \{ */
-void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname)
+void uiTemplateCacheFile(uiLayout *layout,
+ const bContext *C,
+ PointerRNA *ptr,
+ const char *propname)
{
if (!ptr->data) {
return;
diff --git a/source/blender/editors/interface/view2d_draw.c b/source/blender/editors/interface/view2d_draw.c
index 36213f919a3..677043c1ccf 100644
--- a/source/blender/editors/interface/view2d_draw.c
+++ b/source/blender/editors/interface/view2d_draw.c
@@ -203,7 +203,7 @@ static void draw_parallel_lines(const ParallelLinesSet *lines,
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
immUniform2fv("viewportSize", &viewport[2]);
- /* -1.0f offset here is because the line is too fat due to the builtin antialiasing.
+ /* -1.0f offset here is because the line is too fat due to the builtin anti-aliasing.
* TODO make a variant or a uniform to toggle it off. */
immUniform1f("lineWidth", U.pixelsize - 1.0f);
}
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 5b1e5f746ef..98bbd7af943 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -100,6 +100,10 @@ typedef struct v2dViewPanData {
/** for MMB in scrollers (old feature in past, but now not that useful) */
short in_scroller;
+
+ /* View2D Edge Panning */
+ double edge_pan_last_time;
+ double edge_pan_start_time_x, edge_pan_start_time_y;
} v2dViewPanData;
/* initialize panning customdata */
@@ -357,6 +361,186 @@ static void VIEW2D_OT_pan(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name View Edge Pan Operator (modal)
+ *
+ * Scroll the region if the mouse is dragged to an edge. "Invisible" operator that always
+ * passes through.
+ * \{ */
+
+/** Distance from the edge of the region within which to start panning. */
+#define EDGE_PAN_REGION_PAD (U.widget_unit)
+/** Speed factor in pixels per second per pixel of distance from edge pan zone beginning. */
+#define EDGE_PAN_SPEED_PER_PIXEL (25.0f * (float)U.dpi_fac)
+/** Delay before drag panning in seconds. */
+#define EDGE_PAN_DELAY 1.0f
+
+/* set up modal operator and relevant settings */
+static int view_edge_pan_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ /* Set up customdata. */
+ if (!view_pan_init(C, op)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ v2dViewPanData *vpd = op->customdata;
+
+ vpd->edge_pan_start_time_x = 0.0;
+ vpd->edge_pan_start_time_y = 0.0;
+ vpd->edge_pan_last_time = PIL_check_seconds_timer();
+
+ WM_event_add_modal_handler(C, op);
+
+ return (OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH);
+}
+
+/**
+ * Reset the edge pan timers if the mouse isn't in the scroll zone and
+ * start the timers when the mouse enters a scroll zone.
+ */
+static void edge_pan_manage_delay_timers(v2dViewPanData *vpd,
+ int pan_dir_x,
+ int pan_dir_y,
+ const double current_time)
+{
+ if (pan_dir_x == 0) {
+ vpd->edge_pan_start_time_x = 0.0;
+ }
+ else if (vpd->edge_pan_start_time_x == 0.0) {
+ vpd->edge_pan_start_time_x = current_time;
+ }
+ if (pan_dir_y == 0) {
+ vpd->edge_pan_start_time_y = 0.0;
+ }
+ else if (vpd->edge_pan_start_time_y == 0.0) {
+ vpd->edge_pan_start_time_y = current_time;
+ }
+}
+
+/**
+ * Used to calculate a "fade in" factor for edge panning to make the interaction feel smooth
+ * and more purposeful.
+ *
+ * \note Assumes a domain_min of 0.0f.
+ */
+static float smootherstep(const float domain_max, float x)
+{
+ x = clamp_f(x / domain_max, 0.0, 1.0);
+ return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
+}
+
+static float edge_pan_speed(v2dViewPanData *vpd,
+ int event_loc,
+ bool x_dir,
+ const double current_time)
+{
+ ARegion *region = vpd->region;
+
+ /* Find the distance from the start of the drag zone. */
+ int min = (x_dir ? region->winrct.xmin : region->winrct.ymin) + EDGE_PAN_REGION_PAD;
+ int max = (x_dir ? region->winrct.xmax : region->winrct.ymax) - EDGE_PAN_REGION_PAD;
+ int distance = 0.0;
+ if (event_loc > max) {
+ distance = event_loc - max;
+ }
+ else if (event_loc < min) {
+ distance = min - event_loc;
+ }
+ else {
+ BLI_assert(!"Calculating speed outside of pan zones");
+ return 0.0f;
+ }
+
+ /* Apply a fade in to the speed based on a start time delay. */
+ double start_time = x_dir ? vpd->edge_pan_start_time_x : vpd->edge_pan_start_time_y;
+ float delay_factor = smootherstep(EDGE_PAN_DELAY, (float)(current_time - start_time));
+
+ return distance * EDGE_PAN_SPEED_PER_PIXEL * delay_factor;
+}
+
+static int view_edge_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ v2dViewPanData *vpd = op->customdata;
+ ARegion *region = vpd->region;
+
+ if (event->val == KM_RELEASE || event->type == EVT_ESCKEY) {
+ view_pan_exit(op);
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ }
+ /* Only mousemove events matter here, ignore others. */
+ if (event->type != MOUSEMOVE) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* This operator is supposed to run together with some drag action.
+ * On successful handling, always pass events on to other handlers. */
+ const int success_retval = OPERATOR_PASS_THROUGH;
+
+ /* Find whether the mouse is beyond X and Y edges. */
+ int pan_dir_x = 0;
+ int pan_dir_y = 0;
+ if (event->x > region->winrct.xmax - EDGE_PAN_REGION_PAD) {
+ pan_dir_x = 1;
+ }
+ else if (event->x < region->winrct.xmin + EDGE_PAN_REGION_PAD) {
+ pan_dir_x = -1;
+ }
+ if (event->y > region->winrct.ymax - EDGE_PAN_REGION_PAD) {
+ pan_dir_y = 1;
+ }
+ else if (event->y < region->winrct.ymin + EDGE_PAN_REGION_PAD) {
+ pan_dir_y = -1;
+ }
+
+ const double current_time = PIL_check_seconds_timer();
+ edge_pan_manage_delay_timers(vpd, pan_dir_x, pan_dir_y, current_time);
+
+ /* Calculate the delta since the last time the operator was called. */
+ float dtime = (float)(current_time - vpd->edge_pan_last_time);
+ float dx = 0.0f, dy = 0.0f;
+ if (pan_dir_x != 0) {
+ float speed = edge_pan_speed(vpd, event->x, true, current_time);
+ dx = dtime * speed * (float)pan_dir_x;
+ }
+ if (pan_dir_y != 0) {
+ float speed = edge_pan_speed(vpd, event->y, false, current_time);
+ dy = dtime * speed * (float)pan_dir_y;
+ }
+ vpd->edge_pan_last_time = current_time;
+
+ /* Pan, clamping inside the regions's total bounds. */
+ view_pan_apply_ex(C, vpd, dx, dy);
+
+ return success_retval;
+}
+
+static void view_edge_pan_cancel(bContext *UNUSED(C), wmOperator *op)
+{
+ view_pan_exit(op);
+}
+
+static void VIEW2D_OT_edge_pan(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "View Edge Pan";
+ ot->description = "Pan the view when the mouse is held at an edge";
+ ot->idname = "VIEW2D_OT_edge_pan";
+
+ /* api callbacks */
+ ot->invoke = view_edge_pan_invoke;
+ ot->modal = view_edge_pan_modal;
+ ot->cancel = view_edge_pan_cancel;
+
+ /* operator is modal */
+ ot->flag = OPTYPE_INTERNAL;
+}
+
+#undef EDGE_PAN_REGION_PAD
+#undef EDGE_PAN_SPEED_PER_PIXEL
+#undef EDGE_PAN_DELAY
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name View Pan Operator (single step)
* \{ */
@@ -2246,6 +2430,7 @@ static void VIEW2D_OT_reset(wmOperatorType *ot)
void ED_operatortypes_view2d(void)
{
WM_operatortype_append(VIEW2D_OT_pan);
+ WM_operatortype_append(VIEW2D_OT_edge_pan);
WM_operatortype_append(VIEW2D_OT_scroll_left);
WM_operatortype_append(VIEW2D_OT_scroll_right);
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index 551f7989d53..dc8ad858a9f 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -663,7 +663,7 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op)
/* Switch out of edit mode to avoid being stuck in it (T54326). */
Object *obedit = CTX_data_edit_object(C);
if (obedit) {
- ED_object_mode_toggle(C, OB_MODE_EDIT);
+ ED_object_mode_set(C, OB_MODE_OBJECT);
}
bool ok = ABC_import(C,
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index bea44ee89f8..3786ed2789c 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -752,7 +752,7 @@ void ED_mask_draw_region(
}
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
immDrawPixelsTex(
&state, 0.0f, 0.0f, width, height, GL_RED, GL_FLOAT, GL_NEAREST, buffer, 1.0f, 1.0f, NULL);
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 1484dcfa92d..3c426e5d2b1 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -59,6 +59,7 @@ static Object *make_prim_init(bContext *C,
const char *idname,
const float loc[3],
const float rot[3],
+ const float scale[3],
ushort local_view_bits,
MakePrimitiveData *r_creation_data)
{
@@ -76,6 +77,13 @@ static Object *make_prim_init(bContext *C,
ED_object_new_primitive_matrix(C, obedit, loc, rot, r_creation_data->mat);
+ if (scale && !equals_v3v3(scale, (const float[3]){1.0f, 1.0f, 1.0f})) {
+ float scale_half[3];
+ copy_v3_v3(scale_half, scale);
+ mul_v3_fl(scale_half, 0.5f);
+ rescale_m4(r_creation_data->mat, scale_half);
+ }
+
return obedit;
}
@@ -112,9 +120,16 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op)
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Plane"), loc, rot, local_view_bits, &creation_data);
+ ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(C,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Plane"),
+ loc,
+ rot,
+ NULL,
+ local_view_bits,
+ &creation_data);
+
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -164,15 +179,22 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op)
MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3];
+ float loc[3], rot[3], scale[3];
bool enter_editmode;
ushort local_view_bits;
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cube"), loc, rot, local_view_bits, &creation_data);
+ ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, scale, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(C,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cube"),
+ loc,
+ rot,
+ scale,
+ local_view_bits,
+ &creation_data);
+
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -237,9 +259,16 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
cap_tri = (cap_end == 2);
WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Circle"), loc, rot, local_view_bits, &creation_data);
+ ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(C,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Circle"),
+ loc,
+ rot,
+ NULL,
+ local_view_bits,
+ &creation_data);
+
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -294,7 +323,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3];
+ float loc[3], rot[3], scale[3];
bool enter_editmode;
ushort local_view_bits;
const int end_fill_type = RNA_enum_get(op->ptr, "end_fill_type");
@@ -303,11 +332,13 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
+ ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, scale, &enter_editmode, &local_view_bits, NULL);
obedit = make_prim_init(C,
CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cylinder"),
loc,
rot,
+ scale,
local_view_bits,
&creation_data);
em = BKE_editmesh_from_object(obedit);
@@ -368,7 +399,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3];
+ float loc[3], rot[3], scale[3];
bool enter_editmode;
ushort local_view_bits;
const int end_fill_type = RNA_enum_get(op->ptr, "end_fill_type");
@@ -377,9 +408,15 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cone"), loc, rot, local_view_bits, &creation_data);
+ ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, scale, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(C,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cone"),
+ loc,
+ rot,
+ scale,
+ local_view_bits,
+ &creation_data);
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -447,9 +484,15 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op)
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Grid"), loc, rot, local_view_bits, &creation_data);
+ ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(C,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Grid"),
+ loc,
+ rot,
+ NULL,
+ local_view_bits,
+ &creation_data);
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -514,10 +557,16 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, &enter_editmode, &local_view_bits, NULL);
+ ED_object_add_generic_get_opts(
+ C, op, 'Y', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Suzanne"), loc, rot, local_view_bits, &creation_data);
+ obedit = make_prim_init(C,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Suzanne"),
+ loc,
+ rot,
+ NULL,
+ local_view_bits,
+ &creation_data);
dia = RNA_float_get(op->ptr, "size") / 2.0f;
mul_mat3_m4_fl(creation_data.mat, dia);
@@ -567,15 +616,21 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3];
+ float loc[3], rot[3], scale[3];
bool enter_editmode;
ushort local_view_bits;
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
- obedit = make_prim_init(
- C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Sphere"), loc, rot, local_view_bits, &creation_data);
+ ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, scale, &enter_editmode, &local_view_bits, NULL);
+ obedit = make_prim_init(C,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Sphere"),
+ loc,
+ rot,
+ scale,
+ local_view_bits,
+ &creation_data);
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -629,17 +684,19 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3];
+ float loc[3], rot[3], scale[3];
bool enter_editmode;
ushort local_view_bits;
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
- ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL);
+ ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, scale, &enter_editmode, &local_view_bits, NULL);
obedit = make_prim_init(C,
CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Icosphere"),
loc,
rot,
+ scale,
local_view_bits,
&creation_data);
em = BKE_editmesh_from_object(obedit);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index f94cd778e13..5f5599b53df 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -2998,6 +2998,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MOUSEROTATE:
case WHEELUPMOUSE:
case WHEELDOWNMOUSE:
+ case NDOF_MOTION:
return OPERATOR_PASS_THROUGH;
case MOUSEMOVE: /* mouse moved somewhere to select another loop */
if (kcd->mode != MODE_PANNING) {
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 3861676c2cf..0f52911c603 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -515,6 +515,10 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op)
static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
+ if (event->type == NDOF_MOTION) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
RingSelOpData *lcd = op->customdata;
float cuts = lcd->cuts;
float smoothness = lcd->smoothness;
@@ -606,7 +610,8 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
handled = true;
break;
- case MOUSEMOVE: /* mouse moved somewhere to select another loop */
+ case MOUSEMOVE: {
+ /* mouse moved somewhere to select another loop */
/* This is normally disabled for all modal operators.
* This is an exception since mouse movement doesn't relate to numeric input.
@@ -615,14 +620,16 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
#if 0
if (!has_numinput)
#endif
- {
- lcd->vc.mval[0] = event->mval[0];
- lcd->vc.mval[1] = event->mval[1];
- loopcut_mouse_move(lcd, (int)lcd->cuts);
+ {
+ lcd->vc.mval[0] = event->mval[0];
+ lcd->vc.mval[1] = event->mval[1];
+ loopcut_mouse_move(lcd, (int)lcd->cuts);
- ED_region_tag_redraw(lcd->region);
- handled = true;
- } break;
+ ED_region_tag_redraw(lcd->region);
+ handled = true;
+ }
+ break;
+ }
}
/* Modal numinput inactive, try to handle numeric inputs last... */
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index eed2cbcce39..739bc5bdf7c 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -224,7 +224,7 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
if (RNA_boolean_get(op->ptr, "add_solidify")) {
ED_object_modifier_add(
op->reports, bmain, scene, new_ob, "mask_extract_solidify", eModifierType_Solidify);
- SolidifyModifierData *sfmd = (SolidifyModifierData *)BKE_modifiers_findny_name(
+ SolidifyModifierData *sfmd = (SolidifyModifierData *)BKE_modifiers_findby_name(
new_ob, "mask_extract_solidify");
if (sfmd) {
sfmd->offset = -0.05f;
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index a26003d78ed..b5346a9061a 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -1647,14 +1647,13 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
void EDBM_project_snap_verts(
bContext *C, Depsgraph *depsgraph, ARegion *region, Object *obedit, BMEditMesh *em)
{
- Main *bmain = CTX_data_main(C);
BMIter iter;
BMVert *eve;
ED_view3d_init_mats_rv3d(obedit, region->regiondata);
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, CTX_data_scene(C), 0, region, CTX_wm_view3d(C));
+ CTX_data_scene(C), 0, region, CTX_wm_view3d(C));
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 2ee98f39306..8289f52b0c8 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -350,6 +350,18 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
DEG2RADF(-360.0f),
DEG2RADF(360.0f));
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_float_vector_xyz(ot->srna,
+ "scale",
+ 3,
+ NULL,
+ -OBJECT_ADD_SIZE_MAXF,
+ OBJECT_ADD_SIZE_MAXF,
+ "Scale",
+ "Scale for the newly added object",
+ -1000.0f,
+ 1000.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
void ED_object_add_mesh_props(wmOperatorType *ot)
@@ -362,6 +374,7 @@ bool ED_object_add_generic_get_opts(bContext *C,
const char view_align_axis,
float loc[3],
float rot[3],
+ float scale[3],
bool *enter_editmode,
ushort *local_view_bits,
bool *is_view_aligned)
@@ -470,6 +483,26 @@ bool ED_object_add_generic_get_opts(bContext *C,
}
}
+ /* Scale! */
+ {
+ float _scale[3];
+ if (!scale) {
+ scale = _scale;
+ }
+
+ /* For now this is optional, we can make it always use. */
+ copy_v3_fl(scale, 1.0f);
+ if ((prop = RNA_struct_find_property(op->ptr, "scale"))) {
+ if (RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_get_array(op->ptr, prop, scale);
+ }
+ else {
+ copy_v3_fl(scale, 1.0f);
+ RNA_property_float_set_array(op->ptr, prop, scale);
+ }
+ }
+ }
+
return true;
}
@@ -535,7 +568,7 @@ static int object_add_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(
- C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
radius = RNA_float_get(op->ptr, "radius");
@@ -609,7 +642,7 @@ static int lightprobe_add_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(
- C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
type = RNA_enum_get(op->ptr, "type");
@@ -668,7 +701,7 @@ static int effector_add_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(
- C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
type = RNA_enum_get(op->ptr, "type");
@@ -746,7 +779,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op)
RNA_enum_set(op->ptr, "align", ALIGN_VIEW);
if (!ED_object_add_generic_get_opts(
- C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, local_view_bits);
@@ -807,7 +840,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(
- C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
if (obedit == NULL || obedit->type != OB_MBALL) {
@@ -872,7 +905,7 @@ static int object_add_text_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(
- C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
if (obedit && obedit->type == OB_FONT) {
@@ -924,7 +957,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(
- C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) {
@@ -987,7 +1020,7 @@ static int object_empty_add_exec(bContext *C, wmOperator *op)
float loc[3], rot[3];
WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, local_view_bits);
@@ -1047,7 +1080,8 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
ushort local_view_bits;
float rot[3];
- if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, &local_view_bits, NULL)) {
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', NULL, rot, NULL, NULL, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, local_view_bits);
@@ -1134,7 +1168,7 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
/* Note: We use 'Y' here (not 'Z'), as */
WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, &local_view_bits, NULL)) {
+ if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, NULL, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
/* add new object if not currently editing a GP object,
@@ -1264,7 +1298,7 @@ static int object_light_add_exec(bContext *C, wmOperator *op)
float loc[3], rot[3];
WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
ob = ED_object_add_type(C, OB_LAMP, get_light_defname(type), loc, rot, false, local_view_bits);
@@ -1349,7 +1383,7 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op)
collection = BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection"));
}
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
if (collection) {
@@ -1422,7 +1456,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
float loc[3], rot[3];
Scene *scene = CTX_data_scene(C);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits);
@@ -1479,7 +1513,7 @@ static int object_hair_add_exec(bContext *C, wmOperator *op)
ushort local_view_bits;
float loc[3], rot[3];
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
Object *object = ED_object_add_type(C, OB_HAIR, NULL, loc, rot, false, local_view_bits);
@@ -1516,7 +1550,7 @@ static int object_pointcloud_add_exec(bContext *C, wmOperator *op)
ushort local_view_bits;
float loc[3], rot[3];
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
}
Object *object = ED_object_add_type(C, OB_POINTCLOUD, NULL, loc, rot, false, local_view_bits);
@@ -2865,6 +2899,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ ED_outliner_select_sync_from_object_tag(C);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index fcf8a8dc2fe..19974655cbb 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -81,7 +81,7 @@
* \{ */
/* if object in posemode, active bone constraints, else object constraints */
-ListBase *get_active_constraints(Object *ob)
+ListBase *ED_object_constraint_list_from_context(Object *ob)
{
if (ob == NULL) {
return NULL;
@@ -104,7 +104,9 @@ ListBase *get_active_constraints(Object *ob)
/* Find the list that a given constraint belongs to,
* and/or also get the posechannel this is from (if applicable) */
-ListBase *get_constraint_lb(Object *ob, bConstraint *con, bPoseChannel **r_pchan)
+ListBase *ED_object_constraint_list_from_constraint(Object *ob,
+ bConstraint *con,
+ bPoseChannel **r_pchan)
{
if (r_pchan) {
*r_pchan = NULL;
@@ -143,9 +145,9 @@ ListBase *get_constraint_lb(Object *ob, bConstraint *con, bPoseChannel **r_pchan
}
/* single constraint */
-bConstraint *get_active_constraint(Object *ob)
+bConstraint *ED_object_constraint_active_get(Object *ob)
{
- return BKE_constraints_active_get(get_active_constraints(ob));
+ return BKE_constraints_active_get(ED_object_constraint_list_from_context(ob));
}
/** \} */
@@ -721,7 +723,7 @@ static int edit_constraint_invoke_properties(bContext *C, wmOperator *op)
con = ptr.data;
RNA_string_set(op->ptr, "constraint", con->name);
- list = get_constraint_lb(ob, con, NULL);
+ list = ED_object_constraint_list_from_constraint(ob, con, NULL);
if (&ob->constraints == list) {
RNA_enum_set(op->ptr, "owner", EDIT_CONSTRAINT_OWNER_OBJECT);
@@ -769,7 +771,7 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
printf("edit_constraint_property_get: defaulting to getting list in the standard way\n");
}
#endif
- list = get_active_constraints(ob);
+ list = ED_object_constraint_list_from_context(ob);
}
con = BKE_constraints_find_name(list, constraint_name);
@@ -1061,7 +1063,7 @@ static int followpath_path_animate_exec(bContext *C, wmOperator *op)
Curve *cu = (Curve *)data->tar->data;
if (ELEM(NULL, cu->adt, cu->adt->action) ||
- (list_find_fcurve(&cu->adt->action->curves, "eval_time", 0) == NULL)) {
+ (BKE_fcurve_find(&cu->adt->action->curves, "eval_time", 0) == NULL)) {
/* create F-Curve for path animation */
act = ED_id_action_ensure(bmain, &cu->id);
fcu = ED_action_fcurve_ensure(bmain, act, NULL, NULL, "eval_time", 0);
@@ -1305,9 +1307,9 @@ void CONSTRAINT_OT_objectsolver_clear_inverse(wmOperatorType *ot)
/** \name Constraint Management Utilities
* \{ */
-void ED_object_constraint_set_active(Object *ob, bConstraint *con)
+void ED_object_constraint_active_set(Object *ob, bConstraint *con)
{
- ListBase *lb = get_constraint_lb(ob, con, NULL);
+ ListBase *lb = ED_object_constraint_list_from_constraint(ob, con, NULL);
/* lets be nice and escape if its active already */
/* NOTE: this assumes that the stack doesn't have other active ones set... */
@@ -1409,7 +1411,7 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
Object *ob = (Object *)ptr.owner_id;
bConstraint *con = ptr.data;
- ListBase *lb = get_constraint_lb(ob, con, NULL);
+ ListBase *lb = ED_object_constraint_list_from_constraint(ob, con, NULL);
/* free the constraint */
if (BKE_constraint_remove_ex(lb, ob, con, true)) {
@@ -1459,7 +1461,7 @@ static int constraint_move_down_exec(bContext *C, wmOperator *op)
bConstraint *con = edit_constraint_property_get(op, ob, 0);
if (con && con->next) {
- ListBase *conlist = get_constraint_lb(ob, con, NULL);
+ ListBase *conlist = ED_object_constraint_list_from_constraint(ob, con, NULL);
bConstraint *nextCon = con->next;
/* insert the nominated constraint after the one that used to be after it */
@@ -1515,7 +1517,7 @@ static int constraint_move_up_exec(bContext *C, wmOperator *op)
bConstraint *con = edit_constraint_property_get(op, ob, 0);
if (con && con->prev) {
- ListBase *conlist = get_constraint_lb(ob, con, NULL);
+ ListBase *conlist = ED_object_constraint_list_from_constraint(ob, con, NULL);
bConstraint *prevCon = con->prev;
/* insert the nominated constraint before the one that used to be before it */
@@ -2128,7 +2130,8 @@ static int pose_constraint_add_exec(bContext *C, wmOperator *op)
with_targets = 1;
}
- return constraint_add_exec(C, op, ob, get_active_constraints(ob), type, with_targets);
+ return constraint_add_exec(
+ C, op, ob, ED_object_constraint_list_from_context(ob), type, with_targets);
}
/* ------------------ */
@@ -2329,8 +2332,12 @@ static int pose_ik_add_exec(bContext *C, wmOperator *op)
/* add the constraint - all necessary checks should have
* been done by the invoke() callback already... */
- return constraint_add_exec(
- C, op, ob, get_active_constraints(ob), CONSTRAINT_TYPE_KINEMATIC, with_targets);
+ return constraint_add_exec(C,
+ op,
+ ob,
+ ED_object_constraint_list_from_context(ob),
+ CONSTRAINT_TYPE_KINEMATIC,
+ with_targets);
}
void POSE_OT_ik_add(wmOperatorType *ot)
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 53a557c5871..d522dcabae3 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -1475,10 +1475,9 @@ static bool object_mode_set_poll(bContext *C)
static int object_mode_set_exec(bContext *C, wmOperator *op)
{
- bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode");
+ const bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode");
Object *ob = CTX_data_active_object(C);
eObjectMode mode = RNA_enum_get(op->ptr, "mode");
- eObjectMode restore_mode = ob->mode;
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
/* by default the operator assume is a mesh, but if gp object change mode */
@@ -1490,43 +1489,63 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
return OPERATOR_PASS_THROUGH;
}
+ /**
+ * Mode Switching Logic (internal details).
+ *
+ * Notes:
+ * - Code below avoids calling mode switching functions more than once,
+ * as this causes unnecessary calculations and undo steps to be added.
+ * - The previous mode (#Object.restore_mode) is object mode by default.
+ *
+ * Supported Cases:
+ * - Setting the mode (when the 'toggle' setting is off).
+ * - Toggle the mode:
+ * - Toggle between object mode and non-object mode property.
+ * - Toggle between the previous mode (#Object.restore_mode) and the mode property.
+ * - Toggle object mode.
+ * While this is similar to regular toggle,
+ * this operator depends on there being a previous mode set
+ * (this isn't bound to a key with the default key-map).
+ */
if (toggle == false) {
if (ob->mode != mode) {
- if (mode != OB_MODE_OBJECT) {
- /* Enter new mode. */
- ED_object_mode_toggle(C, mode);
- }
- else {
- ED_object_mode_compat_set(C, ob, mode, op->reports);
- }
+ ED_object_mode_set_ex(C, mode, true, op->reports);
}
}
else {
- /* Exit current mode if it's not the mode we're setting */
- if (mode != OB_MODE_OBJECT) {
- /* Enter new mode. */
- ED_object_mode_toggle(C, mode);
- }
-
- /* Special case for Object mode! */
- if ((mode == OB_MODE_OBJECT) && (restore_mode == OB_MODE_OBJECT) &&
- (ob->restore_mode != OB_MODE_OBJECT)) {
- ED_object_mode_toggle(C, ob->restore_mode);
- }
- else if (ob->mode == mode) {
- /* For toggling, store old mode so we know what to go back to */
- ob->restore_mode = restore_mode;
- }
- else if ((ob->restore_mode != OB_MODE_OBJECT) && (ob->restore_mode != mode)) {
- ED_object_mode_toggle(C, ob->restore_mode);
+ const eObjectMode mode_prev = ob->mode;
+ /* When toggling object mode, we always use the restore mode,
+ * otherwise there is nothing to do. */
+ if (mode == OB_MODE_OBJECT) {
+ if (ob->mode != OB_MODE_OBJECT) {
+ if (ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) {
+ /* Store old mode so we know what to go back to. */
+ ob->restore_mode = mode_prev;
+ }
+ }
+ else {
+ if (ob->restore_mode != OB_MODE_OBJECT) {
+ ED_object_mode_set_ex(C, ob->restore_mode, true, op->reports);
+ }
+ }
}
- }
-
- /* if type is OB_GPENCIL, set cursor mode */
- if (ob->type == OB_GPENCIL) {
- if (ob->data) {
- bGPdata *gpd = (bGPdata *)ob->data;
- ED_gpencil_setup_modes(C, gpd, ob->mode);
+ else {
+ /* Non-object modes, enter the 'mode' unless it's already set,
+ * in that case use restore mode. */
+ if (ob->mode != mode) {
+ if (ED_object_mode_set_ex(C, mode, true, op->reports)) {
+ /* Store old mode so we know what to go back to. */
+ ob->restore_mode = mode_prev;
+ }
+ }
+ else {
+ if (ob->restore_mode != OB_MODE_OBJECT) {
+ ED_object_mode_set_ex(C, ob->restore_mode, true, op->reports);
+ }
+ else {
+ ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports);
+ }
+ }
}
}
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index f06b6a4db2a..c518fd32c7f 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -167,41 +167,6 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, Report
return ok;
}
-void ED_object_mode_toggle(bContext *C, eObjectMode mode)
-{
- if (mode != OB_MODE_OBJECT) {
- const char *opstring = object_mode_op_string(mode);
-
- if (opstring) {
- wmOperatorType *ot = WM_operatortype_find(opstring, false);
- WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL);
- }
- }
-}
-
-/* Wrapper for operator */
-void ED_object_mode_set(bContext *C, eObjectMode mode)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- wm->op_undo_depth++;
- /* needed so we don't do undo pushes. */
- ED_object_mode_generic_enter(C, mode);
- wm->op_undo_depth--;
-}
-
-void ED_object_mode_exit(bContext *C, Depsgraph *depsgraph)
-{
- struct Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FOREACH_OBJECT_BEGIN (view_layer, ob) {
- if (ob->mode & OB_MODE_ALL_MODE_DATA) {
- ED_object_mode_generic_exit(bmain, depsgraph, scene, ob);
- }
- }
- FOREACH_OBJECT_END;
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -212,23 +177,50 @@ void ED_object_mode_exit(bContext *C, Depsgraph *depsgraph)
*
* \{ */
-bool ED_object_mode_generic_enter(struct bContext *C, eObjectMode object_mode)
+bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportList *reports)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
if (ob == NULL) {
- return (object_mode == OB_MODE_OBJECT);
+ return (mode == OB_MODE_OBJECT);
}
- if (ob->mode == object_mode) {
+
+ if ((ob->type == OB_GPENCIL) && (mode == OB_MODE_EDIT)) {
+ mode = OB_MODE_EDIT_GPENCIL;
+ }
+
+ if (ob->mode == mode) {
return true;
}
- wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_mode_set", false);
- PointerRNA ptr;
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_enum_set(&ptr, "mode", object_mode);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
- WM_operator_properties_free(&ptr);
- return (ob->mode == object_mode);
+
+ if (!ED_object_mode_compat_test(ob, mode)) {
+ return false;
+ }
+
+ const char *opstring = object_mode_op_string((mode == OB_MODE_OBJECT) ? ob->mode : mode);
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
+
+ if (!use_undo) {
+ wm->op_undo_depth++;
+ }
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL);
+ if (!use_undo) {
+ wm->op_undo_depth--;
+ }
+
+ if (ob->mode != mode) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
+ return false;
+ }
+
+ return true;
+}
+
+bool ED_object_mode_set(bContext *C, eObjectMode mode)
+{
+ /* Don't do undo push by default, since this may be called by lower level code. */
+ return ED_object_mode_set_ex(C, mode, true, NULL);
}
/**
@@ -282,6 +274,18 @@ static bool ed_object_mode_generic_exit_ex(struct Main *bmain,
ED_object_posemode_exit_ex(bmain, ob);
}
}
+ else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_texture_paint_mode_exit_ex(bmain, scene, ob);
+ }
+ else if (ob->mode & OB_MODE_PARTICLE_EDIT) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_particle_edit_mode_exit_ex(scene, ob);
+ }
else if (ob->type == OB_GPENCIL) {
/* Accounted for above. */
BLI_assert((ob->mode & OB_MODE_OBJECT) == 0);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 862bdcee8ce..0bd49f74db9 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -847,7 +847,7 @@ bool ED_object_modifier_apply(Main *bmain,
/* Get evaluated modifier, so object links pointer to evaluated data,
* but still use original object it is applied to the original mesh. */
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- ModifierData *md_eval = (ob_eval) ? BKE_modifiers_findny_name(ob_eval, md->name) : md;
+ ModifierData *md_eval = (ob_eval) ? BKE_modifiers_findby_name(ob_eval, md->name) : md;
/* allow apply of a not-realtime modifier, by first re-enabling realtime. */
prev_mode = md_eval->mode;
@@ -1062,7 +1062,7 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
ModifierData *md;
RNA_string_get(op->ptr, "modifier", modifier_name);
- md = BKE_modifiers_findny_name(ob, modifier_name);
+ md = BKE_modifiers_findby_name(ob, modifier_name);
if (md && type != 0 && md->type != type) {
md = NULL;
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index bfceaef4644..0e8545e07ba 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2072,7 +2072,7 @@ void ED_object_single_users(Main *bmain,
/* Duplicating obdata and other IDs may require another update of the collections and objects
* pointers, especially regarding drivers and custom props, see T66641.
- * Note that this whole scene duplication code and 'make single user' functions have te be
+ * Note that this whole scene duplication code and 'make single user' functions have to be
* rewritten at some point to make use of proper modern ID management code,
* but that is no small task.
* For now we are doomed to that kind of band-aid to try to cover most of remapping cases. */
@@ -2516,7 +2516,8 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
Collection *new_collection = (Collection *)collection->id.newid;
- BKE_collection_child_add(bmain, scene->master_collection, new_collection);
+ BKE_collection_add_from_object(bmain, scene, obcollection, new_collection);
+
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (new_collection, new_ob) {
if (new_ob != NULL && new_ob->id.override_library != NULL) {
if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) {
@@ -2524,14 +2525,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
base = BKE_view_layer_base_find(view_layer, new_ob);
DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS);
}
- /* parent to 'collection' empty */
- /* Disabled for now, according to some artist this is probably not really useful anyway.
- * And it breaks things like objects parented to bones
- * (most likely due to missing proper setting of inverse parent matrix?)... */
- /* Note: we might even actually want to get rid of that instantiating empty... */
- if (0 && new_ob->parent == NULL) {
- new_ob->parent = obcollection;
- }
+
if (new_ob == (Object *)obact->id.newid) {
/* TODO: is setting active needed? */
BKE_view_layer_base_select_and_set_active(view_layer, base);
@@ -2546,9 +2540,9 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- /* obcollection is no more duplicollection-ing,
- * it merely parents whole collection of overriding instantiated objects. */
- obcollection->instance_collection = NULL;
+ /* Remove the instance empty from this scene, the items now have an overridden collection
+ * instead. */
+ ED_object_base_free_and_unlink(bmain, scene, obcollection);
/* Also, we'd likely want to lock by default things like
* transformations of implicitly overridden objects? */
diff --git a/source/blender/editors/object/object_volume.c b/source/blender/editors/object/object_volume.c
index 3c1f7da2bd6..4cdbbea492b 100644
--- a/source/blender/editors/object/object_volume.c
+++ b/source/blender/editors/object/object_volume.c
@@ -59,7 +59,7 @@ static Object *object_volume_add(bContext *C, wmOperator *op, const char *name)
ushort local_view_bits;
float loc[3], rot[3];
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) {
return false;
}
return ED_object_add_type(C, OB_VOLUME, name, loc, rot, false, local_view_bits);
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index ca2dec75160..ef5ed806c1e 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -3230,17 +3230,17 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)
}
}
-static void toggle_particle_cursor(bContext *C, int enable)
+static void toggle_particle_cursor(Scene *scene, bool enable)
{
- ParticleEditSettings *pset = PE_settings(CTX_data_scene(C));
+ ParticleEditSettings *pset = PE_settings(scene);
if (pset->paintcursor && !enable) {
- WM_paint_cursor_end(CTX_wm_manager(C), pset->paintcursor);
+ WM_paint_cursor_end(pset->paintcursor);
pset->paintcursor = NULL;
}
else if (enable) {
pset->paintcursor = WM_paint_cursor_activate(
- CTX_wm_manager(C), SPACE_VIEW3D, RGN_TYPE_WINDOW, PE_poll_view3d, brush_drawcursor, NULL);
+ SPACE_VIEW3D, RGN_TYPE_WINDOW, PE_poll_view3d, brush_drawcursor, NULL);
}
}
@@ -5127,7 +5127,7 @@ void PE_create_particle_edit(
int totpoint;
if (psmd != NULL) {
- psmd_eval = (ParticleSystemModifierData *)BKE_modifiers_findny_name(ob_eval,
+ psmd_eval = (ParticleSystemModifierData *)BKE_modifiers_findby_name(ob_eval,
psmd->modifier.name);
}
@@ -5268,10 +5268,60 @@ static void free_all_psys_edit(Object *object)
}
}
+void ED_object_particle_edit_mode_enter_ex(Depsgraph *depsgraph, Scene *scene, Object *ob)
+{
+ PTCacheEdit *edit;
+
+ ob->mode |= OB_MODE_PARTICLE_EDIT;
+
+ edit = PE_create_current(depsgraph, scene, ob);
+
+ /* Mesh may have changed since last entering editmode.
+ * note, this may have run before if the edit data was just created,
+ * so could avoid this and speed up a little. */
+ if (edit && edit->psys) {
+ /* Make sure pointer to the evaluated modifier data is up to date,
+ * with possible changes applied when object was outside of the
+ * edit mode. */
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
+ edit->psmd_eval = (ParticleSystemModifierData *)BKE_modifiers_findby_name(
+ object_eval, edit->psmd->modifier.name);
+ recalc_emitter_field(depsgraph, ob, edit->psys);
+ }
+
+ toggle_particle_cursor(scene, true);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_PARTICLE, NULL);
+}
+
+void ED_object_particle_edit_mode_enter(bContext *C)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ED_object_particle_edit_mode_enter_ex(depsgraph, scene, ob);
+}
+
+void ED_object_particle_edit_mode_exit_ex(Scene *scene, Object *ob)
+{
+ ob->mode &= ~OB_MODE_PARTICLE_EDIT;
+ toggle_particle_cursor(scene, false);
+ free_all_psys_edit(ob);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+}
+
+void ED_object_particle_edit_mode_exit(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ED_object_particle_edit_mode_exit_ex(scene, ob);
+}
+
static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
{
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
const int mode_flag = OB_MODE_PARTICLE_EDIT;
@@ -5284,37 +5334,13 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
}
if (!is_mode_set) {
- PTCacheEdit *edit;
-
- ob->mode |= mode_flag;
-
- edit = PE_create_current(depsgraph, scene, ob);
-
- /* Mesh may have changed since last entering editmode.
- * note, this may have run before if the edit data was just created,
- * so could avoid this and speed up a little. */
- if (edit && edit->psys) {
- /* Make sure pointer to the evaluated modifier data is up to date,
- * with possible changes applied when object was outside of the
- * edit mode. */
- Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
- edit->psmd_eval = (ParticleSystemModifierData *)BKE_modifiers_findny_name(
- object_eval, edit->psmd->modifier.name);
- recalc_emitter_field(depsgraph, ob, edit->psys);
- }
-
- toggle_particle_cursor(C, 1);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_PARTICLE, NULL);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ ED_object_particle_edit_mode_enter_ex(depsgraph, scene, ob);
}
else {
- ob->mode &= ~mode_flag;
- toggle_particle_cursor(C, 0);
- free_all_psys_edit(ob);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+ ED_object_particle_edit_mode_exit_ex(scene, ob);
}
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
-
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
WM_toolsystem_update_from_context_view3d(C);
diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c
index 5b363bdca78..205c04f54a9 100644
--- a/source/blender/editors/physics/particle_edit_undo.c
+++ b/source/blender/editors/physics/particle_edit_undo.c
@@ -253,7 +253,7 @@ static void particle_undosys_step_decode(struct bContext *C,
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
/* TODO(campbell): undo_system: use low-level API to set mode. */
- ED_object_mode_set(C, OB_MODE_PARTICLE_EDIT);
+ ED_object_mode_set_ex(C, OB_MODE_PARTICLE_EDIT, false, NULL);
BLI_assert(particle_undosys_poll(C));
ParticleUndoStep *us = (ParticleUndoStep *)us_p;
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index ceaac201da3..8524870c15e 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -52,6 +52,7 @@
#include "DEG_depsgraph.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "PIL_time.h"
@@ -154,7 +155,7 @@ static bool fluid_initjob(
{
FluidModifierData *mmd = NULL;
FluidDomainSettings *mds;
- Object *ob = CTX_data_active_object(C);
+ Object *ob = ED_object_active_context(C);
mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid);
if (!mmd) {
@@ -170,7 +171,7 @@ static bool fluid_initjob(
job->bmain = CTX_data_main(C);
job->scene = CTX_data_scene(C);
job->depsgraph = CTX_data_depsgraph_pointer(C);
- job->ob = CTX_data_active_object(C);
+ job->ob = ob;
job->mmd = mmd;
job->type = op->type->idname;
job->name = op->type->name;
@@ -616,7 +617,7 @@ static int fluid_free_exec(struct bContext *C, struct wmOperator *op)
{
FluidModifierData *mmd = NULL;
FluidDomainSettings *mds;
- Object *ob = CTX_data_active_object(C);
+ Object *ob = ED_object_active_context(C);
Scene *scene = CTX_data_scene(C);
/*
@@ -679,7 +680,7 @@ static int fluid_pause_exec(struct bContext *C, struct wmOperator *op)
{
FluidModifierData *mmd = NULL;
FluidDomainSettings *mds;
- Object *ob = CTX_data_active_object(C);
+ Object *ob = ED_object_active_context(C);
/*
* Get modifier data
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 46827940b57..1db7bf5a766 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -437,7 +437,7 @@ static void make_renderinfo_string(const RenderStats *rs,
}
}
else {
- if (rs->totvert || rs->totface || rs->tothalo || rs->totstrand || rs->totlamp) {
+ if (rs->totvert || rs->totface || rs->totlamp) {
spos += sprintf(spos, "| ");
}
@@ -447,12 +447,6 @@ static void make_renderinfo_string(const RenderStats *rs,
if (rs->totface) {
spos += sprintf(spos, TIP_("Fa:%d "), rs->totface);
}
- if (rs->tothalo) {
- spos += sprintf(spos, TIP_("Ha:%d "), rs->tothalo);
- }
- if (rs->totstrand) {
- spos += sprintf(spos, TIP_("St:%d "), rs->totstrand);
- }
if (rs->totlamp) {
spos += sprintf(spos, TIP_("Li:%d "), rs->totlamp);
}
@@ -463,18 +457,6 @@ static void make_renderinfo_string(const RenderStats *rs,
else {
spos += sprintf(spos, TIP_("| Mem:%.2fM, Peak: %.2fM "), rs->mem_used, rs->mem_peak);
}
-
- if (rs->curfield) {
- spos += sprintf(spos, TIP_("Field %d "), rs->curfield);
- }
- if (rs->curblur) {
- spos += sprintf(spos, TIP_("Blur %d "), rs->curblur);
- }
- }
-
- /* full sample */
- if (rs->curfsa) {
- spos += sprintf(spos, TIP_("| Full Sample %d "), rs->curfsa);
}
/* extra info */
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index ddb345ab65e..a9380debbdc 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -83,7 +83,7 @@ static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state)
/* To be used before calling immDrawPixelsTex
* Default shader is GPU_SHADER_2D_IMAGE_COLOR
* You can still set uniforms with :
- * GPU_shader_uniform_int(shader, GPU_shader_get_uniform_ensure(shader, "name"), 0);
+ * GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0);
* */
IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
{
@@ -191,7 +191,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
/* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since
* it does not need color.
*/
- if (state->shader != NULL && GPU_shader_get_uniform_ensure(state->shader, "color") != -1) {
+ if (state->shader != NULL && GPU_shader_get_uniform(state->shader, "color") != -1) {
immUniformColor4fv((color) ? color : white);
}
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index b383930ddda..3202dc68f37 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -118,8 +118,8 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
ScrArea *area = CTX_wm_area(C);
Scene *scene = WM_window_get_active_scene(win);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
- Object *obact = (view_layer && view_layer->basact) ? view_layer->basact->object : NULL;
- Object *obedit = view_layer ? OBEDIT_FROM_VIEW_LAYER(view_layer) : NULL;
+ Object *obact = view_layer->basact ? view_layer->basact->object : NULL;
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
if (CTX_data_dir(member)) {
CTX_data_dir_set(result, screen_context_dir);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 00afbf452dd..6f004238522 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -305,30 +305,28 @@ int area_getorientation(ScrArea *area, ScrArea *sb)
ScrVert *sbTR = sb->v3;
ScrVert *sbBR = sb->v4;
- int tolerance = U.pixelsize * 4;
-
if (saBL->vec.x == sbBR->vec.x && saTL->vec.x == sbTR->vec.x) { /* area to right of sb = W */
- if ((abs(saBL->vec.y - sbBR->vec.y) <= tolerance) &&
- (abs(saTL->vec.y - sbTR->vec.y) <= tolerance)) {
+ if ((abs(saBL->vec.y - sbBR->vec.y) <= AREAJOINTOLERANCE) &&
+ (abs(saTL->vec.y - sbTR->vec.y) <= AREAJOINTOLERANCE)) {
return 0;
}
}
else if (saTL->vec.y == sbBL->vec.y &&
saTR->vec.y == sbBR->vec.y) { /* area to bottom of sb = N */
- if ((abs(saTL->vec.x - sbBL->vec.x) <= tolerance) &&
- (abs(saTR->vec.x - sbBR->vec.x) <= tolerance)) {
+ if ((abs(saTL->vec.x - sbBL->vec.x) <= AREAJOINTOLERANCE) &&
+ (abs(saTR->vec.x - sbBR->vec.x) <= AREAJOINTOLERANCE)) {
return 1;
}
}
else if (saTR->vec.x == sbTL->vec.x && saBR->vec.x == sbBL->vec.x) { /* area to left of sb = E */
- if ((abs(saTR->vec.y - sbTL->vec.y) <= tolerance) &&
- (abs(saBR->vec.y - sbBL->vec.y) <= tolerance)) {
+ if ((abs(saTR->vec.y - sbTL->vec.y) <= AREAJOINTOLERANCE) &&
+ (abs(saBR->vec.y - sbBL->vec.y) <= AREAJOINTOLERANCE)) {
return 2;
}
}
else if (saBL->vec.y == sbTL->vec.y && saBR->vec.y == sbTR->vec.y) { /* area on top of sb = S*/
- if ((abs(saBL->vec.x - sbTL->vec.x) <= tolerance) &&
- (abs(saBR->vec.x - sbTR->vec.x) <= tolerance)) {
+ if ((abs(saBL->vec.x - sbTL->vec.x) <= AREAJOINTOLERANCE) &&
+ (abs(saBR->vec.x - sbTR->vec.x) <= AREAJOINTOLERANCE)) {
return 3;
}
}
@@ -336,6 +334,69 @@ int area_getorientation(ScrArea *area, ScrArea *sb)
return -1;
}
+/* Screen verts with horizontal position equal to from_x are moved to to_x. */
+static void screen_verts_halign(const wmWindow *win,
+ const bScreen *screen,
+ const short from_x,
+ const short to_x)
+{
+ ED_screen_verts_iter(win, screen, v1)
+ {
+ if (v1->vec.x == from_x) {
+ v1->vec.x = to_x;
+ }
+ }
+}
+
+/* Screen verts with vertical position equal to from_y are moved to to_y. */
+static void screen_verts_valign(const wmWindow *win,
+ const bScreen *screen,
+ const short from_y,
+ const short to_y)
+{
+ ED_screen_verts_iter(win, screen, v1)
+ {
+ if (v1->vec.y == from_y) {
+ v1->vec.y = to_y;
+ }
+ }
+}
+
+/* Adjust all screen edges to allow joining two areas. 'dir' value is like area_getorientation().
+ */
+static void screen_areas_align(
+ bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2, const int dir)
+{
+ wmWindow *win = CTX_wm_window(C);
+
+ if (dir == 0 || dir == 2) {
+ /* horizontal join, use average for new top and bottom. */
+ int top = (sa1->v2->vec.y + sa2->v2->vec.y) / 2;
+ int bottom = (sa1->v4->vec.y + sa2->v4->vec.y) / 2;
+
+ /* Move edges exactly matching source top and bottom. */
+ screen_verts_valign(win, screen, sa1->v2->vec.y, top);
+ screen_verts_valign(win, screen, sa1->v4->vec.y, bottom);
+
+ /* Move edges exactly matching target top and bottom. */
+ screen_verts_valign(win, screen, sa2->v2->vec.y, top);
+ screen_verts_valign(win, screen, sa2->v4->vec.y, bottom);
+ }
+ else {
+ /* Vertical join, use averages for new left and right. */
+ int left = (sa1->v1->vec.x + sa2->v1->vec.x) / 2;
+ int right = (sa1->v3->vec.x + sa2->v3->vec.x) / 2;
+
+ /* Move edges exactly matching source left and right. */
+ screen_verts_halign(win, screen, sa1->v1->vec.x, left);
+ screen_verts_halign(win, screen, sa1->v3->vec.x, right);
+
+ /* Move edges exactly matching target left and right */
+ screen_verts_halign(win, screen, sa2->v1->vec.x, left);
+ screen_verts_halign(win, screen, sa2->v3->vec.x, right);
+ }
+}
+
/* Helper function to join 2 areas, it has a return value, 0=failed 1=success
* used by the split, join operators
*/
@@ -348,21 +409,7 @@ int screen_area_join(bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2)
}
/* Align areas if they are not. Do sanity checking before getting here. */
-
- if (dir == 0 || dir == 2) {
- /* horizontal join, so vertically align source vert to target */
- sa2->v1->vec.y = sa1->v1->vec.y; /* vertical align sa1 BL */
- sa2->v2->vec.y = sa1->v2->vec.y; /* vertical align sa1 TL */
- sa2->v3->vec.y = sa1->v3->vec.y; /* vertical align sa1 TR */
- sa2->v4->vec.y = sa1->v4->vec.y; /* vertical align sa1 BR */
- }
- else {
- /* vertical join, so horizontally align source verts to target */
- sa2->v1->vec.x = sa1->v1->vec.x; /* vertical align sa1 BL */
- sa2->v2->vec.x = sa1->v2->vec.x; /* vertical align sa1 TL */
- sa2->v3->vec.x = sa1->v3->vec.x; /* vertical align sa1 TR */
- sa2->v4->vec.x = sa1->v4->vec.x; /* vertical align sa1 BR */
- }
+ screen_areas_align(C, screen, sa1, sa2, dir);
if (dir == 0) { /* sa1 to right of sa2 = W */
sa1->v1 = sa2->v1; /* BL */
@@ -690,8 +737,10 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2])
ARegion *region_prev = screen->active_region;
ED_screen_areas_iter (win, screen, area_iter) {
- if (xy[0] > area_iter->totrct.xmin && xy[0] < area_iter->totrct.xmax) {
- if (xy[1] > area_iter->totrct.ymin && xy[1] < area_iter->totrct.ymax) {
+ if (xy[0] > (area_iter->totrct.xmin + BORDERPADDING) &&
+ xy[0] < (area_iter->totrct.xmax - BORDERPADDING)) {
+ if (xy[1] > (area_iter->totrct.ymin + BORDERPADDING) &&
+ xy[1] < (area_iter->totrct.ymax - BORDERPADDING)) {
if (ED_area_azones_update(area_iter, xy) == NULL) {
area = area_iter;
break;
diff --git a/source/blender/editors/screen/screen_geometry.c b/source/blender/editors/screen/screen_geometry.c
index 4069795657e..47580c2f4b3 100644
--- a/source/blender/editors/screen/screen_geometry.c
+++ b/source/blender/editors/screen/screen_geometry.c
@@ -92,7 +92,7 @@ ScrEdge *screen_geom_area_map_find_active_scredge(const ScrAreaMap *area_map,
const int mx,
const int my)
{
- int safety = U.widget_unit / 10;
+ int safety = BORDERPADDING;
CLAMP_MIN(safety, 2);
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index 3dfc147bc73..2d42313d528 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -35,6 +35,11 @@ struct bContextDataResult;
#define AZONEFADEIN (5.0f * U.widget_unit) /* when azone is totally visible */
#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the azone */
+#define AREAJOINTOLERANCE (1.0f * U.widget_unit) /* Edges must be close to allow joining. */
+
+/* Expanded interaction influence of area borders. */
+#define BORDERPADDING (U.dpi_fac + U.pixelsize)
+
/* area.c */
void ED_area_data_copy(ScrArea *area_dst, ScrArea *area_src, const bool do_free);
void ED_area_data_swap(ScrArea *sa1, ScrArea *sa2);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 4d690ddce72..b2243f2ccb9 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -4866,8 +4866,11 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot)
/** \name Show User Preferences Operator
* \{ */
-static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int userpref_show_exec(bContext *C, wmOperator *op)
{
+ wmWindow *win_cur = CTX_wm_window(C);
+ /* Use eventstate, not event from _invoke, so this can be called through exec(). */
+ const wmEvent *event = win_cur->eventstate;
int sizex = (500 + UI_NAVIGATION_REGION_WIDTH) * UI_DPI_FAC;
int sizey = 520 * UI_DPI_FAC;
@@ -4904,7 +4907,7 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot)
ot->idname = "SCREEN_OT_userpref_show";
/* api callbacks */
- ot->invoke = userpref_show_invoke;
+ ot->exec = userpref_show_exec;
ot->poll = ED_operator_screenactive;
}
@@ -4914,8 +4917,11 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot)
/** \name Show Drivers Editor Operator
* \{ */
-static int drivers_editor_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int drivers_editor_show_exec(bContext *C, wmOperator *op)
{
+ wmWindow *win_cur = CTX_wm_window(C);
+ /* Use eventstate, not event from _invoke, so this can be called through exec(). */
+ const wmEvent *event = win_cur->eventstate;
PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
int index = -1;
@@ -4946,7 +4952,7 @@ static int drivers_editor_show_invoke(bContext *C, wmOperator *op, const wmEvent
FCurve *fcu;
bool driven, special;
- fcu = rna_get_fcurve_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
+ fcu = BKE_fcurve_find_by_rna_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
if (fcu) {
/* Isolate this F-Curve... */
bAnimContext ac;
@@ -4979,7 +4985,7 @@ static void SCREEN_OT_drivers_editor_show(struct wmOperatorType *ot)
ot->idname = "SCREEN_OT_drivers_editor_show";
/* api callbacks */
- ot->invoke = drivers_editor_show_invoke;
+ ot->exec = drivers_editor_show_exec;
ot->poll = ED_operator_screenactive;
}
@@ -4989,8 +4995,11 @@ static void SCREEN_OT_drivers_editor_show(struct wmOperatorType *ot)
/** \name Show Info Log Operator
* \{ */
-static int info_log_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int info_log_show_exec(bContext *C, wmOperator *op)
{
+ wmWindow *win_cur = CTX_wm_window(C);
+ /* Use eventstate, not event from _invoke, so this can be called through exec(). */
+ const wmEvent *event = win_cur->eventstate;
int sizex = 900 * UI_DPI_FAC;
int sizey = 580 * UI_DPI_FAC;
int shift_y = 480;
@@ -5020,7 +5029,7 @@ static void SCREEN_OT_info_log_show(struct wmOperatorType *ot)
ot->idname = "SCREEN_OT_info_log_show";
/* api callbacks */
- ot->invoke = info_log_show_invoke;
+ ot->exec = info_log_show_exec;
ot->poll = ED_operator_screenactive;
}
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index 8feef0c675a..478a0adfd9a 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -83,8 +83,7 @@ static void workspace_change_update(WorkSpace *workspace_new,
eObjectMode mode_new = workspace_new->object_mode;
if (mode_old != mode_new) {
- ED_object_mode_compat_set(C, ob_act, mode_new, &wm->reports);
- ED_object_mode_toggle(C, mode_new);
+ ED_object_mode_set(C, mode_new);
}
#endif
}
@@ -109,9 +108,9 @@ static WorkSpaceLayout *workspace_change_get_new_layout(Main *bmain,
layout_new = win->workspace_hook->temp_layout_store;
}
else {
- layout_new = BKE_workspace_hook_layout_for_workspace_get(win->workspace_hook, workspace_new);
+ layout_new = BKE_workspace_active_layout_for_workspace_get(win->workspace_hook, workspace_new);
if (!layout_new) {
- layout_new = BKE_workspace_layouts_get(workspace_new)->first;
+ layout_new = workspace_new->layouts.first;
}
}
screen_new = BKE_workspace_layout_screen_get(layout_new);
@@ -163,7 +162,7 @@ bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager
return false;
}
- BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace_new, layout_new);
+ BKE_workspace_active_layout_set(win->workspace_hook, workspace_new, layout_new);
BKE_workspace_active_set(win->workspace_hook, workspace_new);
/* update screen *after* changing workspace - which also causes the
@@ -175,7 +174,7 @@ bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager
/* Automatic mode switching. */
if (workspace_new->object_mode != workspace_old->object_mode) {
- ED_object_mode_generic_enter(C, workspace_new->object_mode);
+ ED_object_mode_set(C, workspace_new->object_mode);
}
return true;
@@ -188,7 +187,6 @@ bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager
WorkSpace *ED_workspace_duplicate(WorkSpace *workspace_old, Main *bmain, wmWindow *win)
{
WorkSpaceLayout *layout_active_old = BKE_workspace_active_layout_get(win->workspace_hook);
- ListBase *layouts_old = BKE_workspace_layouts_get(workspace_old);
WorkSpace *workspace_new = ED_workspace_add(bmain, workspace_old->id.name + 2);
workspace_new->flags = workspace_old->flags;
@@ -198,7 +196,7 @@ WorkSpace *ED_workspace_duplicate(WorkSpace *workspace_old, Main *bmain, wmWindo
/* TODO(campbell): tools */
- LISTBASE_FOREACH (WorkSpaceLayout *, layout_old, layouts_old) {
+ LISTBASE_FOREACH (WorkSpaceLayout *, layout_old, &workspace_old->layouts) {
WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(
bmain, workspace_new, layout_old, win);
diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c
index cf9637788a9..7ce92bc3e4d 100644
--- a/source/blender/editors/screen/workspace_layout_edit.c
+++ b/source/blender/editors/screen/workspace_layout_edit.c
@@ -140,7 +140,7 @@ bool ED_workspace_layout_delete(WorkSpace *workspace, WorkSpaceLayout *layout_ol
const bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
WorkSpaceLayout *layout_new;
- BLI_assert(BLI_findindex(BKE_workspace_layouts_get(workspace), layout_old) != -1);
+ BLI_assert(BLI_findindex(&workspace->layouts, layout_old) != -1);
/* don't allow deleting temp fullscreens for now */
if (BKE_screen_is_fullscreen_area(screen_old)) {
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 191a064a95c..4222a466a7b 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1674,23 +1674,13 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* Public API */
-void paint_cursor_start(bContext *C, bool (*poll)(bContext *C))
+void paint_cursor_start(Paint *p, bool (*poll)(bContext *C))
{
- Paint *p = BKE_paint_get_active_from_context(C);
-
if (p && !p->paint_cursor) {
p->paint_cursor = WM_paint_cursor_activate(
- CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL);
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL);
}
/* Invalidate the paint cursors. */
BKE_paint_invalidate_overlay_all();
}
-
-void paint_cursor_start_explicit(Paint *p, wmWindowManager *wm, bool (*poll)(bContext *C))
-{
- if (p && !p->paint_cursor) {
- p->paint_cursor = WM_paint_cursor_activate(
- wm, SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL);
- }
-}
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index fd5018f76ff..08af3bdd16c 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -511,12 +511,8 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
}
if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
- pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- image_paint_poll,
- gradient_draw_line,
- pop);
+ pop->cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, image_paint_poll, gradient_draw_line, pop);
}
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
@@ -655,7 +651,7 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
}
if (pop->cursor) {
- WM_paint_cursor_end(CTX_wm_manager(C), pop->cursor);
+ WM_paint_cursor_end(pop->cursor);
}
ED_image_undo_push_end();
@@ -785,19 +781,18 @@ bool get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
/************************ cursor drawing *******************************/
-static void toggle_paint_cursor(bContext *C, int enable)
+static void toggle_paint_cursor(Scene *scene, bool enable)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- Scene *scene = CTX_data_scene(C);
ToolSettings *settings = scene->toolsettings;
+ Paint *p = &settings->imapaint.paint;
- if (settings->imapaint.paintcursor && !enable) {
- WM_paint_cursor_end(wm, settings->imapaint.paintcursor);
- settings->imapaint.paintcursor = NULL;
+ if (p->paint_cursor && !enable) {
+ WM_paint_cursor_end(p->paint_cursor);
+ p->paint_cursor = NULL;
paint_cursor_delete_textures();
}
else if (enable) {
- paint_cursor_start(C, image_paint_poll);
+ paint_cursor_start(p, image_paint_poll);
}
}
@@ -827,7 +822,7 @@ void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene)
if (enabled) {
BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_2D, PAINT_CURSOR_TEXTURE_PAINT);
- paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll);
+ paint_cursor_start(&imapaint->paint, image_paint_poll);
}
else {
paint_cursor_delete_textures();
@@ -1121,6 +1116,100 @@ void PAINT_OT_sample_color(wmOperatorType *ot)
/******************** texture paint toggle operator ********************/
+void ED_object_texture_paint_mode_enter_ex(Main *bmain, Scene *scene, Object *ob)
+{
+ bScreen *screen;
+ Image *ima = NULL;
+ ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+
+ /* This has to stay here to regenerate the texture paint
+ * cache in case we are loading a file */
+ BKE_texpaint_slots_refresh_object(scene, ob);
+
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+
+ /* entering paint mode also sets image to editors */
+ if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+ /* set the current material active paint slot on image editor */
+ Material *ma = BKE_object_material_get(ob, ob->actcol);
+
+ if (ma && ma->texpaintslot) {
+ ima = ma->texpaintslot[ma->paint_active_slot].ima;
+ }
+ }
+ else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
+ ima = imapaint->canvas;
+ }
+
+ if (ima) {
+ for (screen = bmain->screens.first; screen; screen = screen->id.next) {
+ ScrArea *area;
+ for (area = screen->areabase.first; area; area = area->next) {
+ SpaceLink *sl;
+ for (sl = area->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ if (!sima->pin) {
+ ED_space_image_set(bmain, sima, NULL, ima, true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ob->mode |= OB_MODE_TEXTURE_PAINT;
+
+ BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_3D, PAINT_CURSOR_TEXTURE_PAINT);
+
+ BKE_paint_toolslots_brush_validate(bmain, &imapaint->paint);
+
+ if (U.glreslimit != 0) {
+ GPU_free_images(bmain);
+ }
+ GPU_paint_set_mipmap(bmain, 0);
+
+ toggle_paint_cursor(scene, true);
+
+ Mesh *me = BKE_mesh_from_object(ob);
+ BLI_assert(me != NULL);
+ DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_SCENE | ND_MODE, scene);
+}
+
+void ED_object_texture_paint_mode_enter(bContext *C)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ ED_object_texture_paint_mode_enter_ex(bmain, scene, ob);
+}
+
+void ED_object_texture_paint_mode_exit_ex(Main *bmain, Scene *scene, Object *ob)
+{
+ ob->mode &= ~OB_MODE_TEXTURE_PAINT;
+
+ if (U.glreslimit != 0) {
+ GPU_free_images(bmain);
+ }
+ GPU_paint_set_mipmap(bmain, 1);
+ toggle_paint_cursor(scene, false);
+
+ Mesh *me = BKE_mesh_from_object(ob);
+ BLI_assert(me != NULL);
+ DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_SCENE | ND_MODE, scene);
+}
+
+void ED_object_texture_paint_mode_exit(bContext *C)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ ED_object_texture_paint_mode_exit_ex(bmain, scene, ob);
+}
+
static bool texture_paint_toggle_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
@@ -1150,78 +1239,12 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
}
if (ob->mode & mode_flag) {
- ob->mode &= ~mode_flag;
-
- if (U.glreslimit != 0) {
- GPU_free_images(bmain);
- }
- GPU_paint_set_mipmap(bmain, 1);
-
- toggle_paint_cursor(C, 0);
+ ED_object_texture_paint_mode_exit_ex(bmain, scene, ob);
}
else {
- bScreen *screen;
- Image *ima = NULL;
- ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
-
- /* This has to stay here to regenerate the texture paint
- * cache in case we are loading a file */
- BKE_texpaint_slots_refresh_object(scene, ob);
-
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
-
- /* entering paint mode also sets image to editors */
- if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
- /* set the current material active paint slot on image editor */
- Material *ma = BKE_object_material_get(ob, ob->actcol);
-
- if (ma && ma->texpaintslot) {
- ima = ma->texpaintslot[ma->paint_active_slot].ima;
- }
- }
- else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
- ima = imapaint->canvas;
- }
-
- if (ima) {
- for (screen = bmain->screens.first; screen; screen = screen->id.next) {
- ScrArea *area;
- for (area = screen->areabase.first; area; area = area->next) {
- SpaceLink *sl;
- for (sl = area->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
-
- if (!sima->pin) {
- Object *obedit = CTX_data_edit_object(C);
- ED_space_image_set(bmain, sima, obedit, ima, true);
- }
- }
- }
- }
- }
- }
-
- ob->mode |= mode_flag;
-
- BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_3D, PAINT_CURSOR_TEXTURE_PAINT);
-
- BKE_paint_toolslots_brush_validate(bmain, &imapaint->paint);
-
- if (U.glreslimit != 0) {
- GPU_free_images(bmain);
- }
- GPU_paint_set_mipmap(bmain, 0);
-
- toggle_paint_cursor(C, 1);
+ ED_object_texture_paint_mode_enter_ex(bmain, scene, ob);
}
- Mesh *me = BKE_mesh_from_object(ob);
- BLI_assert(me != NULL);
- DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE);
-
- WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
-
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
WM_toolsystem_update_from_context_view3d(C);
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 018d7f72bb6..0d4e957c77b 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -90,10 +90,7 @@ void *paint_stroke_mode_data(struct PaintStroke *stroke);
float paint_stroke_distance_get(struct PaintStroke *stroke);
void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data);
bool paint_poll(struct bContext *C);
-void paint_cursor_start(struct bContext *C, bool (*poll)(struct bContext *C));
-void paint_cursor_start_explicit(struct Paint *p,
- struct wmWindowManager *wm,
- bool (*poll)(struct bContext *C));
+void paint_cursor_start(struct Paint *p, bool (*poll)(struct bContext *C));
void paint_cursor_delete_textures(void);
/* paint_vertex.c */
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 634e29ca400..0f54d5e0821 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -1147,24 +1147,24 @@ static int stencil_fit_image_aspect_exec(bContext *C, wmOperator *op)
aspy *= tex->yrepeat;
}
- orig_area = aspx * aspy;
+ orig_area = fabsf(aspx * aspy);
if (do_mask) {
- stencil_area = br->mask_stencil_dimension[0] * br->mask_stencil_dimension[1];
+ stencil_area = fabsf(br->mask_stencil_dimension[0] * br->mask_stencil_dimension[1]);
}
else {
- stencil_area = br->stencil_dimension[0] * br->stencil_dimension[1];
+ stencil_area = fabsf(br->stencil_dimension[0] * br->stencil_dimension[1]);
}
factor = sqrtf(stencil_area / orig_area);
if (do_mask) {
- br->mask_stencil_dimension[0] = factor * aspx;
- br->mask_stencil_dimension[1] = factor * aspy;
+ br->mask_stencil_dimension[0] = fabsf(factor * aspx);
+ br->mask_stencil_dimension[1] = fabsf(factor * aspy);
}
else {
- br->stencil_dimension[0] = factor * aspx;
- br->stencil_dimension[1] = factor * aspy;
+ br->stencil_dimension[0] = fabsf(factor * aspx);
+ br->stencil_dimension[1] = fabsf(factor * aspy);
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 458c24e5194..2c6f708d82a 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -230,8 +230,7 @@ static bool paint_tool_require_location(Brush *brush, ePaintMode mode)
SCULPT_TOOL_THUMB)) {
return false;
}
- else if (brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
- brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
+ else if (SCULPT_is_cloth_deform_brush(brush)) {
return false;
}
else {
@@ -963,7 +962,7 @@ void paint_stroke_free(bContext *C, wmOperator *op)
}
if (stroke->stroke_cursor) {
- WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor);
+ WM_paint_cursor_end(stroke->stroke_cursor);
}
BLI_freelistN(&stroke->line);
@@ -1386,12 +1385,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (paint_supports_smooth_stroke(br, mode)) {
- stroke->stroke_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- paint_poll,
- paint_draw_smooth_cursor,
- stroke);
+ stroke->stroke_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_poll, paint_draw_smooth_cursor, stroke);
}
stroke->stroke_init = true;
@@ -1417,12 +1412,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (br->flag & BRUSH_LINE) {
- stroke->stroke_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- paint_poll,
- paint_draw_line_cursor,
- stroke);
+ stroke->stroke_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_poll, paint_draw_line_cursor, stroke);
}
first_dab = true;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index a18a0145faa..6de54b3ae6a 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1193,12 +1193,8 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
/** \name Enter Vertex/Weight Paint Mode
* \{ */
-static void ed_vwpaintmode_enter_generic(Main *bmain,
- Depsgraph *depsgraph,
- wmWindowManager *wm,
- Scene *scene,
- Object *ob,
- const eObjectMode mode_flag)
+static void ed_vwpaintmode_enter_generic(
+ Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, const eObjectMode mode_flag)
{
ob->mode |= mode_flag;
Mesh *me = BKE_mesh_from_object(ob);
@@ -1214,7 +1210,7 @@ static void ed_vwpaintmode_enter_generic(Main *bmain,
BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->vpaint);
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
- paint_cursor_start_explicit(paint, wm, vertex_paint_poll);
+ paint_cursor_start(paint, vertex_paint_poll);
BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT);
}
else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
@@ -1222,7 +1218,7 @@ static void ed_vwpaintmode_enter_generic(Main *bmain,
BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->wpaint);
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
- paint_cursor_start_explicit(paint, wm, weight_paint_poll);
+ paint_cursor_start(paint, weight_paint_poll);
BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT);
/* weight paint specific */
@@ -1248,32 +1244,28 @@ static void ed_vwpaintmode_enter_generic(Main *bmain,
DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
-void ED_object_vpaintmode_enter_ex(
- Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob)
+void ED_object_vpaintmode_enter_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- ed_vwpaintmode_enter_generic(bmain, depsgraph, wm, scene, ob, OB_MODE_VERTEX_PAINT);
+ ed_vwpaintmode_enter_generic(bmain, depsgraph, scene, ob, OB_MODE_VERTEX_PAINT);
}
void ED_object_vpaintmode_enter(struct bContext *C, Depsgraph *depsgraph)
{
Main *bmain = CTX_data_main(C);
- wmWindowManager *wm = CTX_wm_manager(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob);
}
-void ED_object_wpaintmode_enter_ex(
- Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob)
+void ED_object_wpaintmode_enter_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- ed_vwpaintmode_enter_generic(bmain, depsgraph, wm, scene, ob, OB_MODE_WEIGHT_PAINT);
+ ed_vwpaintmode_enter_generic(bmain, depsgraph, scene, ob, OB_MODE_WEIGHT_PAINT);
}
void ED_object_wpaintmode_enter(struct bContext *C, Depsgraph *depsgraph)
{
Main *bmain = CTX_data_main(C);
- wmWindowManager *wm = CTX_wm_manager(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob);
}
/** \} */
@@ -1384,8 +1376,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
if (depsgraph) {
depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
}
- wmWindowManager *wm = CTX_wm_manager(C);
- ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob);
BKE_paint_toolslots_brush_validate(bmain, &ts->wpaint->paint);
}
@@ -2651,8 +2642,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
if (depsgraph) {
depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
}
- wmWindowManager *wm = CTX_wm_manager(C);
- ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob);
BKE_paint_toolslots_brush_validate(bmain, &ts->vpaint->paint);
}
@@ -2694,19 +2684,19 @@ void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
/* Implementation notes:
*
* Operator->invoke()
- * - validate context (add mcol)
- * - create customdata storage
- * - call paint once (mouse click)
- * - add modal handler
+ * - Validate context (add #Mesh.mloopcol).
+ * - Create custom-data storage.
+ * - Call paint once (mouse click).
+ * - Add modal handler.
*
* Operator->modal()
- * - for every mousemove, apply vertex paint
- * - exit on mouse release, free customdata
+ * - For every mouse-move, apply vertex paint.
+ * - Exit on mouse release, free custom-data.
* (return OPERATOR_FINISHED also removes handler and operator)
*
* For future:
- * - implement a stroke event (or mousemove with past positions)
- * - revise whether op->customdata should be added in object, in set_vpaint
+ * - implement a stroke event (or mouse-move with past positions).
+ * - revise whether op->customdata should be added in object, in set_vpaint.
*/
struct VPaintData {
@@ -2718,8 +2708,10 @@ struct VPaintData {
struct VertProjHandle *vp_handle;
struct CoNo *vertexcosnos;
- /* modify 'me->mcol' directly, since the derived mesh is drawing from this
- * array, otherwise we need to refresh the modifier stack */
+ /**
+ * Modify #Mesh.mloopcol directly, since the derived mesh is drawing from this
+ * array, otherwise we need to refresh the modifier stack.
+ */
bool use_fast_update;
/* loops tagged as having been painted, to apply shared vertex color
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 855e7503e3b..b4ae9c96ba7 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -156,9 +156,16 @@ const float *SCULPT_vertex_co_get(SculptSession *ss, int index)
void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
{
switch (BKE_pbvh_type(ss->pbvh)) {
- case PBVH_FACES:
- normal_short_to_float_v3(no, ss->mvert[index].no);
- return;
+ case PBVH_FACES: {
+ if (ss->shapekey_active || ss->deform_modifiers_active) {
+ const MVert *mverts = BKE_pbvh_get_verts(ss->pbvh);
+ normal_short_to_float_v3(no, mverts[index].no);
+ }
+ else {
+ normal_short_to_float_v3(no, ss->mvert[index].no);
+ }
+ break;
+ }
case PBVH_BMESH:
copy_v3_v3(no, BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->no);
break;
@@ -254,8 +261,15 @@ bool SCULPT_vertex_visible_get(SculptSession *ss, int index)
return !(ss->mvert[index].flag & ME_HIDE);
case PBVH_BMESH:
return !BM_elem_flag_test(BM_vert_at_index(ss->bm, index), BM_ELEM_HIDDEN);
- case PBVH_GRIDS:
- return true;
+ case PBVH_GRIDS: {
+ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
+ const int grid_index = index / key->grid_area;
+ const int vertex_index = index - grid_index * key->grid_area;
+ BLI_bitmap **grid_hidden = BKE_pbvh_get_grid_visibility(ss->pbvh);
+ if (grid_hidden && grid_hidden[grid_index]) {
+ return !BLI_BITMAP_TEST(grid_hidden[grid_index], vertex_index);
+ }
+ }
}
return true;
}
@@ -851,7 +865,7 @@ void SCULPT_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
SCULPT_vertex_random_access_init(ss);
flood->queue = BLI_gsqueue_new(sizeof(int));
- flood->visited_vertices = MEM_callocN(vertex_count * sizeof(char), "visited vertices");
+ flood->visited_vertices = BLI_BITMAP_NEW(vertex_count, "visited vertices");
}
void SCULPT_floodfill_add_initial(SculptFloodFill *flood, int index)
@@ -919,8 +933,8 @@ void SCULPT_floodfill_execute(
SculptVertexNeighborIter ni;
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) {
const int to_v = ni.index;
- if (flood->visited_vertices[to_v] == 0 && SCULPT_vertex_visible_get(ss, to_v)) {
- flood->visited_vertices[to_v] = 1;
+ if (!BLI_BITMAP_TEST(flood->visited_vertices, to_v) && SCULPT_vertex_visible_get(ss, to_v)) {
+ BLI_BITMAP_ENABLE(flood->visited_vertices, to_v);
if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) {
BLI_gsqueue_push(flood->queue, &to_v);
@@ -2084,9 +2098,13 @@ static float brush_strength(const Sculpt *sd,
case SCULPT_TOOL_LAYER:
return alpha * flip * pressure * overlap * feather;
case SCULPT_TOOL_CLOTH:
- /* Expand is more sensible to strength as it keeps expanding the cloth when sculpting over
- * the same vertices. */
- if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_EXPAND) {
+ if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
+ /* Grab deform uses the same falloff as a regular grab brush. */
+ return root_alpha * feather;
+ }
+ else if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_EXPAND) {
+ /* Expand is more sensible to strength as it keeps expanding the cloth when sculpting over
+ * the same vertices. */
return 0.1f * alpha * flip * pressure * overlap * feather;
}
else {
@@ -5468,7 +5486,8 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
}
/* The cloth brush adds the gravity as a regular force and it is processed in the solver. */
- if (ss->cache->supports_gravity && brush->sculpt_tool != SCULPT_TOOL_CLOTH) {
+ if (ss->cache->supports_gravity &&
+ !ELEM(brush->sculpt_tool, SCULPT_TOOL_CLOTH, SCULPT_TOOL_DRAW_FACE_SETS)) {
do_gravity(sd, ob, nodes, totnode, sd->gravity_factor);
}
@@ -6208,6 +6227,34 @@ static float sculpt_brush_dynamic_size_get(Brush *brush, StrokeCache *cache, flo
}
}
+/* In these brushes the grab delta is calculated always from the initial stroke location, which is
+ * generally used to create grab deformations. */
+static bool sculpt_needs_delta_from_anchored_origin(Brush *brush)
+{
+ return ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_POSE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_ELASTIC_DEFORM) ||
+ SCULPT_is_cloth_deform_brush(brush);
+}
+
+/* In these brushes the grab delta is calculated from the previous stroke location, which is used
+ * to calculate to orientate the brush tip and deformation towards the stroke direction. */
+static bool sculpt_needs_delta_for_tip_orientation(Brush *brush)
+{
+ if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
+ return !SCULPT_is_cloth_deform_brush(brush);
+ }
+ return ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_CLAY_STRIPS,
+ SCULPT_TOOL_PINCH,
+ SCULPT_TOOL_MULTIPLANE_SCRAPE,
+ SCULPT_TOOL_CLAY_THUMB,
+ SCULPT_TOOL_NUDGE,
+ SCULPT_TOOL_SNAKE_HOOK);
+}
+
static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Brush *brush)
{
SculptSession *ss = ob->sculpt;
@@ -6251,38 +6298,27 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
/* Compute delta to move verts by. */
if (!cache->first_time) {
- switch (tool) {
- case SCULPT_TOOL_GRAB:
- case SCULPT_TOOL_POSE:
- case SCULPT_TOOL_THUMB:
- case SCULPT_TOOL_ELASTIC_DEFORM:
- sub_v3_v3v3(delta, grab_location, cache->old_grab_location);
- invert_m4_m4(imat, ob->obmat);
- mul_mat3_m4_v3(imat, delta);
- add_v3_v3(cache->grab_delta, delta);
- break;
- case SCULPT_TOOL_CLAY_STRIPS:
- case SCULPT_TOOL_PINCH:
- case SCULPT_TOOL_CLOTH:
- case SCULPT_TOOL_MULTIPLANE_SCRAPE:
- case SCULPT_TOOL_CLAY_THUMB:
- case SCULPT_TOOL_NUDGE:
- case SCULPT_TOOL_SNAKE_HOOK:
- if (brush->flag & BRUSH_ANCHORED) {
- float orig[3];
- mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location);
- sub_v3_v3v3(cache->grab_delta, grab_location, orig);
- }
- else {
- sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
- }
- invert_m4_m4(imat, ob->obmat);
- mul_mat3_m4_v3(imat, cache->grab_delta);
- break;
- default:
- /* Use for 'Brush.topology_rake_factor'. */
+ if (sculpt_needs_delta_from_anchored_origin(brush)) {
+ sub_v3_v3v3(delta, grab_location, cache->old_grab_location);
+ invert_m4_m4(imat, ob->obmat);
+ mul_mat3_m4_v3(imat, delta);
+ add_v3_v3(cache->grab_delta, delta);
+ }
+ else if (sculpt_needs_delta_for_tip_orientation(brush)) {
+ if (brush->flag & BRUSH_ANCHORED) {
+ float orig[3];
+ mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location);
+ sub_v3_v3v3(cache->grab_delta, grab_location, orig);
+ }
+ else {
sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
- break;
+ }
+ invert_m4_m4(imat, ob->obmat);
+ mul_mat3_m4_v3(imat, cache->grab_delta);
+ }
+ else {
+ /* Use for 'Brush.topology_rake_factor'. */
+ sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
}
}
else {
@@ -6303,18 +6339,14 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
copy_v3_v3(cache->anchored_location, cache->true_location);
}
}
- else if (tool == SCULPT_TOOL_ELASTIC_DEFORM) {
+ else if (tool == SCULPT_TOOL_ELASTIC_DEFORM || SCULPT_is_cloth_deform_brush(brush)) {
copy_v3_v3(cache->anchored_location, cache->true_location);
}
else if (tool == SCULPT_TOOL_THUMB) {
copy_v3_v3(cache->anchored_location, cache->orig_grab_location);
}
- if (ELEM(tool,
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_ELASTIC_DEFORM,
- SCULPT_TOOL_POSE)) {
+ if (sculpt_needs_delta_from_anchored_origin(brush)) {
/* Location stays the same for finding vertices in brush radius. */
copy_v3_v3(cache->true_location, cache->orig_grab_location);
@@ -6385,9 +6417,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
if (cache->first_time ||
!((brush->flag & BRUSH_ANCHORED) || (brush->sculpt_tool == SCULPT_TOOL_SNAKE_HOOK) ||
- (brush->sculpt_tool == SCULPT_TOOL_ROTATE) ||
- (brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
- brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB))) {
+ (brush->sculpt_tool == SCULPT_TOOL_ROTATE) || SCULPT_is_cloth_deform_brush(brush))) {
RNA_float_get_array(ptr, "location", cache->true_location);
}
@@ -7606,7 +7636,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
Paint *paint = BKE_paint_get_active_from_paintmode(scene, PAINT_MODE_SCULPT);
BKE_paint_init(bmain, scene, PAINT_MODE_SCULPT, PAINT_CURSOR_SCULPT);
- paint_cursor_start_explicit(paint, bmain->wm.first, SCULPT_poll_view3d);
+ paint_cursor_start(paint, SCULPT_poll_view3d);
/* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes,
* As long as no data was added that is not supported. */
@@ -7813,8 +7843,7 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float
float brush_co[3];
copy_v3_v3(brush_co, SCULPT_active_vertex_co_get(ss));
- char *visited_vertices = MEM_callocN(SCULPT_vertex_count_get(ss) * sizeof(char),
- "visited vertices");
+ BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(SCULPT_vertex_count_get(ss), "visited_vertices");
/* Assuming an average of 6 edges per vertex in a triangulated mesh. */
const int max_preview_vertices = SCULPT_vertex_count_get(ss) * 3 * 2;
@@ -7838,8 +7867,8 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float
totpoints++;
ss->preview_vert_index_list[totpoints] = to_v;
totpoints++;
- if (visited_vertices[to_v] == 0) {
- visited_vertices[to_v] = 1;
+ if (!BLI_BITMAP_TEST(visited_vertices, to_v)) {
+ BLI_BITMAP_ENABLE(visited_vertices, to_v);
const float *co = SCULPT_vertex_co_get(ss, to_v);
if (len_squared_v3v3(brush_co, co) < radius * radius) {
BLI_gsqueue_push(not_visited_vertices, &to_v);
@@ -7877,4 +7906,5 @@ void ED_operatortypes_sculpt(void)
WM_operatortype_append(SCULPT_OT_face_sets_change_visibility);
WM_operatortype_append(SCULPT_OT_face_sets_randomize_colors);
WM_operatortype_append(SCULPT_OT_face_sets_init);
+ WM_operatortype_append(SCULPT_OT_cloth_filter);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c
index f0f6478d3a6..bfa657147fd 100644
--- a/source/blender/editors/sculpt_paint/sculpt_automasking.c
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c
@@ -91,7 +91,7 @@ bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, co
float SCULPT_automasking_factor_get(SculptSession *ss, int vert)
{
- if (ss->cache->automask) {
+ if (ss->cache && ss->cache->automask) {
return ss->cache->automask[vert];
}
else {
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 62a7f1925ab..3203282c30c 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -106,9 +106,11 @@
#define CLOTH_MAX_CONSTRAINTS_PER_VERTEX 1024
#define CLOTH_SIMULATION_TIME_STEP 0.01f
-static void cloth_brush_add_length_constraint(SculptSession *ss, const int v1, const int v2)
+static void cloth_brush_add_length_constraint(SculptSession *ss,
+ SculptClothSimulation *cloth_sim,
+ const int v1,
+ const int v2)
{
- SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v1 = v1;
cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v2 = v2;
cloth_sim->length_constraints[cloth_sim->tot_length_constraints].length = len_v3v3(
@@ -133,12 +135,11 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
SculptSession *ss = data->ob->sculpt;
PBVHVertexIter vd;
- const float radius = ss->cache->initial_radius;
- const float limit = radius + (radius * data->brush->cloth_sim_limit);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (len_squared_v3v3(vd.co, ss->cache->initial_location) < limit * limit) {
+ if (len_squared_v3v3(vd.co, data->cloth_sim_initial_location) <
+ data->cloth_sim_radius * data->cloth_sim_radius) {
SculptVertexNeighborIter ni;
int build_indices[CLOTH_MAX_CONSTRAINTS_PER_VERTEX];
@@ -159,7 +160,8 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
for (int c_i = 0; c_i < tot_indices; c_i++) {
for (int c_j = 0; c_j < tot_indices; c_j++) {
if (c_i != c_j) {
- cloth_brush_add_length_constraint(ss, build_indices[c_i], build_indices[c_j]);
+ cloth_brush_add_length_constraint(
+ ss, data->cloth_sim, build_indices[c_i], build_indices[c_j]);
}
}
}
@@ -192,11 +194,11 @@ static float cloth_brush_simulation_falloff_get(const Brush *brush,
}
}
-static void cloth_brush_apply_force_to_vertex(SculptSession *ss,
+static void cloth_brush_apply_force_to_vertex(SculptSession *UNUSED(ss),
+ SculptClothSimulation *cloth_sim,
const float force[3],
const int vertex_index)
{
- SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
madd_v3_v3fl(cloth_sim->acceleration[vertex_index], force, 1.0f / cloth_sim->mass);
}
@@ -212,8 +214,9 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
const float *grab_delta = data->grab_delta;
float(*imat)[4] = data->mat;
- const bool use_falloff_plane = brush->cloth_force_falloff_type ==
- BRUSH_CLOTH_FORCE_FALLOFF_PLANE;
+ const bool use_falloff_plane = !SCULPT_is_cloth_deform_brush(brush) &&
+ brush->cloth_force_falloff_type ==
+ BRUSH_CLOTH_FORCE_FALLOFF_PLANE;
PBVHVertexIter vd;
const float bstrength = ss->cache->bstrength;
@@ -246,14 +249,29 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
gravity, ss->cache->gravity_direction, -ss->cache->radius * data->sd->gravity_factor);
}
+ /* Original data for deform brushes. */
+ SculptOrigVertData orig_data;
+ if (SCULPT_is_cloth_deform_brush(brush)) {
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ }
+
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
float force[3];
const float sim_factor = cloth_brush_simulation_falloff_get(
brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[vd.index]);
+ float current_vertex_location[3];
+ if (SCULPT_is_cloth_deform_brush(brush)) {
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
+ copy_v3_v3(current_vertex_location, orig_data.co);
+ }
+ else {
+ copy_v3_v3(current_vertex_location, vd.co);
+ }
+
/* When using the plane falloff mode the falloff is not constrained by the brush radius. */
- if (sculpt_brush_test_sq_fn(&test, vd.co) || use_falloff_plane) {
+ if (sculpt_brush_test_sq_fn(&test, current_vertex_location) || use_falloff_plane) {
float dist = sqrtf(test.dist);
@@ -264,7 +282,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
const float fade = sim_factor * bstrength *
SCULPT_brush_strength_factor(ss,
brush,
- vd.co,
+ current_vertex_location,
dist,
vd.no,
vd.fno,
@@ -274,7 +292,6 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
float brush_disp[3];
float normal[3];
-
if (vd.no) {
normal_short_to_float_v3(normal, vd.no);
}
@@ -293,7 +310,10 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
mul_v3_v3fl(force, offset, -fade);
break;
case BRUSH_CLOTH_DEFORM_GRAB:
- mul_v3_v3fl(force, grab_delta, fade);
+ /* Grab writes the positions in the simulation directly without applying forces. */
+ madd_v3_v3v3fl(
+ cloth_sim->pos[vd.index], orig_data.co, ss->cache->grab_delta_symmetry, fade);
+ zero_v3(force);
break;
case BRUSH_CLOTH_DEFORM_PINCH_POINT:
if (use_falloff_plane) {
@@ -329,13 +349,15 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
madd_v3_v3fl(force, gravity, fade);
- cloth_brush_apply_force_to_vertex(ss, force, vd.index);
+ cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, force, vd.index);
}
}
BKE_pbvh_vertex_iter_end;
}
-static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss, Brush *brush)
+static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss,
+ const float cloth_mass,
+ const float cloth_damping)
{
const int totverts = SCULPT_vertex_count_get(ss);
SculptClothSimulation *cloth_sim;
@@ -354,8 +376,8 @@ static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss, B
cloth_sim->length_constraint_tweak = MEM_callocN(sizeof(float) * totverts,
"cloth sim length tweak");
- cloth_sim->mass = brush->cloth_mass;
- cloth_sim->damping = brush->cloth_damping;
+ cloth_sim->mass = cloth_mass;
+ cloth_sim->damping = cloth_damping;
return cloth_sim;
}
@@ -367,12 +389,16 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
SculptSession *ss = data->ob->sculpt;
const Brush *brush = data->brush;
PBVHVertexIter vd;
- SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
+ SculptClothSimulation *cloth_sim = data->cloth_sim;
const float time_step = data->cloth_time_step;
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- const float sim_factor = cloth_brush_simulation_falloff_get(
- brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[vd.index]);
+ const float sim_factor = ss->cache ? cloth_brush_simulation_falloff_get(
+ brush,
+ ss->cache->radius,
+ ss->cache->initial_location,
+ cloth_sim->init_pos[vd.index]) :
+ 1.0f;
if (sim_factor > 0.0f) {
int i = vd.index;
float temp[3];
@@ -393,7 +419,7 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
copy_v3_fl(cloth_sim->acceleration[i], 0.0f);
- copy_v3_v3(vd.co, ss->cache->cloth_sim->pos[vd.index]);
+ copy_v3_v3(vd.co, cloth_sim->pos[vd.index]);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
@@ -405,7 +431,10 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
static void cloth_brush_build_nodes_constraints(Sculpt *sd,
Object *ob,
PBVHNode **nodes,
- int totnode)
+ int totnode,
+ SculptClothSimulation *cloth_sim,
+ float initial_location[3],
+ const float radius)
{
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -421,6 +450,9 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd,
.ob = ob,
.brush = brush,
.nodes = nodes,
+ .cloth_sim = cloth_sim,
+ .cloth_sim_initial_location = initial_location,
+ .cloth_sim_radius = radius,
};
BLI_task_parallel_range(
0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings);
@@ -461,10 +493,18 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, v2)) *
SCULPT_automasking_factor_get(ss, v2);
- const float sim_factor_v1 = cloth_brush_simulation_falloff_get(
- brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[v1]);
- const float sim_factor_v2 = cloth_brush_simulation_falloff_get(
- brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[v2]);
+ const float sim_factor_v1 = ss->cache ? cloth_brush_simulation_falloff_get(
+ brush,
+ ss->cache->radius,
+ ss->cache->initial_location,
+ cloth_sim->init_pos[v1]) :
+ 1.0f;
+ const float sim_factor_v2 = ss->cache ? cloth_brush_simulation_falloff_get(
+ brush,
+ ss->cache->radius,
+ ss->cache->initial_location,
+ cloth_sim->init_pos[v2]) :
+ 1.0f;
madd_v3_v3fl(cloth_sim->pos[v1], correction_vector_half, 1.0f * mask_v1 * sim_factor_v1);
madd_v3_v3fl(cloth_sim->pos[v2], correction_vector_half, -1.0f * mask_v2 * sim_factor_v2);
@@ -472,13 +512,12 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
}
}
-static void cloth_brush_do_simulation_step(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+static void cloth_brush_do_simulation_step(
+ Sculpt *sd, Object *ob, SculptClothSimulation *cloth_sim, PBVHNode **nodes, int totnode)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
-
/* Update the constraints. */
cloth_brush_satisfy_constraints(ss, brush, cloth_sim);
@@ -489,6 +528,7 @@ static void cloth_brush_do_simulation_step(Sculpt *sd, Object *ob, PBVHNode **no
.brush = brush,
.nodes = nodes,
.cloth_time_step = CLOTH_SIMULATION_TIME_STEP,
+ .cloth_sim = cloth_sim,
};
TaskParallelSettings settings;
@@ -589,7 +629,8 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
/* The simulation structure only needs to be created on the first symmetry pass. */
if (ss->cache->mirror_symmetry_pass == 0) {
- ss->cache->cloth_sim = cloth_brush_simulation_create(ss, brush);
+ ss->cache->cloth_sim = cloth_brush_simulation_create(
+ ss, brush->cloth_mass, brush->cloth_damping);
for (int i = 0; i < totverts; i++) {
copy_v3_v3(ss->cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
copy_v3_v3(ss->cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
@@ -597,7 +638,10 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
}
/* Build the constraints. */
- cloth_brush_build_nodes_constraints(sd, ob, nodes, totnode);
+ const float radius = ss->cache->initial_radius;
+ const float limit = radius + (radius * brush->cloth_sim_limit);
+ cloth_brush_build_nodes_constraints(
+ sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, limit);
return;
}
@@ -611,7 +655,7 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
cloth_brush_apply_brush_foces(sd, ob, nodes, totnode);
/* Update and write the simulation to the nodes. */
- cloth_brush_do_simulation_step(sd, ob, nodes, totnode);
+ cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode);
return;
}
@@ -687,3 +731,246 @@ void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr,
immEnd();
}
+
+/* Cloth Filter. */
+
+typedef enum eSculpClothFilterType {
+ CLOTH_FILTER_GRAVITY,
+ CLOTH_FILTER_INFLATE,
+ CLOTH_FILTER_EXPAND,
+ CLOTH_FILTER_PINCH,
+} eSculptClothFilterType;
+
+static EnumPropertyItem prop_cloth_filter_type[] = {
+ {CLOTH_FILTER_GRAVITY, "GRAVITY", 0, "Gravity", "Applies gravity to the simulation"},
+ {CLOTH_FILTER_INFLATE, "INFLATE", 0, "Inflate", "Inflates the cloth"},
+ {CLOTH_FILTER_EXPAND, "EXPAND", 0, "Expand", "Expands the cloth's dimensions"},
+ {CLOTH_FILTER_PINCH,
+ "PINCH",
+ 0,
+ "Pinch",
+ "Pinches the cloth to the point were the cursor was when the filter started"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static void cloth_filter_apply_forces_task_cb(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ Sculpt *sd = data->sd;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHNode *node = data->nodes[i];
+
+ SculptClothSimulation *cloth_sim = ss->filter_cache->cloth_sim;
+ const int filter_type = data->filter_type;
+
+ float sculpt_gravity[3] = {0.0f};
+ if (sd->gravity_object) {
+ copy_v3_v3(sculpt_gravity, sd->gravity_object->obmat[2]);
+ }
+ else {
+ sculpt_gravity[2] = -1.0f;
+ }
+ mul_v3_fl(sculpt_gravity, sd->gravity_factor * data->filter_strength);
+
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ float fade = vd.mask ? *vd.mask : 0.0f;
+ fade = 1.0f - fade;
+ float force[3] = {0.0f, 0.0f, 0.0f};
+
+ if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) {
+ if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) {
+ continue;
+ }
+ }
+
+ switch (filter_type) {
+ case CLOTH_FILTER_GRAVITY:
+ force[2] = -data->filter_strength * fade;
+ break;
+ case CLOTH_FILTER_INFLATE: {
+ float normal[3];
+ SCULPT_vertex_normal_get(ss, vd.index, normal);
+ mul_v3_v3fl(force, normal, fade * data->filter_strength);
+ } break;
+ case CLOTH_FILTER_EXPAND:
+ cloth_sim->length_constraint_tweak[vd.index] += fade * data->filter_strength * 0.01f;
+ zero_v3(force);
+ break;
+ case CLOTH_FILTER_PINCH:
+ sub_v3_v3v3(force, ss->filter_cache->cloth_sim_pinch_point, vd.co);
+ normalize_v3(force);
+ mul_v3_fl(force, fade * data->filter_strength);
+ break;
+ }
+
+ add_v3_v3(force, sculpt_gravity);
+
+ cloth_brush_apply_force_to_vertex(ss, cloth_sim, force, vd.index);
+ }
+ BKE_pbvh_vertex_iter_end;
+
+ BKE_pbvh_node_mark_update(node);
+}
+
+static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *ob = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ int filter_type = RNA_enum_get(op->ptr, "type");
+ float filter_strength = RNA_float_get(op->ptr, "strength");
+
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ SCULPT_filter_cache_free(ss);
+ SCULPT_undo_push_end();
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
+ return OPERATOR_FINISHED;
+ }
+
+ if (event->type != MOUSEMOVE) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ float len = event->prevclickx - event->mval[0];
+ filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
+
+ SCULPT_vertex_random_access_init(ss);
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
+
+ const int totverts = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totverts; i++) {
+ copy_v3_v3(ss->filter_cache->cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i));
+ }
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = ss->filter_cache->nodes,
+ .filter_type = filter_type,
+ .filter_strength = filter_strength,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(
+ &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
+ BLI_task_parallel_range(
+ 0, ss->filter_cache->totnode, &data, cloth_filter_apply_forces_task_cb, &settings);
+
+ /* Update and write the simulation to the nodes. */
+ cloth_brush_do_simulation_step(
+ sd, ob, ss->filter_cache->cloth_sim, ss->filter_cache->nodes, ss->filter_cache->totnode);
+
+ if (ss->deform_modifiers_active || ss->shapekey_active) {
+ SCULPT_flush_stroke_deform(sd, ob, true);
+ }
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *ob = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ SculptSession *ss = ob->sculpt;
+
+ /* Update the active vertex */
+ float mouse[2];
+ SculptCursorGeometryInfo sgi;
+ mouse[0] = event->mval[0];
+ mouse[1] = event->mval[1];
+ SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
+
+ SCULPT_vertex_random_access_init(ss);
+
+ /* Needs mask data to be available as it is used when solving the constraints. */
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
+
+ SCULPT_undo_push_begin("Cloth filter");
+ SCULPT_filter_cache_init(ob, sd);
+
+ const float cloth_mass = RNA_float_get(op->ptr, "cloth_mass");
+ const float cloth_damping = RNA_float_get(op->ptr, "cloth_damping");
+ ss->filter_cache->cloth_sim = cloth_brush_simulation_create(ss, cloth_mass, cloth_damping);
+ copy_v3_v3(ss->filter_cache->cloth_sim_pinch_point, SCULPT_active_vertex_co_get(ss));
+
+ const int totverts = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totverts; i++) {
+ copy_v3_v3(ss->filter_cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
+ copy_v3_v3(ss->filter_cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
+ }
+
+ float origin[3] = {0.0f, 0.0f, 0.0f};
+ cloth_brush_build_nodes_constraints(sd,
+ ob,
+ ss->filter_cache->nodes,
+ ss->filter_cache->totnode,
+ ss->filter_cache->cloth_sim,
+ origin,
+ FLT_MAX);
+
+ const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
+ if (use_face_sets) {
+ ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss);
+ }
+ else {
+ ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
+ }
+
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void SCULPT_OT_cloth_filter(struct wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Filter cloth";
+ ot->idname = "SCULPT_OT_cloth_filter";
+ ot->description = "Applies a cloth simulation deformation to the entire mesh";
+
+ /* API callbacks. */
+ ot->invoke = sculpt_cloth_filter_invoke;
+ ot->modal = sculpt_cloth_filter_modal;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* RNA. */
+ RNA_def_enum(ot->srna,
+ "type",
+ prop_cloth_filter_type,
+ CLOTH_FILTER_GRAVITY,
+ "Filter type",
+ "Operation that is going to be applied to the mesh");
+ RNA_def_float(
+ ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f);
+ RNA_def_float(ot->srna,
+ "cloth_mass",
+ 1.0f,
+ 0.0f,
+ 2.0f,
+ "Cloth Mass",
+ "Mass of each simulation particle",
+ 0.0f,
+ 1.0f);
+ RNA_def_float(ot->srna,
+ "cloth_damping",
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ "Cloth Damping",
+ "How much the applied forces are propagated through the cloth",
+ 0.0f,
+ 1.0f);
+ ot->prop = RNA_def_boolean(ot->srna,
+ "use_face_sets",
+ false,
+ "Use Face Sets",
+ "Apply the filter only to the Face Set under the cursor");
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c
index f96f08e3244..cbdbab14690 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.c
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c
@@ -297,6 +297,25 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
}
if (mode == SCULPT_FACE_SET_VISIBLE) {
+
+ /* If all vertices in the sculpt are visible, create the new face set and update the default
+ * color. This way the new face set will be white, which is a quick way of disabling all face
+ * sets and the performance hit of rendering the overlay. */
+ bool all_visible = true;
+ for (int i = 0; i < tot_vert; i++) {
+ if (!SCULPT_vertex_visible_get(ss, i)) {
+ all_visible = false;
+ break;
+ }
+ }
+
+ if (all_visible) {
+ Mesh *mesh = ob->data;
+ mesh->face_sets_color_default = next_face_set;
+ BKE_pbvh_face_sets_color_set(
+ ss->pbvh, mesh->face_sets_color_seed, mesh->face_sets_color_default);
+ }
+
for (int i = 0; i < tot_vert; i++) {
if (SCULPT_vertex_visible_get(ss, i)) {
SCULPT_vertex_face_set_set(ss, i, next_face_set);
@@ -504,7 +523,7 @@ static void sculpt_face_sets_init_flood_fill(Object *ob,
.calc_face_normal = true,
}));
- bool *visited_faces = MEM_callocN(sizeof(bool) * mesh->totpoly, "visited faces");
+ BLI_bitmap *visited_faces = BLI_BITMAP_NEW(mesh->totpoly, "visited faces");
const int totfaces = mesh->totpoly;
int *face_sets = ss->face_sets;
@@ -515,12 +534,12 @@ static void sculpt_face_sets_init_flood_fill(Object *ob,
int next_face_set = 1;
for (int i = 0; i < totfaces; i++) {
- if (!visited_faces[i]) {
+ if (!BLI_BITMAP_TEST(visited_faces, i)) {
GSQueue *queue;
queue = BLI_gsqueue_new(sizeof(int));
face_sets[i] = next_face_set;
- visited_faces[i] = true;
+ BLI_BITMAP_ENABLE(visited_faces, i);
BLI_gsqueue_push(queue, &i);
while (!BLI_gsqueue_is_empty(queue)) {
@@ -537,10 +556,10 @@ static void sculpt_face_sets_init_flood_fill(Object *ob,
BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) {
if (f_neighbor != f) {
int neighbor_face_index = BM_elem_index_get(f_neighbor);
- if (!visited_faces[neighbor_face_index]) {
+ if (!BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) {
if (test(bm, f, ed, f_neighbor, threshold)) {
face_sets[neighbor_face_index] = next_face_set;
- visited_faces[neighbor_face_index] = true;
+ BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index);
BLI_gsqueue_push(queue, &neighbor_face_index);
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index 7c438e9245b..fd0f67f040a 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -121,6 +121,9 @@ void SCULPT_filter_cache_init(Object *ob, Sculpt *sd)
void SCULPT_filter_cache_free(SculptSession *ss)
{
+ if (ss->filter_cache->cloth_sim) {
+ SCULPT_cloth_simulation_free(ss->filter_cache->cloth_sim);
+ }
MEM_SAFE_FREE(ss->filter_cache->nodes);
MEM_SAFE_FREE(ss->filter_cache->mask_update_it);
MEM_SAFE_FREE(ss->filter_cache->prev_mask);
@@ -129,7 +132,6 @@ void SCULPT_filter_cache_free(SculptSession *ss)
MEM_SAFE_FREE(ss->filter_cache->automask);
MEM_SAFE_FREE(ss->filter_cache->surface_smooth_laplacian_disp);
MEM_SAFE_FREE(ss->filter_cache->sharpen_factor);
- MEM_SAFE_FREE(ss->filter_cache->accum_disp);
MEM_SAFE_FREE(ss->filter_cache);
}
@@ -344,9 +346,18 @@ static void mesh_filter_task_cb(void *__restrict userdata,
/* This filter can't work at full strength as it needs multiple iterations to reach a
* stable state. */
fade = clamp_f(fade, 0.0f, 0.5f);
+ float disp_sharpen[3] = {0.0f, 0.0f, 0.0f};
+
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ float disp_n[3];
+ sub_v3_v3v3(
+ disp_n, SCULPT_vertex_co_get(ss, ni.index), SCULPT_vertex_co_get(ss, vd.index));
+ mul_v3_fl(disp_n, ss->filter_cache->sharpen_factor[ni.index]);
+ add_v3_v3(disp_sharpen, disp_n);
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
- float disp_sharpen[3];
- copy_v3_v3(disp_sharpen, ss->filter_cache->accum_disp[vd.index]);
mul_v3_fl(disp_sharpen, 1.0f - ss->filter_cache->sharpen_factor[vd.index]);
float disp_avg[3];
@@ -404,24 +415,6 @@ static void mesh_filter_sharpen_init_factors(SculptSession *ss)
}
}
-static void mesh_filter_sharpen_accumulate_displacement(SculptSession *ss)
-{
- const int totvert = SCULPT_vertex_count_get(ss);
- for (int i = 0; i < totvert; i++) {
- zero_v3(ss->filter_cache->accum_disp[i]);
- }
- for (int i = 0; i < totvert; i++) {
- SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
- float disp_n[3];
- sub_v3_v3v3(disp_n, SCULPT_vertex_co_get(ss, i), SCULPT_vertex_co_get(ss, ni.index));
- mul_v3_fl(disp_n, ss->filter_cache->sharpen_factor[i]);
- add_v3_v3(ss->filter_cache->accum_disp[ni.index], disp_n);
- }
- SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
- }
-}
-
static void mesh_filter_surface_smooth_displace_task_cb(
void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
{
@@ -484,10 +477,6 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets);
BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false);
- if (filter_type == MESH_FILTER_SHARPEN) {
- mesh_filter_sharpen_accumulate_displacement(ss);
- }
-
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
@@ -565,8 +554,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SCULPT_filter_cache_init(ob, sd);
if (use_face_sets) {
- ss->filter_cache->active_face_set = SCULPT_vertex_face_set_get(ss,
- SCULPT_active_vertex_get(ss));
+ ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss);
}
else {
ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
@@ -584,7 +572,6 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_SHARPEN) {
ss->filter_cache->sharpen_smooth_ratio = RNA_float_get(op->ptr, "sharpen_smooth_ratio");
ss->filter_cache->sharpen_factor = MEM_mallocN(sizeof(float) * totvert, "sharpen factor");
- ss->filter_cache->accum_disp = MEM_mallocN(3 * sizeof(float) * totvert, "orco");
mesh_filter_sharpen_init_factors(ss);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 9b13f6e6c24..50808b04276 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -120,7 +120,7 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss,
SCULPT_vertex_neighbors_get(ss, v_index, false, &neighbor_iterator); \
for (neighbor_iterator.i = 0; neighbor_iterator.i < neighbor_iterator.size; \
neighbor_iterator.i++) { \
- neighbor_iterator.index = ni.neighbors[ni.i];
+ neighbor_iterator.index = neighbor_iterator.neighbors[neighbor_iterator.i];
/* Iterate over neighboring and duplicate vertices (for PBVH_GRIDS). Duplicates come
* first since they are nearest for floodfill. */
@@ -128,8 +128,8 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss,
SCULPT_vertex_neighbors_get(ss, v_index, true, &neighbor_iterator); \
for (neighbor_iterator.i = neighbor_iterator.size - 1; neighbor_iterator.i >= 0; \
neighbor_iterator.i--) { \
- neighbor_iterator.index = ni.neighbors[ni.i]; \
- neighbor_iterator.is_duplicate = (ni.i >= \
+ neighbor_iterator.index = neighbor_iterator.neighbors[neighbor_iterator.i]; \
+ neighbor_iterator.is_duplicate = (neighbor_iterator.i >= \
neighbor_iterator.size - neighbor_iterator.num_duplicates);
#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator) \
@@ -233,7 +233,7 @@ void SCULPT_flip_quat_by_symm_area(float quat[3],
/* Flood Fill. */
typedef struct {
GSQueue *queue;
- char *visited_vertices;
+ BLI_bitmap *visited_vertices;
} SculptFloodFill;
void SCULPT_floodfill_init(struct SculptSession *ss, SculptFloodFill *flood);
@@ -333,6 +333,13 @@ void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr,
struct SculptSession *ss,
const float outline_col[3],
float outline_alpha);
+
+BLI_INLINE bool SCULPT_is_cloth_deform_brush(const Brush *brush)
+{
+ return brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
+ brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB;
+}
+
/* Pose Brush. */
void SCULPT_do_pose_brush(struct Sculpt *sd,
struct Object *ob,
@@ -585,6 +592,9 @@ typedef struct SculptThreadedTaskData {
float transform_mats[8][4][4];
float cloth_time_step;
+ SculptClothSimulation *cloth_sim;
+ float *cloth_sim_initial_location;
+ float cloth_sim_radius;
float dirty_mask_min;
float dirty_mask_max;
@@ -824,12 +834,15 @@ typedef struct FilterCache {
/* Sharpen mesh filter. */
float sharpen_smooth_ratio;
float *sharpen_factor;
- float (*accum_disp)[3];
/* unmasked nodes */
PBVHNode **nodes;
int totnode;
+ /* Cloth filter. */
+ SculptClothSimulation *cloth_sim;
+ float cloth_sim_pinch_point[3];
+
/* mask expand iteration caches */
int mask_update_current_it;
int mask_update_last_it;
@@ -884,6 +897,9 @@ void SCULPT_OT_set_pivot_position(struct wmOperatorType *ot);
/* Mesh Filter. */
void SCULPT_OT_mesh_filter(struct wmOperatorType *ot);
+/* Cloth Filter. */
+void SCULPT_OT_cloth_filter(struct wmOperatorType *ot);
+
/* Mask filter and Dirty Mask. */
void SCULPT_OT_mask_filter(struct wmOperatorType *ot);
void SCULPT_OT_dirty_mask(struct wmOperatorType *ot);
diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c
index c7511dfc80f..56ba15bef70 100644
--- a/source/blender/editors/sculpt_paint/sculpt_pose.c
+++ b/source/blender/editors/sculpt_paint/sculpt_pose.c
@@ -131,6 +131,32 @@ static void pose_solve_roll_chain(SculptPoseIKChain *ik_chain,
}
}
+static void pose_solve_translate_chain(SculptPoseIKChain *ik_chain, const float delta[3])
+{
+ SculptPoseIKChainSegment *segments = ik_chain->segments;
+ const int tot_segments = ik_chain->tot_segments;
+
+ for (int i = 0; i < tot_segments; i++) {
+ /* Move the origin and head of each segment by delta. */
+ add_v3_v3v3(segments[i].head, segments[i].initial_head, delta);
+ add_v3_v3v3(segments[i].orig, segments[i].initial_orig, delta);
+
+ /* Reset the segment rotation. */
+ unit_qt(segments[i].rot);
+ }
+}
+
+static void pose_solve_scale_chain(SculptPoseIKChain *ik_chain, const float scale)
+{
+ SculptPoseIKChainSegment *segments = ik_chain->segments;
+ const int tot_segments = ik_chain->tot_segments;
+
+ for (int i = 0; i < tot_segments; i++) {
+ /* Assign the scale to each segment. */
+ segments[i].scale = scale;
+ }
+}
+
static void do_pose_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict UNUSED(tls))
@@ -363,26 +389,43 @@ typedef struct PoseFloodFillData {
GSet *visited_face_sets;
/* In face sets origin mode, each vertex can only be assigned to one face set. */
- bool *is_weighted;
+ BLI_bitmap *is_weighted;
bool is_first_iteration;
+ /* In topology mode this stores the furthest point from the stroke origin for cases when a pose
+ * origin based on the brush radius can't be set. */
+ float fallback_floodfill_origin[3];
+
/* Fallback origin. If we can't find any face set to continue, use the position of all vertices
* that have the current face set. */
float fallback_origin[3];
int fallback_count;
+
+ /* Face Set FK mode. */
+ int *floodfill_it;
+ float *fk_weights;
+ int initial_face_set;
+ int masked_face_set_it;
+ int masked_face_set;
+ int target_face_set;
} PoseFloodFillData;
static bool pose_topology_floodfill_cb(
SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata)
{
PoseFloodFillData *data = userdata;
+ const float *co = SCULPT_vertex_co_get(ss, to_v);
if (data->pose_factor) {
data->pose_factor[to_v] = 1.0f;
}
- const float *co = SCULPT_vertex_co_get(ss, to_v);
+ if (len_squared_v3v3(data->pose_initial_co, data->fallback_floodfill_origin) <
+ len_squared_v3v3(data->pose_initial_co, co)) {
+ copy_v3_v3(data->fallback_floodfill_origin, co);
+ }
+
if (sculpt_pose_brush_is_vertex_inside_brush_radius(
co, data->pose_initial_co, data->radius, data->symm)) {
return true;
@@ -415,7 +458,7 @@ static bool pose_face_sets_floodfill_cb(
if (data->current_face_set == SCULPT_FACE_SET_NONE) {
data->pose_factor[index] = 1.0f;
- data->is_weighted[index] = true;
+ BLI_BITMAP_ENABLE(data->is_weighted, index);
if (sculpt_pose_brush_is_vertex_inside_brush_radius(
co, data->pose_initial_co, data->radius, data->symm)) {
@@ -446,9 +489,9 @@ static bool pose_face_sets_floodfill_cb(
if (is_vertex_valid) {
- if (!data->is_weighted[index]) {
+ if (!BLI_BITMAP_TEST(data->is_weighted, index)) {
data->pose_factor[index] = 1.0f;
- data->is_weighted[index] = true;
+ BLI_BITMAP_ENABLE(data->is_weighted, index);
visit_next = true;
}
@@ -521,12 +564,16 @@ void SCULPT_pose_calc_pose_data(Sculpt *sd,
};
zero_v3(fdata.pose_origin);
copy_v3_v3(fdata.pose_initial_co, initial_location);
+ copy_v3_v3(fdata.fallback_floodfill_origin, initial_location);
SCULPT_floodfill_execute(ss, &flood, pose_topology_floodfill_cb, &fdata);
SCULPT_floodfill_free(&flood);
if (fdata.tot_co > 0) {
mul_v3_fl(fdata.pose_origin, 1.0f / (float)fdata.tot_co);
}
+ else {
+ copy_v3_v3(fdata.pose_origin, fdata.fallback_floodfill_origin);
+ }
/* Offset the pose origin. */
float pose_d[3];
@@ -600,7 +647,19 @@ static void pose_ik_chain_origin_heads_init(SculptPoseIKChain *ik_chain,
copy_v3_v3(ik_chain->segments[i].initial_orig, origin);
copy_v3_v3(ik_chain->segments[i].initial_head, head);
ik_chain->segments[i].len = len_v3v3(head, origin);
+ ik_chain->segments[i].scale = 1.0f;
+ }
+}
+
+static int pose_brush_num_effective_segments(const Brush *brush)
+{
+ /* Scaling multiple segments at the same time is not supported as the IK solver can't handle
+ * changes in the segment's length. It will also required a better weight distribution to avoid
+ * artifacts in the areas affected by multiple segments. */
+ if (brush->pose_deform_type == BRUSH_POSE_DEFORM_SCALE_TRASLATE) {
+ return 1;
}
+ return brush->pose_ik_segments;
}
static SculptPoseIKChain *pose_ik_chain_init_topology(Sculpt *sd,
@@ -629,7 +688,8 @@ static SculptPoseIKChain *pose_ik_chain_init_topology(Sculpt *sd,
pose_factor_grow[nearest_vertex_index] = 1.0f;
- SculptPoseIKChain *ik_chain = pose_ik_chain_new(br->pose_ik_segments, totvert);
+ const int tot_segments = pose_brush_num_effective_segments(br);
+ SculptPoseIKChain *ik_chain = pose_ik_chain_new(tot_segments, totvert);
/* Calculate the first segment in the chain using the brush radius and the pose origin offset. */
copy_v3_v3(next_chain_segment_target, initial_location);
@@ -688,11 +748,13 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(
int totvert = SCULPT_vertex_count_get(ss);
- SculptPoseIKChain *ik_chain = pose_ik_chain_new(br->pose_ik_segments, totvert);
+ const int tot_segments = pose_brush_num_effective_segments(br);
+
+ SculptPoseIKChain *ik_chain = pose_ik_chain_new(tot_segments, totvert);
GSet *visited_face_sets = BLI_gset_int_new_ex("visited_face_sets", ik_chain->tot_segments);
- bool *is_weighted = MEM_callocN(sizeof(bool) * totvert, "weighted");
+ BLI_bitmap *is_weighted = BLI_BITMAP_NEW(totvert, "weighted");
int current_face_set = SCULPT_FACE_SET_NONE;
int prev_face_set = SCULPT_FACE_SET_NONE;
@@ -752,6 +814,119 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(
return ik_chain;
}
+static bool pose_face_sets_fk_find_masked_floodfill_cb(
+ SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
+{
+ PoseFloodFillData *data = userdata;
+
+ if (!is_duplicate) {
+ data->floodfill_it[to_v] = data->floodfill_it[from_v] + 1;
+ }
+ else {
+ data->floodfill_it[to_v] = data->floodfill_it[from_v];
+ }
+
+ const int to_face_set = SCULPT_vertex_face_set_get(ss, to_v);
+ if (SCULPT_vertex_has_unique_face_set(ss, to_v) &&
+ !SCULPT_vertex_has_unique_face_set(ss, from_v) &&
+ SCULPT_vertex_has_face_set(ss, from_v, to_face_set)) {
+
+ if (data->floodfill_it[to_v] > data->masked_face_set_it) {
+ data->masked_face_set = to_face_set;
+ data->masked_face_set_it = data->floodfill_it[to_v];
+ }
+
+ if (data->target_face_set == SCULPT_FACE_SET_NONE) {
+ data->target_face_set = to_face_set;
+ }
+ }
+
+ return SCULPT_vertex_has_face_set(ss, to_v, data->initial_face_set);
+}
+
+static bool pose_face_sets_fk_set_weights_floodfill_cb(
+ SculptSession *ss, int UNUSED(from_v), int to_v, bool UNUSED(is_duplicate), void *userdata)
+{
+ PoseFloodFillData *data = userdata;
+ data->fk_weights[to_v] = 1.0f;
+ return !SCULPT_vertex_has_face_set(ss, to_v, data->masked_face_set);
+}
+
+static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(
+ Sculpt *sd, Object *ob, SculptSession *ss, const float radius, const float *initial_location)
+{
+ const int totvert = SCULPT_vertex_count_get(ss);
+
+ SculptPoseIKChain *ik_chain = pose_ik_chain_new(1, totvert);
+
+ const int active_vertex = SCULPT_active_vertex_get(ss);
+ const int active_face_set = SCULPT_active_face_set_get(ss);
+
+ SculptFloodFill flood;
+ SCULPT_floodfill_init(ss, &flood);
+ SCULPT_floodfill_add_initial(&flood, active_vertex);
+ PoseFloodFillData fdata;
+ fdata.floodfill_it = MEM_calloc_arrayN(totvert, sizeof(int), "floodfill iteration");
+ fdata.floodfill_it[active_vertex] = 1;
+ fdata.initial_face_set = active_face_set;
+ fdata.masked_face_set = SCULPT_FACE_SET_NONE;
+ fdata.target_face_set = SCULPT_FACE_SET_NONE;
+ fdata.masked_face_set_it = 0;
+ SCULPT_floodfill_execute(ss, &flood, pose_face_sets_fk_find_masked_floodfill_cb, &fdata);
+ SCULPT_floodfill_free(&flood);
+
+ int origin_count = 0;
+ float origin_acc[3] = {0.0f};
+ for (int i = 0; i < totvert; i++) {
+ if (fdata.floodfill_it[i] != 0 && SCULPT_vertex_has_face_set(ss, i, fdata.initial_face_set) &&
+ SCULPT_vertex_has_face_set(ss, i, fdata.masked_face_set)) {
+ add_v3_v3(origin_acc, SCULPT_vertex_co_get(ss, i));
+ origin_count++;
+ }
+ }
+
+ int target_count = 0;
+ float target_acc[3] = {0.0f};
+ if (fdata.target_face_set != fdata.masked_face_set) {
+ for (int i = 0; i < totvert; i++) {
+ if (fdata.floodfill_it[i] != 0 &&
+ SCULPT_vertex_has_face_set(ss, i, fdata.initial_face_set) &&
+ SCULPT_vertex_has_face_set(ss, i, fdata.target_face_set)) {
+ add_v3_v3(target_acc, SCULPT_vertex_co_get(ss, i));
+ target_count++;
+ }
+ }
+ }
+
+ MEM_freeN(fdata.floodfill_it);
+
+ if (origin_count > 0) {
+ copy_v3_v3(ik_chain->segments[0].orig, origin_acc);
+ mul_v3_fl(ik_chain->segments[0].orig, 1.0f / origin_count);
+ }
+ else {
+ zero_v3(ik_chain->segments[0].orig);
+ }
+
+ if (target_count > 0) {
+ copy_v3_v3(ik_chain->segments[0].head, target_acc);
+ mul_v3_fl(ik_chain->segments[0].head, 1.0f / target_count);
+ sub_v3_v3v3(ik_chain->grab_delta_offset, ik_chain->segments[0].head, initial_location);
+ }
+ else {
+ copy_v3_v3(ik_chain->segments[0].head, initial_location);
+ }
+
+ SCULPT_floodfill_init(ss, &flood);
+ SCULPT_floodfill_add_active(sd, ob, ss, &flood, radius);
+ fdata.fk_weights = ik_chain->segments[0].weights;
+ SCULPT_floodfill_execute(ss, &flood, pose_face_sets_fk_set_weights_floodfill_cb, &fdata);
+ SCULPT_floodfill_free(&flood);
+
+ pose_ik_chain_origin_heads_init(ik_chain, ik_chain->segments[0].head);
+ return ik_chain;
+}
+
SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd,
Object *ob,
SculptSession *ss,
@@ -766,6 +941,9 @@ SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd,
case BRUSH_POSE_ORIGIN_FACE_SETS:
return pose_ik_chain_init_face_sets(sd, ob, ss, br, radius);
break;
+ case BRUSH_POSE_ORIGIN_FACE_SETS_FK:
+ return pose_ik_chain_init_face_sets_fk(sd, ob, ss, radius, initial_location);
+ break;
}
return NULL;
}
@@ -802,13 +980,86 @@ void SCULPT_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br
MEM_SAFE_FREE(nodes);
}
+static void sculpt_pose_do_translate_deform(SculptSession *ss, Brush *brush)
+{
+ SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
+ BKE_curvemapping_initialize(brush->curve);
+ pose_solve_translate_chain(ik_chain, ss->cache->grab_delta);
+}
+
+static void sculpt_pose_do_scale_deform(SculptSession *ss, Brush *brush)
+{
+ float ik_target[3];
+ SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
+
+ copy_v3_v3(ik_target, ss->cache->true_location);
+ add_v3_v3(ik_target, ss->cache->grab_delta);
+
+ /* Solve the IK for the first segment to include rotation as part of scale. */
+ pose_solve_ik_chain(ik_chain, ik_target, brush->flag2 & BRUSH_POSE_IK_ANCHORED);
+
+ /* Calculate a scale factor based on the grab delta. */
+ float plane[4];
+ float segment_dir[3];
+ sub_v3_v3v3(segment_dir, ik_chain->segments[0].initial_head, ik_chain->segments[0].initial_orig);
+ normalize_v3(segment_dir);
+ plane_from_point_normal_v3(plane, ik_chain->segments[0].initial_head, segment_dir);
+ const float segment_len = ik_chain->segments[0].len;
+ const float scale = segment_len / (segment_len - dist_signed_to_plane_v3(ik_target, plane));
+
+ /* Write the scale into the segments. */
+ pose_solve_scale_chain(ik_chain, scale);
+}
+
+static void sculpt_pose_do_twist_deform(SculptSession *ss, Brush *brush)
+{
+ SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
+
+ /* Calculate the maximum roll. 0.02 radians per pixel works fine. */
+ float roll = (ss->cache->initial_mouse[0] - ss->cache->mouse[0]) * ss->cache->bstrength * 0.02f;
+ BKE_curvemapping_initialize(brush->curve);
+ pose_solve_roll_chain(ik_chain, brush, roll);
+}
+
+static void sculpt_pose_do_rotate_deform(SculptSession *ss, Brush *brush)
+{
+ float ik_target[3];
+ SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
+
+ /* Calculate the IK target. */
+ copy_v3_v3(ik_target, ss->cache->true_location);
+ add_v3_v3(ik_target, ss->cache->grab_delta);
+ add_v3_v3(ik_target, ik_chain->grab_delta_offset);
+
+ /* Solve the IK positions. */
+ pose_solve_ik_chain(ik_chain, ik_target, brush->flag2 & BRUSH_POSE_IK_ANCHORED);
+}
+
+static void sculpt_pose_do_rotate_twist_deform(SculptSession *ss, Brush *brush)
+{
+ if (ss->cache->invert) {
+ sculpt_pose_do_twist_deform(ss, brush);
+ }
+ else {
+ sculpt_pose_do_rotate_deform(ss, brush);
+ }
+}
+
+static void sculpt_pose_do_scale_translate_deform(SculptSession *ss, Brush *brush)
+{
+ if (ss->cache->invert) {
+ sculpt_pose_do_translate_deform(ss, brush);
+ }
+ else {
+ sculpt_pose_do_scale_deform(ss, brush);
+ }
+}
+
/* Main Brush Function. */
void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- float grab_delta[3];
- float ik_target[3];
const ePaintSymmetryFlags symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
/* The pose brush applies all enabled symmetry axis in a single iteration, so the rest can be
@@ -819,25 +1070,13 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
- /* Solve the positions and rotations of the IK chain. */
- if (ss->cache->invert) {
- /* Roll Mode. */
- /* Calculate the maximum roll. 0.02 radians per pixel works fine. */
- float roll = (ss->cache->initial_mouse[0] - ss->cache->mouse[0]) * ss->cache->bstrength *
- 0.02f;
- BKE_curvemapping_initialize(brush->curve);
- pose_solve_roll_chain(ik_chain, brush, roll);
- }
- else {
- /* IK follow target mode. */
- /* Calculate the IK target. */
-
- copy_v3_v3(grab_delta, ss->cache->grab_delta);
- copy_v3_v3(ik_target, ss->cache->true_location);
- add_v3_v3(ik_target, ss->cache->grab_delta);
-
- /* Solve the IK positions. */
- pose_solve_ik_chain(ik_chain, ik_target, brush->flag2 & BRUSH_POSE_IK_ANCHORED);
+ switch (brush->pose_deform_type) {
+ case BRUSH_POSE_DEFORM_ROTATE_TWIST:
+ sculpt_pose_do_rotate_twist_deform(ss, brush);
+ break;
+ case BRUSH_POSE_DEFORM_SCALE_TRASLATE:
+ sculpt_pose_do_scale_translate_deform(ss, brush);
+ break;
}
/* Flip the segment chain in all symmetry axis and calculate the transform matrices for each
@@ -845,7 +1084,7 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
/* This can be optimized by skipping the calculation of matrices where the symmetry is not
* enabled. */
for (int symm_it = 0; symm_it < PAINT_SYMM_AREAS; symm_it++) {
- for (int i = 0; i < brush->pose_ik_segments; i++) {
+ for (int i = 0; i < ik_chain->tot_segments; i++) {
float symm_rot[4];
float symm_orig[3];
float symm_initial_orig[3];
@@ -865,6 +1104,7 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
/* Create the transform matrix and store it in the segment. */
unit_m4(ik_chain->segments[i].pivot_mat[symm_it]);
quat_to_mat4(ik_chain->segments[i].trans_mat[symm_it], symm_rot);
+ mul_m4_fl(ik_chain->segments[i].trans_mat[symm_it], ik_chain->segments[i].scale);
translate_m4(ik_chain->segments[i].trans_mat[symm_it],
symm_orig[0] - symm_initial_orig[0],
@@ -882,7 +1122,6 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.ob = ob,
.brush = brush,
.nodes = nodes,
- .grab_delta = grab_delta,
};
TaskParallelSettings settings;
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 4a449e529d5..d21552efafe 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -1570,7 +1570,7 @@ static void sculpt_undo_push_all_grids(Object *object)
/* It is possible that undo push is done from an object state where there is no PBVH. This
* happens, for example, when an operation which tagged for geometry update was performed prior
- * to the current operation without making any stroke inbetween.
+ * to the current operation without making any stroke in between.
*
* Skip pushing nodes based on the following logic: on redo SCULPT_UNDO_COORDS will ensure
* PBVH for the new base geometry, which will have same coordinates as if we create PBVH here. */
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index a1094dde749..d6b259c9ac0 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -548,8 +548,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
if (do_island_optimization) {
UvElement *element;
UvNearestHit hit = UV_NEAREST_HIT_INIT;
- Image *ima = CTX_data_edit_image(C);
- uv_find_nearest_vert(scene, ima, obedit, co, 0.0f, &hit);
+ uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit);
element = BM_uv_element_get(data->elementMap, hit.efa, hit.l);
island_index = element->island;
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index e90122f2585..b390e4b56d6 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -218,7 +218,7 @@ static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const
float tmin, tmax;
/* get range and apply necessary scaling before processing */
- if (calc_fcurve_range(fcu, &tmin, &tmax, onlySel, false)) {
+ if (BKE_fcurve_calc_range(fcu, &tmin, &tmax, onlySel, false)) {
if (adt) {
tmin = BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
@@ -490,7 +490,7 @@ void ACTION_OT_view_frame(wmOperatorType *ot)
/* identifiers */
ot->name = "Go to Current Frame";
ot->idname = "ACTION_OT_view_frame";
- ot->description = "Move the view to the playhead";
+ ot->description = "Move the view to the current frame";
/* api callbacks */
ot->exec = actkeys_view_frame_exec;
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index f81aaeb0ee4..e084d5fcdf2 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -135,6 +135,7 @@ void ED_spacetypes_init(void)
ED_gizmotypes_blank_3d();
ED_gizmotypes_cage_2d();
ED_gizmotypes_cage_3d();
+ ED_gizmotypes_snap_3d();
/* register types for operators and gizmos */
spacetypes = BKE_spacetypes_list();
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 6b7f86a9143..3dc5eca8a8b 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -373,7 +373,7 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)
/* set user as active */
if (user->node) {
- ED_node_set_active(CTX_data_main(C), user->ntree, user->node);
+ ED_node_set_active(CTX_data_main(C), user->ntree, user->node, NULL);
ct->texture = NULL;
}
else {
@@ -545,7 +545,7 @@ static void template_texture_show(bContext *C, void *data_p, void *prop_p)
}
}
-void uiTemplateTextureShow(uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop)
+void uiTemplateTextureShow(uiLayout *layout, const bContext *C, PointerRNA *ptr, PropertyRNA *prop)
{
/* button to quickly show texture in texture tab */
SpaceProperties *sbuts = CTX_wm_space_properties(C);
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index e3f7cffc8ed..5ab3304c0e6 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -30,7 +30,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_gpencil_modifier.h" /* Types for regiestering panels. */
+#include "BKE_gpencil_modifier.h" /* Types for registering panels. */
#include "BKE_modifier.h"
#include "BKE_screen.h"
#include "BKE_shader_fx.h"
@@ -39,6 +39,8 @@
#include "DNA_modifier_types.h"
#include "DNA_shader_fx_types.h"
+#include "DNA_modifier_types.h"
+
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_view3d.h" /* To draw toolbar UI. */
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
index 6b741363d42..805e9608fec 100644
--- a/source/blender/editors/space_console/console_draw.c
+++ b/source/blender/editors/space_console/console_draw.c
@@ -142,10 +142,7 @@ static void console_cursor_wrap_offset(
return;
}
-static void console_textview_draw_cursor(TextViewContext *tvc,
- int cwidth,
- int columns,
- int descender)
+static void console_textview_draw_cursor(TextViewContext *tvc, int cwidth, int columns)
{
int pen[2];
{
@@ -171,8 +168,7 @@ static void console_textview_draw_cursor(TextViewContext *tvc,
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_CONSOLE_CURSOR);
- immRectf(
- pos, pen[0] - U.pixelsize, pen[1], pen[0] + U.pixelsize, pen[1] + tvc->lheight + descender);
+ immRectf(pos, pen[0] - U.pixelsize, pen[1], pen[0] + U.pixelsize, pen[1] + tvc->lheight);
immUnbindProgram();
}
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 226e7ae6b22..8d14664c0fa 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -220,7 +220,8 @@ static void file_draw_preview(uiBlock *block,
const bool is_icon,
const int typeflags,
const bool drag,
- const bool dimmed)
+ const bool dimmed,
+ const bool is_link)
{
uiBut *but;
float fx, fy;
@@ -312,37 +313,57 @@ static void file_draw_preview(uiBlock *block,
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- if (icon && !(typeflags & FILE_TYPE_FTFONT)) {
- /* size of center icon is scaled to fit container and UI scale */
+ if (icon && is_icon) {
+ /* Small icon in the middle of large image, scaled to fit container and UI scale */
float icon_x, icon_y;
-
- if (is_icon) {
- const float icon_size = 16.0f / icon_aspect * U.dpi_fac;
- float icon_opacity = 0.3f;
- uchar icon_color[4] = {0, 0, 0, 255};
- float bgcolor[4];
- UI_GetThemeColor4fv(TH_ICON_FOLDER, bgcolor);
- if (rgb_to_grayscale(bgcolor) < 0.5f) {
- icon_color[0] = 255;
- icon_color[1] = 255;
- icon_color[2] = 255;
- }
- icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f);
- icon_y = yco + (ey / 2.0f) - (icon_size * ((typeflags & FILE_TYPE_DIR) ? 0.78f : 0.75f));
- UI_icon_draw_ex(
- icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
+ const float icon_size = 16.0f / icon_aspect * U.dpi_fac;
+ float icon_opacity = 0.3f;
+ uchar icon_color[4] = {0, 0, 0, 255};
+ float bgcolor[4];
+ UI_GetThemeColor4fv(TH_ICON_FOLDER, bgcolor);
+ if (rgb_to_grayscale(bgcolor) < 0.5f) {
+ icon_color[0] = 255;
+ icon_color[1] = 255;
+ icon_color[2] = 255;
}
- else {
+ icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f);
+ icon_y = yco + (ey / 2.0f) - (icon_size * ((typeflags & FILE_TYPE_DIR) ? 0.78f : 0.75f));
+ UI_icon_draw_ex(
+ icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
+ }
+
+ if (is_link) {
+ /* Arrow icon to indicate it is a shortcut, link, or alias. */
+ float icon_x, icon_y;
+ icon_x = xco + (2.0f * UI_DPI_FAC);
+ icon_y = yco + (2.0f * UI_DPI_FAC);
+ const int arrow = ICON_LOOP_FORWARDS;
+ if (!is_icon) {
+ /* Arrow at very bottom-left if preview style. */
const uchar dark[4] = {0, 0, 0, 255};
const uchar light[4] = {255, 255, 255, 255};
-
- /* Smaller, fainter icon for preview image thumbnail. */
- icon_x = xco + (2.0f * UI_DPI_FAC);
- icon_y = yco + (2.0f * UI_DPI_FAC);
-
- UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
- UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ UI_icon_draw_ex(icon_x + 1, icon_y - 1, arrow, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
+ UI_icon_draw_ex(icon_x, icon_y, arrow, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
}
+ else {
+ /* Link to folder or non-previewed file. */
+ uchar icon_color[4];
+ UI_GetThemeColor4ubv(TH_BACK, icon_color);
+ icon_x = xco + ((typeflags & FILE_TYPE_DIR) ? 0.14f : 0.23f) * scaledx;
+ icon_y = yco + ((typeflags & FILE_TYPE_DIR) ? 0.24f : 0.14f) * scaledy;
+ UI_icon_draw_ex(
+ icon_x, icon_y, arrow, icon_aspect / U.dpi_fac * 1.8, 0.3f, 0.0f, icon_color, false);
+ }
+ }
+ else if (icon && !is_icon && !(typeflags & FILE_TYPE_FTFONT)) {
+ /* Smaller, fainter icon at bottom-left for preview image thumbnail, but not for fonts. */
+ float icon_x, icon_y;
+ const uchar dark[4] = {0, 0, 0, 255};
+ const uchar light[4] = {255, 255, 255, 255};
+ icon_x = xco + (2.0f * UI_DPI_FAC);
+ icon_y = yco + (2.0f * UI_DPI_FAC);
+ UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
+ UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
}
/* Contrasting outline around some preview types. */
@@ -788,6 +809,7 @@ void file_draw_list(const bContext *C, ARegion *region)
/* don't drag parent or refresh items */
do_drag = !(FILENAME_IS_CURRPAR(file->relpath));
const bool is_hidden = (file->attributes & FILE_ATTR_HIDDEN);
+ const bool is_link = (file->attributes & FILE_ATTR_ANY_LINK);
if (FILE_IMGDISPLAY == params->display) {
const int icon = filelist_geticon(files, i, false);
@@ -809,7 +831,8 @@ void file_draw_list(const bContext *C, ARegion *region)
is_icon,
file->typeflag,
do_drag,
- is_hidden);
+ is_hidden,
+ is_link);
}
else {
file_draw_icon(block,
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index a5263378850..41d32fda088 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -1469,9 +1469,12 @@ void file_sfile_to_operator_ex(bContext *C, wmOperator *op, SpaceFile *sfile, ch
for (i = 0; i < numfiles; i++) {
if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
FileDirEntry *file = filelist_file(sfile->files, i);
- RNA_property_collection_add(op->ptr, prop, &itemptr);
- RNA_string_set(&itemptr, "name", file->relpath);
- num_files++;
+ /* Cannot (currently) mix regular items and alias/shortcuts in multiple selection. */
+ if (!file->redirection_path) {
+ RNA_property_collection_add(op->ptr, prop, &itemptr);
+ RNA_string_set(&itemptr, "name", file->relpath);
+ num_files++;
+ }
}
}
/* make sure the file specified in the filename button is added even if no
@@ -1617,9 +1620,23 @@ static int file_exec(bContext *C, wmOperator *exec_op)
Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
- const struct FileDirEntry *file = filelist_file(sfile->files, sfile->params->active_file);
+ struct FileDirEntry *file = filelist_file(sfile->files, sfile->params->active_file);
char filepath[FILE_MAX];
+ if (file && file->redirection_path) {
+ /* redirection_path is an absolute path that takes precedence
+ * over using sfile->params->dir + sfile->params->file. */
+ BLI_split_dirfile(file->redirection_path,
+ sfile->params->dir,
+ sfile->params->file,
+ sizeof(sfile->params->dir),
+ sizeof(sfile->params->file));
+ /* Update relpath with redirected filename as well so that the alternative
+ * combination of sfile->params->dir + relpath remains valid as well. */
+ MEM_freeN(file->relpath);
+ file->relpath = BLI_strdup(sfile->params->file);
+ }
+
/* directory change */
if (file && (file->typeflag & FILE_TYPE_DIR)) {
if (!file->relpath) {
@@ -1634,9 +1651,6 @@ static int file_exec(bContext *C, wmOperator *exec_op)
BLI_path_append(sfile->params->dir, sizeof(sfile->params->dir) - 1, file->relpath);
BLI_path_slash_ensure(sfile->params->dir);
}
- if (file->redirection_path) {
- STRNCPY(sfile->params->dir, file->redirection_path);
- }
ED_file_change_dir(C);
}
/* opening file - sends events now, so things get handled on windowqueue level */
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 7f6d0658ec8..d8d7ef01a2e 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -1015,6 +1015,7 @@ static int filelist_geticon_ex(FileDirEntry *file,
/* If this path is in System list or path cache then use that icon. */
struct FSMenu *fsmenu = ED_fsmenu_get();
FSMenuCategory categories[] = {
+ FS_CATEGORY_SYSTEM,
FS_CATEGORY_SYSTEM_BOOKMARKS,
FS_CATEGORY_OTHER,
};
@@ -1022,10 +1023,16 @@ static int filelist_geticon_ex(FileDirEntry *file,
for (int i = 0; i < ARRAY_SIZE(categories); i++) {
FSMenuEntry *tfsm = ED_fsmenu_get_category(fsmenu, categories[i]);
char fullpath[FILE_MAX_LIBEXTRA];
- BLI_join_dirfile(fullpath, sizeof(fullpath), root, file->relpath);
- BLI_path_slash_ensure(fullpath);
+ char *target = fullpath;
+ if (file->redirection_path) {
+ target = file->redirection_path;
+ }
+ else {
+ BLI_join_dirfile(fullpath, sizeof(fullpath), root, file->relpath);
+ BLI_path_slash_ensure(fullpath);
+ }
for (; tfsm; tfsm = tfsm->next) {
- if (STREQ(tfsm->path, fullpath)) {
+ if (STREQ(tfsm->path, target)) {
/* Never want a little folder inside a large one. */
return (tfsm->icon == ICON_FILE_FOLDER) ? ICON_NONE : tfsm->icon;
}
@@ -1033,10 +1040,7 @@ static int filelist_geticon_ex(FileDirEntry *file,
}
}
- if (file->attributes & FILE_ATTR_ANY_LINK) {
- return ICON_LOOP_FORWARDS;
- }
- else if (file->attributes & FILE_ATTR_OFFLINE) {
+ if (file->attributes & FILE_ATTR_OFFLINE) {
return ICON_ERROR;
}
else if (file->attributes & FILE_ATTR_TEMPORARY) {
@@ -1375,8 +1379,15 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
(entry->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT |
FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB))) {
FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__);
- BLI_join_dirfile(
- preview->path, sizeof(preview->path), filelist->filelist.root, entry->relpath);
+
+ if (entry->redirection_path) {
+ BLI_strncpy(preview->path, entry->redirection_path, FILE_MAXDIR);
+ }
+ else {
+ BLI_join_dirfile(
+ preview->path, sizeof(preview->path), filelist->filelist.root, entry->relpath);
+ }
+
preview->index = index;
preview->flags = entry->typeflag;
preview->img = NULL;
@@ -2270,13 +2281,6 @@ int ED_path_extension_type(const char *path)
return 0;
}
-static int file_extension_type(const char *dir, const char *relpath)
-{
- char path[FILE_MAX];
- BLI_join_dirfile(path, sizeof(path), dir, relpath);
- return ED_path_extension_type(path);
-}
-
int ED_file_extension_icon(const char *path)
{
const int type = ED_path_extension_type(path);
@@ -2475,7 +2479,8 @@ static int filelist_readjob_list_dir(const char *root,
{
struct direntry *files;
int nbr_files, nbr_entries = 0;
- char path[FILE_MAX];
+ /* Full path of the item. */
+ char full_path[FILE_MAX];
nbr_files = BLI_filelist_dir_contents(root, &files);
if (files) {
@@ -2491,38 +2496,53 @@ static int filelist_readjob_list_dir(const char *root,
entry->relpath = MEM_dupallocN(files[i].relname);
entry->st = files[i].s;
- BLI_join_dirfile(path, sizeof(path), root, entry->relpath);
+ BLI_join_dirfile(full_path, FILE_MAX, root, entry->relpath);
+ char *target = full_path;
- /* Set file type. */
+ /* Set initial file type and attributes. */
+ entry->attributes = BLI_file_attributes(full_path);
if (S_ISDIR(files[i].s.st_mode)) {
entry->typeflag = FILE_TYPE_DIR;
}
- else if (do_lib && BLO_has_bfile_extension(entry->relpath)) {
- /* If we are considering .blend files as libs, promote them to directory status. */
- entry->typeflag = FILE_TYPE_BLENDER;
- /* prevent current file being used as acceptable dir */
- if (BLI_path_cmp(main_name, path) != 0) {
- entry->typeflag |= FILE_TYPE_DIR;
- }
- }
- /* Otherwise, do not check extensions for directories! */
- else if (!(entry->typeflag & FILE_TYPE_DIR)) {
- entry->typeflag = file_extension_type(root, entry->relpath);
- if (filter_glob[0] && BLI_path_extension_check_glob(entry->relpath, filter_glob)) {
- entry->typeflag |= FILE_TYPE_OPERATOR;
- }
- }
- /* Set file attributes. */
- entry->attributes = BLI_file_attributes(path);
+ /* Is this a file that points to another file? */
if (entry->attributes & FILE_ATTR_ALIAS) {
entry->redirection_path = MEM_callocN(FILE_MAXDIR, __func__);
- if (BLI_file_alias_target(entry->redirection_path, path)) {
+ if (BLI_file_alias_target(entry->redirection_path, full_path)) {
if (BLI_is_dir(entry->redirection_path)) {
entry->typeflag = FILE_TYPE_DIR;
+ BLI_path_slash_ensure(entry->redirection_path);
}
- else
+ else {
entry->typeflag = ED_path_extension_type(entry->redirection_path);
+ }
+ target = entry->redirection_path;
+#ifdef WIN32
+ /* On Windows don't show ".lnk" extension for valid shortcuts. */
+ BLI_path_extension_replace(entry->relpath, FILE_MAXDIR, "");
+#endif
+ }
+ else {
+ MEM_freeN(entry->redirection_path);
+ entry->redirection_path = NULL;
+ entry->attributes |= FILE_ATTR_HIDDEN;
+ }
+ }
+
+ if (!(entry->typeflag & FILE_TYPE_DIR)) {
+ if (do_lib && BLO_has_bfile_extension(target)) {
+ /* If we are considering .blend files as libs, promote them to directory status. */
+ entry->typeflag = FILE_TYPE_BLENDER;
+ /* prevent current file being used as acceptable dir */
+ if (BLI_path_cmp(main_name, target) != 0) {
+ entry->typeflag |= FILE_TYPE_DIR;
+ }
+ }
+ else {
+ entry->typeflag = ED_path_extension_type(target);
+ if (filter_glob[0] && BLI_path_extension_check_glob(target, filter_glob)) {
+ entry->typeflag |= FILE_TYPE_OPERATOR;
+ }
}
}
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index 66157296064..b03df01a02b 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -418,7 +418,7 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu,
else {
/* if we're bookmarking this, file should come
* before the last separator, only automatically added
- * current dir go after the last sep. */
+ * current dir go after the last separator. */
if (flag & FS_INSERT_SAVE) {
break;
}
@@ -848,6 +848,10 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
CFRelease(volEnum);
+ /* kLSSharedFileListFavoriteItems is deprecated, but available till macOS 10.15.
+ * Will have to find a new method to sync the Finder Favorites with File Browser. */
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
/* Finally get user favorite places */
if (read_bookmarks) {
UInt32 seed;
@@ -891,6 +895,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
CFRelease(pathesArray);
CFRelease(list);
}
+# pragma GCC diagnostic pop
}
# else
/* unix */
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 185bf029f1a..179d73a38ba 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -1284,7 +1284,7 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *panel)
FCurve *fcu;
bool driven, special;
- fcu = rna_get_fcurve_context_ui(
+ fcu = BKE_fcurve_find_by_rna_context_ui(
(bContext *)C, &ptr, prop, index, NULL, NULL, &driven, &special);
/* Hack: Force all buttons in this panel to be able to know the driver button
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 68fef5e921f..f2071d292ca 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -1159,7 +1159,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, shor
* we must obey this.
*/
if (!(sipo->flag & SIPO_SELCUVERTSONLY) || (fcu->flag & FCURVE_SELECTED)) {
- if (!fcurve_are_keyframes_usable(fcu) && !(fcu->fpt && fcu->totvert)) {
+ if (!BKE_fcurve_are_keyframes_usable(fcu) && !(fcu->fpt && fcu->totvert)) {
/* only draw controls if this is the active modifier */
if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) {
switch (fcm->type) {
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 8ffd2844f1a..03151da8d4d 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -126,7 +126,8 @@ void get_graph_keyframe_extents(bAnimContext *ac,
float unitFac, offset;
/* get range */
- if (calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles)) {
+ if (BKE_fcurve_calc_bounds(
+ fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles)) {
short mapping_flag = ANIM_get_normalization_flags(ac);
/* apply NLA scaling */
@@ -385,7 +386,7 @@ void GRAPH_OT_view_frame(wmOperatorType *ot)
/* identifiers */
ot->name = "Go to Current Frame";
ot->idname = "GRAPH_OT_view_frame";
- ot->description = "Move the view to the playhead";
+ ot->description = "Move the view to the current frame";
/* api callbacks */
ot->exec = graphkeys_view_frame_exec;
@@ -409,7 +410,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end)
int filter;
/* free existing ghost curves */
- free_fcurves(&sipo->runtime.ghost_curves);
+ BKE_fcurves_free(&sipo->runtime.ghost_curves);
/* sanity check */
if (start >= end) {
@@ -425,7 +426,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end)
/* loop through filtered data and add keys between selected keyframes on every frame */
for (ale = anim_data.first; ale; ale = ale->next) {
FCurve *fcu = (FCurve *)ale->key_data;
- FCurve *gcu = MEM_callocN(sizeof(FCurve), "Ghost FCurve");
+ FCurve *gcu = BKE_fcurve_create();
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
ChannelDriver *driver = fcu->driver;
FPoint *fpt;
@@ -536,7 +537,7 @@ static int graphkeys_clear_ghostcurves_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
/* free ghost curves */
- free_fcurves(&sipo->runtime.ghost_curves);
+ BKE_fcurves_free(&sipo->runtime.ghost_curves);
/* update this editor only */
ED_area_tag_redraw(CTX_wm_area(C));
@@ -806,7 +807,7 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
/* when there are F-Modifiers on the curve, only allow adding
* keyframes if these will be visible after doing so...
*/
- if (fcurve_is_keyframable(fcu)) {
+ if (BKE_fcurve_is_keyframable(fcu)) {
ListBase anim_data;
ToolSettings *ts = ac.scene->toolsettings;
diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c
index 575cba07f04..03ed8870d67 100644
--- a/source/blender/editors/space_graph/graph_utils.c
+++ b/source/blender/editors/space_graph/graph_utils.c
@@ -171,7 +171,7 @@ bool graphop_visible_keyframes_poll(bContext *C)
if (fcu->bezt == NULL) {
continue;
}
- if (fcurve_are_keyframes_usable(fcu)) {
+ if (BKE_fcurve_are_keyframes_usable(fcu)) {
found = 1;
break;
}
@@ -225,7 +225,7 @@ bool graphop_editable_keyframes_poll(bContext *C)
if (fcu->bezt == NULL) {
continue;
}
- if (fcurve_is_keyframable(fcu)) {
+ if (BKE_fcurve_is_keyframable(fcu)) {
found = 1;
break;
}
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index bd82b8ecf2e..b9c7c529620 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -145,7 +145,7 @@ static void graph_free(SpaceLink *sl)
}
if (si->runtime.ghost_curves.first) {
- free_fcurves(&si->runtime.ghost_curves);
+ BKE_fcurves_free(&si->runtime.ghost_curves);
}
}
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 6037c1d2ec8..9040ca5e79c 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -476,7 +476,7 @@ static void sima_draw_zbuf_pixels(
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
immDrawPixelsTex(
&state, x1, y1, rectx, recty, GL_RED, GL_INT, GL_NEAREST, recti, zoomx, zoomy, NULL);
@@ -524,7 +524,7 @@ static void sima_draw_zbuffloat_pixels(Scene *scene,
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
immDrawPixelsTex(
&state, x1, y1, rectx, recty, GL_RED, GL_FLOAT, GL_NEAREST, rectf, zoomx, zoomy, NULL);
@@ -637,7 +637,7 @@ static void draw_image_buffer(const bContext *C,
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle);
IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
display_buffer = IMB_display_buffer_acquire(
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index eb97077f77a..8cb85ce9800 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -885,7 +885,6 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene;
ViewLayer *view_layer;
Object *obedit;
- Image *ima;
/* retrieve state */
sima = CTX_wm_space_image(C);
@@ -894,15 +893,13 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
view_layer = CTX_data_view_layer(C);
obedit = CTX_data_edit_object(C);
- ima = ED_space_image(sima);
-
/* get bounds */
float min[2], max[2];
if (ED_space_image_show_uvedit(sima, obedit)) {
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
view_layer, ((View3D *)NULL), &objects_len);
- bool success = ED_uvedit_minmax_multi(scene, ima, objects, objects_len, min, max);
+ bool success = ED_uvedit_minmax_multi(scene, objects, objects_len, min, max);
MEM_freeN(objects);
if (!success) {
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c
index 5668b88826e..e0c44c3a0ba 100644
--- a/source/blender/editors/space_image/image_undo.c
+++ b/source/blender/editors/space_image/image_undo.c
@@ -958,7 +958,7 @@ static void image_undosys_step_decode(
}
if (us->paint_mode == PAINT_MODE_TEXTURE_3D) {
- ED_object_mode_set(C, OB_MODE_TEXTURE_PAINT);
+ ED_object_mode_set_ex(C, OB_MODE_TEXTURE_PAINT, false, NULL);
}
/* Refresh texture slots. */
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index dbd3b65857a..e1937dffb37 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -438,7 +438,7 @@ static const char *footer_string(ViewLayer *view_layer)
"%s%s | %s",
memstr,
gpumemstr,
- versionstr);
+ BKE_blender_version_string());
return view_layer->footer_str;
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index 5d5c41597b4..8076d3d7eaf 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -408,7 +408,7 @@ int textview_draw(TextViewContext *tvc,
if (do_draw) {
/* We always want the cursor to draw. */
if (tvc->draw_cursor && iter_index == 0) {
- tvc->draw_cursor(tvc, tds.cwidth, tds.columns, tds.lofs);
+ tvc->draw_cursor(tvc, tds.cwidth, tds.columns);
}
/* When drawing, if we pass v2d->cur.ymax, then quit. */
diff --git a/source/blender/editors/space_info/textview.h b/source/blender/editors/space_info/textview.h
index 8eef4ef5d56..41f8baf634e 100644
--- a/source/blender/editors/space_info/textview.h
+++ b/source/blender/editors/space_info/textview.h
@@ -60,7 +60,7 @@ typedef struct TextViewContext {
int *r_icon,
uchar r_icon_fg[4],
uchar r_icon_bg[4]);
- void (*draw_cursor)(struct TextViewContext *tvc, int cwidth, int columns, int descender);
+ void (*draw_cursor)(struct TextViewContext *tvc, int cwidth, int columns);
/* constant theme colors */
void (*const_colors)(struct TextViewContext *tvc, unsigned char bg_sel[4]);
const void *iter;
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 5c4ccd96534..a56b7f8422e 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -325,7 +325,7 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, uin
/* influence -------------------------- */
if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
- FCurve *fcu = list_find_fcurve(&strip->fcurves, "influence", 0);
+ FCurve *fcu = BKE_fcurve_find(&strip->fcurves, "influence", 0);
float cfra;
/* plot the curve (over the strip's main region) */
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index f68896e21d6..dec7a0fd93c 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -567,7 +567,7 @@ void NLA_OT_view_frame(wmOperatorType *ot)
/* identifiers */
ot->name = "Go to Current Frame";
ot->idname = "NLA_OT_view_frame";
- ot->description = "Move the view to the playhead";
+ ot->description = "Move the view to the current frame";
/* api callbacks */
ot->exec = nlaedit_viewframe_exec;
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 44003a5b9bc..01ac3a80871 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -3638,7 +3638,7 @@ void draw_nodespace_back_pix(const bContext *C,
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle);
immDrawPixelsTex(&state,
x,
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 1d73937d762..95a37f85828 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -82,7 +82,7 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx
nodeSetSelected(node, true);
ntreeUpdateTree(bmain, snode->edittree);
- ED_node_set_active(bmain, snode->edittree, node);
+ ED_node_set_active(bmain, snode->edittree, node, NULL);
snode_update(snode, node);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index bd5ce135f82..ac58ec1e636 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -648,9 +648,12 @@ void snode_update(SpaceNode *snode, bNode *node)
}
}
-void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
+void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed)
{
const bool was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE) != 0;
+ if (r_active_texture_changed) {
+ *r_active_texture_changed = false;
+ }
nodeSetActive(ntree, node);
@@ -719,6 +722,9 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
}
}
+ if (r_active_texture_changed) {
+ *r_active_texture_changed = true;
+ }
ED_node_tag_update_nodetree(bmain, ntree, node);
WM_main_add_notifier(NC_IMAGE, NULL);
}
@@ -1290,7 +1296,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
newnode = node->new_node;
nodeSetSelected(node, false);
- node->flag &= ~NODE_ACTIVE;
+ node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_TEXTURE);
nodeSetSelected(newnode, true);
do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, newnode));
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index 9eabcc44d80..06f568c80f3 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include "DNA_node_types.h"
+#include "DNA_windowmanager_types.h"
#include "BLI_lasso_2d.h"
#include "BLI_listbase.h"
@@ -36,10 +37,12 @@
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_workspace.h"
#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_select_utils.h"
+#include "ED_view3d.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -57,6 +60,36 @@
#include "node_intern.h" /* own include */
+/* Function to detect if there is a visible view3d that uses workbench in texture mode.
+ * This function is for fixing T76970 for Blender 2.83. The actual fix should add a mechanism in
+ * the depsgraph that can be used by the draw engines to check if they need to be redrawn.
+ *
+ * We don't want to add these risky changes this close before releasing 2.83 without good testing
+ * hence this workaround. There are still cases were too many updates happen. For example when you
+ * have both a Cycles and workbench with textures viewport.
+ * */
+static bool has_workbench_in_texture_color(const wmWindowManager *wm,
+ const Scene *scene,
+ const Object *ob)
+{
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
+ if (win->scene != scene) {
+ continue;
+ }
+ const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (area->spacetype == SPACE_VIEW3D) {
+ const View3D *v3d = area->spacedata.first;
+
+ if (ED_view3d_has_workbench_in_texture_color(scene, ob, v3d)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
/* -------------------------------------------------------------------- */
/** \name Public Node Selection API
* \{ */
@@ -415,6 +448,10 @@ void node_select_single(bContext *C, bNode *node)
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
+ const Object *ob = CTX_data_active_object(C);
+ const Scene *scene = CTX_data_scene(C);
+ const wmWindowManager *wm = CTX_wm_manager(C);
+ bool active_texture_changed = false;
bNode *tnode;
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
@@ -424,10 +461,13 @@ void node_select_single(bContext *C, bNode *node)
}
nodeSetSelected(node, true);
- ED_node_set_active(bmain, snode->edittree, node);
+ ED_node_set_active(bmain, snode->edittree, node, &active_texture_changed);
ED_node_set_active_viewer_key(snode);
ED_node_sort(snode->edittree);
+ if (active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) {
+ DEG_id_tag_update(&snode->edittree->id, ID_RECALC_COPY_ON_WRITE);
+ }
WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
@@ -440,6 +480,9 @@ static int node_mouse_select(bContext *C,
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *region = CTX_wm_region(C);
+ const Object *ob = CTX_data_active_object(C);
+ const Scene *scene = CTX_data_scene(C);
+ const wmWindowManager *wm = CTX_wm_manager(C);
bNode *node, *tnode;
bNodeSocket *sock = NULL;
bNodeSocket *tsock;
@@ -546,12 +589,15 @@ static int node_mouse_select(bContext *C,
/* update node order */
if (ret_value != OPERATOR_CANCELLED) {
+ bool active_texture_changed = false;
if (node != NULL && ret_value != OPERATOR_RUNNING_MODAL) {
- ED_node_set_active(bmain, snode->edittree, node);
+ ED_node_set_active(bmain, snode->edittree, node, &active_texture_changed);
}
ED_node_set_active_viewer_key(snode);
ED_node_sort(snode->edittree);
- DEG_id_tag_update(&snode->edittree->id, ID_RECALC_COPY_ON_WRITE);
+ if (active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) {
+ DEG_id_tag_update(&snode->edittree->id, ID_RECALC_COPY_ON_WRITE);
+ }
WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 13cbda5aad7..7d3b95721c6 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -178,20 +178,13 @@ static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2)
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin);
}
-static void restrictbutton_bone_visibility_cb(bContext *C, void *poin, void *poin2)
+static void restrictbutton_bone_visibility_cb(bContext *C, void *poin, void *UNUSED(poin2))
{
- bArmature *arm = (bArmature *)poin;
- Bone *bone = (Bone *)poin2;
- if (bone->flag & BONE_HIDDEN_P) {
- bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
+ Bone *bone = (Bone *)poin;
if (CTX_wm_window(C)->eventstate->ctrl) {
restrictbutton_recursive_bone(bone, BONE_HIDDEN_P, (bone->flag & BONE_HIDDEN_P) != 0);
}
-
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
}
static void restrictbutton_bone_select_cb(bContext *C, void *UNUSED(poin), void *poin2)
@@ -859,6 +852,7 @@ typedef struct RestrictProperties {
*layer_collection_hide_viewport;
PropertyRNA *modifier_show_viewport, *modifier_show_render;
PropertyRNA *constraint_enable;
+ PropertyRNA *bone_hide_viewport;
} RestrictProperties;
/* We don't care about the value of the property
@@ -877,6 +871,7 @@ typedef struct RestrictPropertiesActive {
bool modifier_show_viewport;
bool modifier_show_render;
bool constraint_enable;
+ bool bone_hide_viewport;
} RestrictPropertiesActive;
static void outliner_restrict_properties_enable_collection_set(
@@ -1011,6 +1006,8 @@ static void outliner_draw_restrictbuts(uiBlock *block,
props.constraint_enable = RNA_struct_type_find_property(&RNA_Constraint, "mute");
+ props.bone_hide_viewport = RNA_struct_type_find_property(&RNA_Bone, "hide");
+
props.initialized = true;
}
@@ -1279,27 +1276,32 @@ static void outliner_draw_restrictbuts(uiBlock *block,
}
}
else if (tselem->type == TSE_POSE_CHANNEL) {
+ PointerRNA ptr;
bPoseChannel *pchan = (bPoseChannel *)te->directdata;
Bone *bone = pchan->bone;
Object *ob = (Object *)tselem->id;
+ bArmature *arm = ob->data;
+
+ RNA_pointer_create(&arm->id, &RNA_Bone, bone, &ptr);
if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
- bt = uiDefIconButBitI(block,
- UI_BTYPE_ICON_TOGGLE,
- BONE_HIDDEN_P,
- 0,
- ICON_RESTRICT_VIEW_OFF,
- (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &(bone->flag),
- 0,
- 0,
- 0,
- 0,
- TIP_("Restrict visibility in the 3D View"));
- UI_but_func_set(bt, restrictbutton_bone_visibility_cb, ob->data, bone);
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.bone_hide_viewport,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ TIP_("Restrict visibility in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_bone_visibility_cb, bone, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
}
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 53f2c6a90d4..80a63af3f42 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -931,7 +931,7 @@ static void cleardrivers_animdata_cb(int UNUSED(event),
IdAdtTemplate *iat = (IdAdtTemplate *)tselem->id;
/* just free drivers - stored as a list of F-Curves */
- free_fcurves(&iat->adt->drivers);
+ BKE_fcurves_free(&iat->adt->drivers);
DEG_id_tag_update(tselem->id, ID_RECALC_ANIMATION);
}
@@ -2488,6 +2488,7 @@ static int do_outliner_operation_event(
/* Only redraw, don't rebuild here because TreeElement pointers will
* become invalid and operations will crash. */
ED_region_tag_redraw_no_rebuild(region);
+ ED_outliner_select_sync_from_outliner(C, soops);
}
set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 7bb62b0d1e2..d6efe683673 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1427,9 +1427,9 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops,
ten->name = id->name + 2;
ten->directdata = lc;
- /* Open by default. */
+ /* Open by default, except linked collections, which may contain many elements. */
TreeStoreElem *tselem = TREESTORE(ten);
- if (!tselem->used) {
+ if (!(tselem->used || ID_IS_LINKED(id) || ID_IS_OVERRIDE_LIBRARY(id))) {
tselem->flag &= ~TSE_CLOSED;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 80172c5462f..6202a3556a4 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -655,7 +655,7 @@ static int sequencer_add_movie_strip_invoke(bContext *C,
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
- /* Only enable "use_framerate" if there aren't any existing strips, unless overriden by user. */
+ /* Only enable "use_framerate" if there aren't any existing strips, unless overridden by user. */
if (ed && ed->seqbasep && ed->seqbasep->first) {
RNA_boolean_set(op->ptr, "use_framerate", false);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 5d8851d5e3d..1f06ab68516 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -2299,10 +2299,10 @@ void draw_timeline_seq(const bContext *C, ARegion *region)
cfra_flag |= DRAWCFRA_UNIT_SECONDS;
}
- /* Draw playhead. */
+ /* Draw the current frame indicator. */
ANIM_draw_cfra(C, v2d, cfra_flag);
- /* Draw overlap playhead. */
+ /* Draw overlap frame frame indicator. */
if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) {
int cfra_over = (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) ?
scene->ed->over_cfra :
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index c910f1d2382..28ded81eeae 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -71,7 +71,10 @@
/* Own include. */
#include "sequencer_intern.h"
-/* XXX */
+/* -------------------------------------------------------------------- */
+/** \name Structs & Enums
+ * \{ */
+
/* RNA Enums, used in multiple files. */
EnumPropertyItem sequencer_prop_effect_types[] = {
{SEQ_TYPE_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
@@ -122,9 +125,11 @@ typedef struct TransSeq {
int len;
} TransSeq;
-/* ********************************************************************** */
+/** \} */
-/* ***************** proxy job manager ********************** */
+/* -------------------------------------------------------------------- */
+/** \name Proxy Job Manager
+ * \{ */
typedef struct ProxyBuildJob {
struct Main *main;
@@ -214,20 +219,41 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports)
}
file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
+ bool selected = false; /* Check for no selected strips */
+
SEQP_BEGIN (ed, seq) {
- if ((seq->flag & SELECT)) {
- bool success = BKE_sequencer_proxy_rebuild_context(
- pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue);
- if (!success) {
- BKE_reportf(reports, RPT_ERROR, "Could not build proxy for strip %s", seq->name);
- }
+ if (!ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META) ||
+ (seq->flag & SELECT) == 0) {
+ continue;
+ }
+
+ selected = true;
+ if (!(seq->flag & SEQ_USE_PROXY)) {
+ BKE_reportf(reports, RPT_WARNING, "Proxy is not enabled for %s, skipping.", seq->name);
+ continue;
+ }
+ else if (seq->strip->proxy->build_size_flags == 0) {
+ BKE_reportf(reports, RPT_WARNING, "Resolution is not selected for %s, skipping.", seq->name);
+ continue;
+ }
+
+ bool success = BKE_sequencer_proxy_rebuild_context(
+ pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue);
+
+ if (!success && (seq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) != 0) {
+ BKE_reportf(reports, RPT_WARNING, "Overwrite is not checked for %s, skipping.", seq->name);
}
}
SEQ_END;
+ if (!selected) {
+ BKE_reportf(reports, RPT_WARNING, "Select movie or image strips.");
+ return;
+ }
+
BLI_gset_free(file_list, MEM_freeN);
- if (!WM_jobs_is_running(wm_job)) {
+ if (selected && !WM_jobs_is_running(wm_job)) {
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
@@ -235,7 +261,11 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports)
ED_area_tag_redraw(area);
}
-/* ********************************************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sequence Query Utilities
+ * \{ */
void seq_rectf(Sequence *seq, rctf *rect)
{
@@ -290,7 +320,7 @@ static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
mval[0] = mouse_x;
mval[1] = 0;
- /* Choose the side based on which side of the playhead the mouse is on. */
+ /* Choose the side based on which side of the current frame the mouse is on. */
UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
@@ -466,6 +496,12 @@ static bool seq_is_predecessor(Sequence *pred, Sequence *seq)
return 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Selection Utilities
+ * \{ */
+
void ED_sequencer_deselect_all(Scene *scene)
{
Sequence *seq;
@@ -506,6 +542,12 @@ void recurs_sel_seq(Sequence *seqm)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Public Context Checks
+ * \{ */
+
bool ED_space_sequencer_maskedit_mask_poll(bContext *C)
{
return ED_space_sequencer_maskedit_poll(C);
@@ -545,6 +587,12 @@ bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq)
ELEM(sseq->mainb, SEQ_DRAW_SEQUENCE, SEQ_DRAW_IMG_IMBUF));
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Find Selected Strips as Inputs to an Effects Strip
+ * \{ */
+
int seq_effect_find_selected(Scene *scene,
Sequence *activeseq,
int type,
@@ -633,6 +681,12 @@ int seq_effect_find_selected(Scene *scene,
return 1;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Utilities
+ * \{ */
+
static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
{
Sequence *seq1, *seq2, *seq3;
@@ -727,6 +781,12 @@ static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short de
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Split (Hard) Utility
+ * \{ */
+
static Sequence *split_seq_hard(
Main *bmain, Scene *scene, Sequence *seq, ListBase *new_seq_list, int split_frame)
{
@@ -844,6 +904,12 @@ static Sequence *split_seq_hard(
return seqn;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Split (Soft) Utility
+ * \{ */
+
static Sequence *split_seq_soft(
Main *UNUSED(bmain), Scene *scene, Sequence *seq, ListBase *new_seq_list, int split_frame)
{
@@ -1109,6 +1175,12 @@ static void UNUSED_FUNCTION(seq_remap_paths)(Scene *scene)
SEQ_END;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Remove Gaps Operator
+ * \{ */
+
static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1177,6 +1249,12 @@ void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", 0, "All Gaps", "Do all gaps to right of current frame");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Insert Gaps Operator
+ * \{ */
+
static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1217,6 +1295,12 @@ void SEQUENCER_OT_gap_insert(struct wmOperatorType *ot)
1000);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Shared Poll Functions
+ * \{ */
+
#if 0
static int seq_get_snaplimit(View2D *v2d)
{
@@ -1277,7 +1361,12 @@ bool sequencer_view_strips_poll(bContext *C)
return 0;
}
-/* Snap operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snap Strips to the Current Frame Operator
+ * \{ */
+
static int sequencer_snap_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1355,7 +1444,7 @@ static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNU
void SEQUENCER_OT_snap(struct wmOperatorType *ot)
{
/* Identifiers. */
- ot->name = "Snap Strips to Playhead";
+ ot->name = "Snap Strips to the Current Frame";
ot->idname = "SEQUENCER_OT_snap";
ot->description = "Frame where selected strips will be snapped";
@@ -1378,6 +1467,12 @@ void SEQUENCER_OT_snap(struct wmOperatorType *ot)
INT_MAX);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Trim Strips Operator
+ * \{ */
+
typedef struct SlipData {
int init_mouse[2];
float init_mouseloc[2];
@@ -1652,10 +1747,10 @@ static void sequencer_slip_update_header(Scene *scene, ScrArea *area, SlipData *
if (hasNumInput(&data->num_input)) {
char num_str[NUM_STR_REP_LEN];
outputNumInput(&data->num_input, num_str, &scene->unit);
- BLI_snprintf(msg, sizeof(msg), TIP_("Trim offset: %s"), num_str);
+ BLI_snprintf(msg, sizeof(msg), TIP_("Slip offset: %s"), num_str);
}
else {
- BLI_snprintf(msg, sizeof(msg), TIP_("Trim offset: %d"), offset);
+ BLI_snprintf(msg, sizeof(msg), TIP_("Slip offset: %d"), offset);
}
}
@@ -1706,7 +1801,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
mouse_x = event->mval[0];
}
- /* Choose the side based on which side of the playhead the mouse is. */
+ /* Choose the side based on which side of the current frame the mouse is. */
UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
offset = mouseloc[0] - data->init_mouseloc[0];
@@ -1834,7 +1929,12 @@ void SEQUENCER_OT_slip(struct wmOperatorType *ot)
INT32_MAX);
}
-/* Mute operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mute Strips Operator
+ * \{ */
+
static int sequencer_mute_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1885,7 +1985,12 @@ void SEQUENCER_OT_mute(struct wmOperatorType *ot)
ot->srna, "unselected", 0, "Unselected", "Mute unselected rather than selected strips");
}
-/* Unmute operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Unmute Strips Operator
+ * \{ */
+
static int sequencer_unmute_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1936,7 +2041,12 @@ void SEQUENCER_OT_unmute(struct wmOperatorType *ot)
ot->srna, "unselected", 0, "Unselected", "Unmute unselected rather than selected strips");
}
-/* Lock operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Lock Strips Operator
+ * \{ */
+
static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -1969,7 +2079,12 @@ void SEQUENCER_OT_lock(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* Unlock operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Unlock Strips Operator
+ * \{ */
+
static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -2002,7 +2117,12 @@ void SEQUENCER_OT_unlock(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* Reload operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Reload Strips Operator
+ * \{ */
+
static int sequencer_reload_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -2053,7 +2173,12 @@ void SEQUENCER_OT_reload(struct wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* Reload operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Refresh Sequencer Operator
+ * \{ */
+
static bool sequencer_refresh_all_poll(bContext *C)
{
if (G.is_rendering) {
@@ -2086,6 +2211,12 @@ void SEQUENCER_OT_refresh_all(struct wmOperatorType *ot)
ot->poll = sequencer_refresh_all_poll;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Reassign Inputs Operator
+ * \{ */
+
static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -2145,6 +2276,12 @@ void SEQUENCER_OT_reassign_inputs(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Swap Inputs Operator
+ * \{ */
+
static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -2180,7 +2317,12 @@ void SEQUENCER_OT_swap_inputs(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* Split operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Split Strips Operator
+ * \{ */
+
static const EnumPropertyItem prop_split_types[] = {
{SEQ_SPLIT_SOFT, "SOFT", 0, "Soft", ""},
{SEQ_SPLIT_HARD, "HARD", 0, "Hard", ""},
@@ -2353,7 +2495,7 @@ void SEQUENCER_OT_split(struct wmOperatorType *ot)
"use_cursor_position",
0,
"Use Cursor Position",
- "Split at position of the cursor instead of playhead");
+ "Split at position of the cursor instead of current frame");
prop = RNA_def_enum(ot->srna,
"side",
@@ -2376,7 +2518,12 @@ void SEQUENCER_OT_split(struct wmOperatorType *ot)
#undef SEQ_SIDE_MOUSE
-/* Duplicate operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Duplicate Strips Operator
+ * \{ */
+
static int apply_unique_name_fn(Sequence *seq, void *arg_pt)
{
Scene *scene = (Scene *)arg_pt;
@@ -2432,7 +2579,12 @@ void SEQUENCER_OT_duplicate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* Delete operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Erase Strips Operator
+ * \{ */
+
static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
@@ -2508,7 +2660,7 @@ static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
}
- return WM_operator_confirm(C, op, event);
+ return sequencer_delete_exec(C, op);
}
void SEQUENCER_OT_delete(wmOperatorType *ot)
@@ -2528,7 +2680,12 @@ void SEQUENCER_OT_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* Offset clear operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Strip Offset Operator
+ * \{ */
+
static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -2578,7 +2735,12 @@ void SEQUENCER_OT_offset_clear(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* Separate_images operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Separate Images Operator
+ * \{ */
+
static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -2677,9 +2839,12 @@ void SEQUENCER_OT_images_separate(wmOperatorType *ot)
RNA_def_int(ot->srna, "length", 1, 1, INT_MAX, "Length", "Length of each frame", 1, 1000);
}
-/* META Operators. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Meta Strip Operator
+ * \{ */
-/* Separate_meta_toggle operator. */
static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -2765,7 +2930,12 @@ void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* Separate_meta_make operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Make Meta Strip Operator
+ * \{ */
+
static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -2829,6 +2999,12 @@ void SEQUENCER_OT_meta_make(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name UnMeta Strip Operator
+ * \{ */
+
static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
{
if (seq == seqm) {
@@ -2848,7 +3024,6 @@ static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
}
}
-/* Separate_meta_make operator. */
static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -2914,7 +3089,12 @@ void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* View_all operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sequencer Frame All Operator
+ * \{ */
+
static int sequencer_view_all_exec(bContext *C, wmOperator *op)
{
ARegion *region = CTX_wm_region(C);
@@ -2942,6 +3122,12 @@ void SEQUENCER_OT_view_all(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Go to Current Frame Operator
+ * \{ */
+
static int sequencer_view_frame_exec(bContext *C, wmOperator *op)
{
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
@@ -2955,7 +3141,7 @@ void SEQUENCER_OT_view_frame(wmOperatorType *ot)
/* Identifiers. */
ot->name = "Go to Current Frame";
ot->idname = "SEQUENCER_OT_view_frame";
- ot->description = "Move the view to the playhead";
+ ot->description = "Move the view to the current frame";
/* Api callbacks. */
ot->exec = sequencer_view_frame_exec;
@@ -2965,7 +3151,12 @@ void SEQUENCER_OT_view_frame(wmOperatorType *ot)
ot->flag = 0;
}
-/* View_all operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Preview Frame All Operator
+ * \{ */
+
static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op))
{
bScreen *screen = CTX_wm_screen(C);
@@ -3029,6 +3220,12 @@ void SEQUENCER_OT_view_all_preview(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sequencer View Zoom Ratio Operator
+ * \{ */
+
static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op)
{
RenderData *rd = &CTX_data_scene(C)->r;
@@ -3072,6 +3269,12 @@ void SEQUENCER_OT_view_zoom_ratio(wmOperatorType *ot)
FLT_MAX);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Toggle Operator
+ * \{ */
+
#if 0
static const EnumPropertyItem view_type_items[] = {
{SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""},
@@ -3085,7 +3288,6 @@ static const EnumPropertyItem view_type_items[] = {
};
#endif
-/* View_all operator. */
static int sequencer_view_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceSeq *sseq = (SpaceSeq *)CTX_wm_space_data(C);
@@ -3115,7 +3317,12 @@ void SEQUENCER_OT_view_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
}
-/* View_selected operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Frame Selected Operator
+ * \{ */
+
static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -3197,6 +3404,12 @@ void SEQUENCER_OT_view_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Jump to Strip Operator
+ * \{ */
+
static bool strip_jump_internal(Scene *scene,
const short side,
const bool do_skip_mute,
@@ -3224,7 +3437,6 @@ static bool sequencer_strip_jump_poll(bContext *C)
return sequencer_edit_poll(C);
}
-/* Jump frame to edit point operator. */
static int sequencer_strip_jump_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -3260,6 +3472,12 @@ void SEQUENCER_OT_strip_jump(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "center", true, "Use strip center", "");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Swap Strip Operator
+ * \{ */
+
static void swap_sequence(Scene *scene, Sequence *seqa, Sequence *seqb)
{
int gap = seqb->startdisp - seqa->enddisp;
@@ -3380,6 +3598,12 @@ void SEQUENCER_OT_swap(wmOperatorType *ot)
ot->srna, "side", prop_side_lr_types, SEQ_SIDE_RIGHT, "Side", "Side of the strip to swap");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Render Size Operator
+ * \{ */
+
static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op))
{
int retval = OPERATOR_CANCELLED;
@@ -3436,6 +3660,12 @@ void SEQUENCER_OT_rendersize(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Copy Operator
+ * \{ */
+
static void seq_copy_del_sound(Scene *scene, Sequence *seq)
{
if (seq->type == SEQ_TYPE_META) {
@@ -3495,6 +3725,12 @@ void SEQUENCER_OT_copy(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Paste Operator
+ * \{ */
+
static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
@@ -3551,6 +3787,12 @@ void SEQUENCER_OT_paste(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sequencer Swap Data Operator
+ * \{ */
+
static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -3612,7 +3854,12 @@ void SEQUENCER_OT_swap_data(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* Box select operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Border Offset View Operator
+ * \{ */
+
static int view_ghost_border_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -3668,7 +3915,12 @@ void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot)
WM_operator_properties_gesture_box(ot);
}
-/* Rebuild_proxy operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Rebuild Proxy and Timecode Indices Operator
+ * \{ */
+
static int sequencer_rebuild_proxy_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
@@ -3732,6 +3984,12 @@ void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Selected Strip Proxies Operator
+ * \{ */
+
static int sequencer_enable_proxies_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
@@ -3757,12 +4015,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
SEQP_BEGIN (ed, seq) {
if ((seq->flag & SELECT)) {
- if (ELEM(seq->type,
- SEQ_TYPE_MOVIE,
- SEQ_TYPE_IMAGE,
- SEQ_TYPE_META,
- SEQ_TYPE_SCENE,
- SEQ_TYPE_MULTICAM)) {
+ if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META)) {
BKE_sequencer_proxy_set(seq, turnon);
if (seq->strip->proxy == NULL) {
continue;
@@ -3833,7 +4086,12 @@ void SEQUENCER_OT_enable_proxies(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite", "");
}
-/* Change effect inputs operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Change Effect Input Operator
+ * \{ */
+
static const EnumPropertyItem prop_change_effect_input_types[] = {
{0, "A_B", 0, "A -> B", ""},
{1, "B_C", 0, "B -> C", ""},
@@ -3898,7 +4156,12 @@ void SEQUENCER_OT_change_effect_input(struct wmOperatorType *ot)
ot->srna, "swap", prop_change_effect_input_types, 0, "Swap", "The effect inputs to swap");
}
-/* Change effect type operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Change Effect Type Operator
+ * \{ */
+
static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -3960,7 +4223,12 @@ void SEQUENCER_OT_change_effect_type(struct wmOperatorType *ot)
"Sequencer effect type");
}
-/* Change path operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Change Data/Files Operator
+ * \{ */
+
static int sequencer_change_path_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -4108,7 +4376,12 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
"Use placeholders for missing frames of the strip");
}
-/* Export subtitles operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Export Subtitles Operator
+ * \{ */
+
static int sequencer_export_subtitles_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
@@ -4243,7 +4516,12 @@ void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot)
FILE_SORT_ALPHA);
}
-/* Set range to strips operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Range to Strips Operator
+ * \{ */
+
static int sequencer_set_range_to_strips_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -4307,3 +4585,5 @@ void SEQUENCER_OT_set_range_to_strips(struct wmOperatorType *ot)
prop = RNA_def_boolean(ot->srna, "preview", false, "Preview", "Set the preview range instead");
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
+
+/** \} */
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 708682cd04f..eec8d604b64 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -158,6 +158,7 @@ void SEQUENCER_OT_view_all_preview(struct wmOperatorType *ot);
/* sequencer_select.c */
void SEQUENCER_OT_select_all(struct wmOperatorType *ot);
void SEQUENCER_OT_select(struct wmOperatorType *ot);
+void SEQUENCER_OT_select_side_of_frame(struct wmOperatorType *ot);
void SEQUENCER_OT_select_more(struct wmOperatorType *ot);
void SEQUENCER_OT_select_less(struct wmOperatorType *ot);
void SEQUENCER_OT_select_linked(struct wmOperatorType *ot);
@@ -181,20 +182,6 @@ enum {
SEQ_SPLIT_SOFT,
SEQ_SPLIT_HARD,
};
-enum {
- SEQ_SELECTED,
- SEQ_UNSELECTED,
-};
-
-enum {
- SEQ_SELECT_LR_NONE = 0,
- SEQ_SELECT_LR_MOUSE,
- SEQ_SELECT_LR_LEFT,
- SEQ_SELECT_LR_RIGHT,
-};
-
-/* Defines used internally. */
-#define SCE_MARKERS 0 /* XXX - dummy */
/* sequencer_ops.c */
void sequencer_operatortypes(void);
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index ac00838a079..4fe1c953c74 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -99,6 +99,7 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_select_linked);
WM_operatortype_append(SEQUENCER_OT_select_handles);
WM_operatortype_append(SEQUENCER_OT_select_side);
+ WM_operatortype_append(SEQUENCER_OT_select_side_of_frame);
WM_operatortype_append(SEQUENCER_OT_select_box);
WM_operatortype_append(SEQUENCER_OT_select_grouped);
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index c5472ed88e5..f2b7e138c3e 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -52,10 +52,9 @@
/* Own include. */
#include "sequencer_intern.h"
-static void *find_nearest_marker(int UNUSED(d1), int UNUSED(d2))
-{
- return NULL;
-}
+/* -------------------------------------------------------------------- */
+/** \name Selection Utilities
+ * \{ */
static void select_surrounding_handles(Scene *scene, Sequence *test) /* XXX BRING BACK */
{
@@ -253,6 +252,12 @@ static void select_neighbor_from_last(Scene *scene, int lr)
}
#endif
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name (De)select All Operator
+ * \{ */
+
static int sequencer_de_select_all_exec(bContext *C, wmOperator *op)
{
int action = RNA_enum_get(op->ptr, "action");
@@ -316,6 +321,12 @@ void SEQUENCER_OT_select_all(struct wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Inverse Operator
+ * \{ */
+
static int sequencer_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -354,6 +365,12 @@ void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Operator
+ * \{ */
+
static int sequencer_select_exec(bContext *C, wmOperator *op)
{
View2D *v2d = UI_view2d_fromcontext(C);
@@ -363,8 +380,8 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
const bool linked_handle = RNA_boolean_get(op->ptr, "linked_handle");
const bool linked_time = RNA_boolean_get(op->ptr, "linked_time");
+ bool side_of_frame = RNA_boolean_get(op->ptr, "side_of_frame");
bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
- int left_right = RNA_enum_get(op->ptr, "left_right");
int mval[2];
int ret_value = OPERATOR_CANCELLED;
@@ -373,7 +390,6 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
Sequence *seq, *neighbor, *act_orig;
int hand, sel_side;
- TimeMarker *marker;
if (ed == NULL) {
return OPERATOR_CANCELLED;
@@ -383,57 +399,31 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
wait_to_deselect_others = false;
}
- marker = find_nearest_marker(SCE_MARKERS, 1); /* XXX - dummy function for now */
-
seq = find_nearest_seq(scene, v2d, &hand, mval);
- /* XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip */
- if (seq && linked_time && (left_right == SEQ_SELECT_LR_MOUSE)) {
- left_right = SEQ_SELECT_LR_NONE;
+ /* XXX - not nice, Ctrl+RMB needs to do side_of_frame only when not over a strip */
+ if (seq && linked_time) {
+ side_of_frame = false;
}
- if (marker) {
- int oldflag;
- /* Select timeline marker. */
- if (extend) {
- oldflag = marker->flag;
- if (oldflag & SELECT) {
- marker->flag &= ~SELECT;
- }
- else {
- marker->flag |= SELECT;
- }
- }
- else {
- /* XXX, in 2.4x, seq selection used to deselect all, need to re-thnik this for 2.5 */
- /* deselect_markers(0, 0); */
- marker->flag |= SELECT;
- }
-
- ret_value = OPERATOR_FINISHED;
- }
- else if (left_right != SEQ_SELECT_LR_NONE) {
+ /* Select left, right or overlapping the current frame. */
+ if (side_of_frame) {
/* Use different logic for this. */
float x;
if (extend == false) {
ED_sequencer_deselect_all(scene);
}
- switch (left_right) {
- case SEQ_SELECT_LR_MOUSE:
- x = UI_view2d_region_to_view_x(v2d, mval[0]);
- break;
- case SEQ_SELECT_LR_LEFT:
- x = CFRA - 1.0f;
- break;
- case SEQ_SELECT_LR_RIGHT:
- default:
- x = CFRA;
- break;
+ /* 10px margin around current frame to select under the current frame with mouse. */
+ float margin = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask) * 10;
+ x = UI_view2d_region_to_view_x(v2d, mval[0]);
+ if (x >= CFRA - margin && x <= CFRA + margin) {
+ x = CFRA;
}
SEQP_BEGIN (ed, seq) {
- if (((x < CFRA) && (seq->enddisp <= CFRA)) || ((x >= CFRA) && (seq->startdisp >= CFRA))) {
+ /* Select left or right. */
+ if ((x < CFRA && seq->enddisp <= CFRA) || (x > CFRA && seq->startdisp >= CFRA)) {
seq->flag |= SELECT;
recurs_sel_seq(seq);
}
@@ -624,13 +614,6 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
void SEQUENCER_OT_select(wmOperatorType *ot)
{
- static const EnumPropertyItem sequencer_select_left_right_types[] = {
- {SEQ_SELECT_LR_NONE, "NONE", 0, "None", "Don't do left-right selection"},
- {SEQ_SELECT_LR_MOUSE, "MOUSE", 0, "Mouse", "Use mouse position for selection"},
- {SEQ_SELECT_LR_LEFT, "LEFT", 0, "Left", "Select left"},
- {SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select right"},
- {0, NULL, 0, NULL, NULL},
- };
PropertyRNA *prop;
/* Identifiers. */
@@ -649,26 +632,43 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
/* Properties. */
WM_operator_properties_generic_select(ot);
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
+
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
prop = RNA_def_boolean(ot->srna,
"deselect_all",
false,
"Deselect On Nothing",
"Deselect all when nothing under the cursor");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- RNA_def_boolean(
- ot->srna, "linked_handle", 0, "Linked Handle", "Select handles next to the active strip");
- /* For animation this is enum but atm having an enum isn't useful for us. */
- RNA_def_enum(ot->srna,
- "left_right",
- sequencer_select_left_right_types,
- 0,
- "Left/Right",
- "Select based on the current frame side the cursor is on");
- RNA_def_boolean(
- ot->srna, "linked_time", 0, "Linked Time", "Select other strips at the same time");
+
+ prop = RNA_def_boolean(ot->srna,
+ "linked_handle",
+ false,
+ "Linked Handle",
+ "Select handles next to the active strip");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(
+ ot->srna, "linked_time", false, "Linked Time", "Select other strips at the same time");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(
+ ot->srna,
+ "side_of_frame",
+ false,
+ "Side of Frame",
+ "Select all strips on same side of the current frame as the mouse cursor");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select More Operator
+ * \{ */
+
/* Run recursively to select linked. */
static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool linked)
{
@@ -766,6 +766,12 @@ void SEQUENCER_OT_select_more(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Less Operator
+ * \{ */
+
static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -796,6 +802,12 @@ void SEQUENCER_OT_select_less(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Pick Linked Operator
+ * \{ */
+
static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
@@ -849,6 +861,12 @@ void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked Operator
+ * \{ */
+
static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -881,6 +899,12 @@ void SEQUENCER_OT_select_linked(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Handles Operator
+ * \{ */
+
static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -936,6 +960,87 @@ void SEQUENCER_OT_select_handles(wmOperatorType *ot)
"The side of the handle that is selected");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Side of Frame Operator
+ * \{ */
+
+static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const int side = RNA_enum_get(op->ptr, "side");
+ Sequence *seq;
+
+ if (ed == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ if (extend == false) {
+ ED_sequencer_deselect_all(scene);
+ }
+ const int cfra = CFRA;
+ SEQP_BEGIN (ed, seq) {
+ bool test = false;
+ switch (side) {
+ case -1:
+ test = (cfra >= seq->startdisp);
+ break;
+ case 1:
+ test = (cfra <= seq->enddisp);
+ break;
+ case 0:
+ test = (cfra <= seq->enddisp) && (cfra >= seq->startdisp);
+ break;
+ }
+
+ if (test) {
+ seq->flag |= SELECT;
+ recurs_sel_seq(seq);
+ }
+ }
+ SEQ_END;
+
+ ED_outliner_select_sync_from_sequence_tag(C);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_select_side_of_frame(wmOperatorType *ot)
+{
+ static const EnumPropertyItem sequencer_select_left_right_types[] = {
+ {0, "OVERLAP", 0, "Overlap", "Select overlapping the current frame"},
+ {-1, "LEFT", 0, "Left", "Select to the left of the current frame"},
+ {1, "RIGHT", 0, "Right", "Select to the right of the current frame"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* Identifiers. */
+ ot->name = "Select Side of Frame";
+ ot->idname = "SEQUENCER_OT_select_side_of_frame";
+ ot->description = "Select strips relative to the current frame";
+
+ /* Api callbacks. */
+ ot->exec = sequencer_select_side_of_frame_exec;
+ ot->poll = ED_operator_sequencer_active;
+
+ /* Flags. */
+ ot->flag = OPTYPE_UNDO;
+
+ /* Properties. */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
+ ot->prop = RNA_def_enum(ot->srna, "side", sequencer_select_left_right_types, 0, "Side", "");
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Side Operator
+ * \{ */
+
static int sequencer_select_side_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1000,6 +1105,12 @@ void SEQUENCER_OT_select_side(wmOperatorType *ot)
"The side to which the selection is applied");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Box Select Operator
+ * \{ */
+
static int sequencer_box_select_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1124,6 +1235,12 @@ void SEQUENCER_OT_select_box(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Grouped Operator
+ * \{ */
+
enum {
SEQ_SELECT_GROUP_TYPE,
SEQ_SELECT_GROUP_TYPE_BASIC,
@@ -1460,8 +1577,8 @@ void SEQUENCER_OT_select_grouped(wmOperatorType *ot)
{
/* Identifiers. */
ot->name = "Select Grouped";
- ot->description = "Select all strips grouped by various properties";
ot->idname = "SEQUENCER_OT_select_grouped";
+ ot->description = "Select all strips grouped by various properties";
/* Api callbacks. */
ot->invoke = WM_menu_invoke;
@@ -1484,3 +1601,5 @@ void SEQUENCER_OT_select_grouped(wmOperatorType *ot)
"Same Channel",
"Only consider strips on the same channel as the active one");
}
+
+/** \} */
diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c
index 1ec459ccfca..d823530fd89 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -25,11 +25,15 @@
#include "DNA_screen_types.h"
+#include "BLI_listbase.h"
+
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
#include "RNA_types.h"
#include "UI_interface.h"
@@ -41,11 +45,13 @@
#include "ED_userpref.h"
+#include "MEM_guardedalloc.h"
+
/* -------------------------------------------------------------------- */
-/** \name Reset Default Theme
+/** \name Reset Default Theme Operator
* \{ */
-static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
+static int preferences_reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
UI_theme_init_default();
@@ -64,7 +70,7 @@ static void PREFERENCES_OT_reset_default_theme(wmOperatorType *ot)
ot->description = "Reset to the default theme colors";
/* callbacks */
- ot->exec = reset_default_theme_exec;
+ ot->exec = preferences_reset_default_theme_exec;
/* flags */
ot->flag = OPTYPE_REGISTER;
@@ -72,7 +78,64 @@ static void PREFERENCES_OT_reset_default_theme(wmOperatorType *ot)
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Add Auto-Execution Path Operator
+ * \{ */
+
+static int preferences_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
+{
+ bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare");
+ BLI_addtail(&U.autoexec_paths, path_cmp);
+ U.runtime.is_dirty = true;
+ return OPERATOR_FINISHED;
+}
+
+static void PREFERENCES_OT_autoexec_path_add(wmOperatorType *ot)
+{
+ ot->name = "Add Autoexec Path";
+ ot->idname = "PREFERENCES_OT_autoexec_path_add";
+ ot->description = "Add path to exclude from auto-execution";
+
+ ot->exec = preferences_autoexec_add_exec;
+
+ ot->flag = OPTYPE_INTERNAL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Remove Auto-Execution Path Operator
+ * \{ */
+
+static int preferences_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op)
+{
+ const int index = RNA_int_get(op->ptr, "index");
+ bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index);
+ if (path_cmp) {
+ BLI_freelinkN(&U.autoexec_paths, path_cmp);
+ U.runtime.is_dirty = true;
+ }
+ return OPERATOR_FINISHED;
+}
+
+static void PREFERENCES_OT_autoexec_path_remove(wmOperatorType *ot)
+{
+ ot->name = "Remove Autoexec Path";
+ ot->idname = "PREFERENCES_OT_autoexec_path_remove";
+ ot->description = "Remove path to exclude from auto-execution";
+
+ ot->exec = preferences_autoexec_remove_exec;
+
+ ot->flag = OPTYPE_INTERNAL;
+
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
+}
+
+/** \} */
+
void ED_operatortypes_userpref(void)
{
WM_operatortype_append(PREFERENCES_OT_reset_default_theme);
+ WM_operatortype_append(PREFERENCES_OT_autoexec_path_add);
+ WM_operatortype_append(PREFERENCES_OT_autoexec_path_remove);
}
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index c7fe82e0cbb..f2536cfac62 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -64,6 +64,7 @@ set(SRC
view3d_header.c
view3d_iterators.c
view3d_ops.c
+ view3d_placement.c
view3d_project.c
view3d_select.c
view3d_snap.c
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index a5c99016434..4fc98789c18 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -675,6 +675,8 @@ static void view3d_widgets(void)
WM_gizmogrouptype_append(VIEW3D_GGT_ruler);
WM_gizmotype_append(VIEW3D_GT_ruler_item);
+ WM_gizmogrouptype_append(VIEW3D_GGT_placement);
+
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_navigate);
WM_gizmotype_append(VIEW3D_GT_navigate_rotate);
}
@@ -1082,9 +1084,19 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
}
}
+/* concept is to retrieve cursor type context-less */
static void view3d_main_region_cursor(wmWindow *win, ScrArea *area, ARegion *region)
{
- if (!WM_cursor_set_from_tool(win, area, region)) {
+ if (WM_cursor_set_from_tool(win, area, region)) {
+ return;
+ }
+
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+ if (obedit) {
+ WM_cursor_set(win, WM_CURSOR_EDIT);
+ }
+ else {
WM_cursor_set(win, WM_CURSOR_DEFAULT);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index f81b4bb09e2..cb87ddafea1 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -1642,7 +1642,7 @@ static int view3d_object_mode_menu(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
else if (((ob->mode & OB_MODE_EDIT) == 0) && (ELEM(ob->type, OB_ARMATURE))) {
- ED_object_mode_toggle(C, OB_MODE_POSE);
+ ED_object_mode_set(C, (ob->mode == OB_MODE_OBJECT) ? OB_MODE_POSE : OB_MODE_OBJECT);
return OPERATOR_CANCELLED;
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 5cdf6ce28cb..edd75d8e561 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -3349,7 +3349,7 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name View Camera Center Operator
+/** \name Frame Camera Bounds Operator
* \{ */
static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op))
@@ -3386,8 +3386,8 @@ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op))
void VIEW3D_OT_view_center_camera(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Camera Center";
- ot->description = "Center the camera view";
+ ot->name = "Frame Camera Bounds";
+ ot->description = "Center the camera view, resizing the view to fit its bounds";
ot->idname = "VIEW3D_OT_view_center_camera";
/* api callbacks */
@@ -5018,7 +5018,6 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
float cursor_co[3],
float cursor_quat[4])
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
ARegion *region = CTX_wm_region(C);
@@ -5052,7 +5051,7 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
float ray_co[3];
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, scene, 0, region, v3d);
+ scene, 0, region, v3d);
float obmat[4][4];
Object *ob_dummy = NULL;
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
index 3301e28c90c..3ce4c8dc9a8 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
@@ -536,9 +536,12 @@ static int gizmo_axis_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mv
return -1;
}
-static int gizmo_axis_cursor_get(wmGizmo *UNUSED(gz))
+static int gizmo_axis_cursor_get(wmGizmo *gz)
{
- return WM_CURSOR_DEFAULT;
+ if (gz->highlight_part > 0) {
+ return WM_CURSOR_EDIT;
+ }
+ return WM_CURSOR_NSEW_SCROLL;
}
void VIEW3D_GT_navigate_rotate(wmGizmoType *gzt)
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index e4863c0cdeb..f3bc0a8a15b 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -40,6 +40,7 @@
#include "DNA_object_types.h"
#include "DNA_view3d_types.h"
+#include "ED_gizmo_library.h"
#include "ED_gizmo_utils.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
@@ -57,10 +58,13 @@
#include "WM_toolsystem.h"
#include "WM_types.h"
+#include "DEG_depsgraph_query.h"
+
#include "view3d_intern.h" /* own include */
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#include "GPU_state.h"
#include "BLF_api.h"
@@ -94,10 +98,6 @@ enum {
RULER_STATE_DRAG,
};
-enum {
- RULER_SNAP_OK = (1 << 0),
-};
-
struct RulerItem;
typedef struct RulerInfo {
@@ -106,19 +106,25 @@ typedef struct RulerInfo {
int snap_flag;
int state;
- struct SnapObjectContext *snap_context;
-
/* wm state */
+ wmWindowManager *wm;
wmWindow *win;
ScrArea *area;
ARegion *region; /* re-assigned every modal update */
/* Track changes in state. */
struct {
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
bool do_snap;
+#endif
bool do_thickness;
} drag_state_prev;
+ struct {
+ wmGizmo *gizmo;
+ PropertyRNA *prop_prevpoint;
+ } snap_data;
+
} RulerInfo;
/* -------------------------------------------------------------------- */
@@ -269,26 +275,17 @@ static bool view3d_ruler_pick(wmGizmoGroup *gzgroup,
* Ensure the 'snap_context' is only cached while dragging,
* needed since the user may toggle modes between tool use.
*/
-static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
+static void ruler_state_set(RulerInfo *ruler_info, int state)
{
- Main *bmain = CTX_data_main(C);
if (state == ruler_info->state) {
return;
}
- /* always remove */
- if (ruler_info->snap_context) {
- ED_transform_snap_object_context_destroy(ruler_info->snap_context);
- ruler_info->snap_context = NULL;
- }
-
if (state == RULER_STATE_NORMAL) {
/* pass */
}
else if (state == RULER_STATE_DRAG) {
memset(&ruler_info->drag_state_prev, 0x0, sizeof(ruler_info->drag_state_prev));
- ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, CTX_data_scene(C), 0, ruler_info->region, CTX_wm_view3d(C));
}
else {
BLI_assert(0);
@@ -307,13 +304,18 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
RulerInfo *ruler_info,
RulerItem *ruler_item,
const int mval[2],
- const bool do_thickness,
- const bool do_snap)
+ const bool do_thickness
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ ,
+ const bool do_snap
+#endif
+)
{
+ wmGizmo *snap_gizmo = ruler_info->snap_data.gizmo;
const float eps_bias = 0.0002f;
float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */
- ruler_info->snap_flag &= ~RULER_SNAP_OK;
+ WM_gizmo_set_flag(snap_gizmo, WM_GIZMO_HIDDEN, true);
if (ruler_item) {
RulerInteraction *inter = ruler_item->gz.interaction_data;
@@ -322,8 +324,10 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
copy_v3_v3(co, inter->drag_start_co);
view3d_ruler_item_project(ruler_info, co, mval);
if (do_thickness && inter->co_index != 1) {
- // Scene *scene = CTX_data_scene(C);
- // View3D *v3d = ruler_info->area->spacedata.first;
+ Scene *scene = DEG_get_input_scene(depsgraph);
+ View3D *v3d = ruler_info->area->spacedata.first;
+ SnapObjectContext *snap_context = ED_gizmotypes_snap_3d_context_ensure(
+ scene, ruler_info->region, v3d, snap_gizmo);
const float mval_fl[2] = {UNPACK2(mval)};
float ray_normal[3];
float ray_start[3];
@@ -331,7 +335,7 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0];
- if (ED_transform_snap_object_project_view3d(ruler_info->snap_context,
+ if (ED_transform_snap_object_project_view3d(snap_context,
depsgraph,
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
@@ -346,7 +350,7 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
negate_v3(ray_normal);
/* add some bias */
madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias);
- ED_transform_snap_object_project_ray(ruler_info->snap_context,
+ ED_transform_snap_object_project_ray(snap_context,
depsgraph,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
@@ -359,7 +363,12 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
NULL);
}
}
- else if (do_snap) {
+ else
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ if (do_snap)
+#endif
+ {
+ View3D *v3d = ruler_info->area->spacedata.first;
const float mval_fl[2] = {UNPACK2(mval)};
float *prev_point = NULL;
@@ -374,23 +383,16 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
prev_point = ruler_item->co[0];
}
}
+ if (prev_point != NULL) {
+ RNA_property_float_set_array(
+ snap_gizmo->ptr, ruler_info->snap_data.prop_prevpoint, prev_point);
+ }
- if (ED_transform_snap_object_project_view3d(
- ruler_info->snap_context,
- depsgraph,
- (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
- SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR),
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- .use_object_edit_cage = true,
- .use_occlusion_test = true,
- },
- mval_fl,
- prev_point,
- &dist_px,
- co,
- NULL)) {
- ruler_info->snap_flag |= RULER_SNAP_OK;
+ short snap_elem = ED_gizmotypes_snap_3d_update(
+ snap_gizmo, depsgraph, ruler_info->region, v3d, ruler_info->wm, mval_fl, co, NULL);
+
+ if (snap_elem) {
+ WM_gizmo_set_flag(snap_gizmo, WM_GIZMO_HIDDEN, false);
}
}
return true;
@@ -417,6 +419,15 @@ static bGPDlayer *view3d_ruler_layer_get(bGPdata *gpd)
return NULL;
}
+static RulerItem *gzgroup_ruler_item_first_get(wmGizmoGroup *gzgroup)
+{
+#ifndef NDEBUG
+ RulerInfo *ruler_info = gzgroup->customdata;
+ BLI_assert(gzgroup->gizmos.first == ruler_info->snap_data.gizmo);
+#endif
+ return (RulerItem *)((wmGizmo *)gzgroup->gizmos.first)->next;
+}
+
#define RULER_ID "RulerData3D"
static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
{
@@ -448,7 +459,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
BKE_gpencil_free_strokes(gpf);
- for (ruler_item = gzgroup->gizmos.first; ruler_item;
+ for (ruler_item = gzgroup_ruler_item_first_get(gzgroup); ruler_item;
ruler_item = (RulerItem *)ruler_item->gz.next) {
bGPDspoint *pt;
int j;
@@ -556,6 +567,12 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
uchar color_wire[3];
float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f};
+ /* Pixel Space. */
+ GPU_matrix_push_projection();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+ wmOrtho2_region_pixelspace(region);
+
/* anti-aliased lines for more consistent appearance */
GPU_line_smooth(true);
GPU_line_width(1.0f);
@@ -575,20 +592,30 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
const bool is_act = (ruler_info->item_active == ruler_item);
float dir_ruler[2];
float co_ss[3][2];
+ bool proj_ok[3];
int j;
- /* should these be checked? - ok for now not to */
+ /* Check if each corner is behind the near plane. If it is, we do not draw certain lines. */
for (j = 0; j < 3; j++) {
- ED_view3d_project_float_global(region, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
+ eV3DProjStatus status = ED_view3d_project_float_global(
+ region, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_CLIP_NEAR);
+ proj_ok[j] = (status == V3D_PROJ_RET_OK);
}
+ /* 3d drawing. */
+
+ GPU_matrix_push_projection();
+ GPU_matrix_push();
+ GPU_matrix_projection_set(rv3d->winmat);
+ GPU_matrix_set(rv3d->viewmat);
+
GPU_blend(true);
- const uint shdr_pos = GPU_vertformat_attr_add(
- immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ const uint shdr_pos_3d = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
if (ruler_item->flag & RULERITEM_USE_ANGLE) {
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
@@ -605,21 +632,20 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2fv(shdr_pos, co_ss[0]);
- immVertex2fv(shdr_pos, co_ss[1]);
- immVertex2fv(shdr_pos, co_ss[2]);
+ immVertex3fv(shdr_pos_3d, ruler_item->co[0]);
+ immVertex3fv(shdr_pos_3d, ruler_item->co[1]);
+ immVertex3fv(shdr_pos_3d, ruler_item->co[2]);
immEnd();
immUnbindProgram();
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
/* arc */
{
float dir_tmp[3];
- float co_tmp[3];
- float arc_ss_coord[2];
+ float ar_coord[3];
float dir_a[3];
float dir_b[3];
@@ -648,16 +674,53 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immBegin(GPU_PRIM_LINE_STRIP, arc_steps + 1);
for (j = 0; j <= arc_steps; j++) {
- madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
- ED_view3d_project_float_global(region, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP);
+ madd_v3_v3v3fl(ar_coord, ruler_item->co[1], dir_tmp, px_scale);
mul_qt_v3(quat, dir_tmp);
- immVertex2fv(shdr_pos, arc_ss_coord);
+ immVertex3fv(shdr_pos_3d, ar_coord);
}
immEnd();
}
+ immUnbindProgram();
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("colors_len", 2); /* "advanced" mode */
+ const float *col = is_act ? color_act : color_base;
+ immUniformArray4fv(
+ "colors",
+ (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}},
+ 2);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+
+ immVertex3fv(shdr_pos_3d, ruler_item->co[0]);
+ immVertex3fv(shdr_pos_3d, ruler_item->co[2]);
+
+ immEnd();
+
+ immUnbindProgram();
+ }
+
+ /* 2d drawing. */
+
+ GPU_matrix_pop();
+ GPU_matrix_pop_projection();
+
+ const uint shdr_pos_2d = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* capping */
{
float rot_90_vec_a[2];
@@ -676,15 +739,15 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
GPU_blend(true);
- if (is_act && (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) {
+ if (proj_ok[1] && is_act && (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) {
GPU_line_width(3.0f);
immUniformColor3fv(color_act);
immBegin(GPU_PRIM_LINES, 4);
/* angle vertex */
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
immEnd();
GPU_line_width(1.0f);
@@ -692,25 +755,33 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immUniformColor3ubv(color_wire);
- immBegin(GPU_PRIM_LINES, 8);
+ if (proj_ok[0] || proj_ok[2] || proj_ok[1]) {
+ immBegin(GPU_PRIM_LINES, proj_ok[0] * 2 + proj_ok[2] * 2 + proj_ok[1] * 4);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ if (proj_ok[0]) {
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ }
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ if (proj_ok[2]) {
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ }
- /* angle vertex */
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+ /* angle vertex */
+ if (proj_ok[1]) {
+ immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+ }
- immEnd();
+ immEnd();
+ }
GPU_blend(false);
}
@@ -729,10 +800,10 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);
/* draw text (bg) */
- {
+ if (proj_ok[1]) {
immUniformColor4fv(color_back);
GPU_blend(true);
- immRectf(shdr_pos,
+ immRectf(shdr_pos_2d,
posit[0] - bg_margin,
posit[1] - bg_margin,
posit[0] + bg_margin + numstr_size[0],
@@ -743,7 +814,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immUnbindProgram();
/* draw text */
- {
+ if (proj_ok[1]) {
BLF_color3ubv(blf_mono_font, color_text);
BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
BLF_rotation(blf_mono_font, 0.0f);
@@ -751,30 +822,6 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
}
}
else {
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
-
- immUniform1i("colors_len", 2); /* "advanced" mode */
- const float *col = is_act ? color_act : color_base;
- immUniformArray4fv(
- "colors",
- (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}},
- 2);
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
-
- immBegin(GPU_PRIM_LINES, 2);
-
- immVertex2fv(shdr_pos, co_ss[0]);
- immVertex2fv(shdr_pos, co_ss[2]);
-
- immEnd();
-
- immUnbindProgram();
-
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);
@@ -790,19 +837,25 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immUniformColor3ubv(color_wire);
- immBegin(GPU_PRIM_LINES, 4);
+ if (proj_ok[0] || proj_ok[2]) {
+ immBegin(GPU_PRIM_LINES, proj_ok[0] * 2 + proj_ok[2] * 2);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ if (proj_ok[0]) {
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ }
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ if (proj_ok[2]) {
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ }
- immEnd();
+ immEnd();
+ }
GPU_blend(false);
}
@@ -824,10 +877,10 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
posit[1] -= numstr_size[1] / 2.0f;
/* draw text (bg) */
- {
+ if (proj_ok[0] && proj_ok[2]) {
immUniformColor4fv(color_back);
GPU_blend(true);
- immRectf(shdr_pos,
+ immRectf(shdr_pos_2d,
posit[0] - bg_margin,
posit[1] - bg_margin,
posit[0] + bg_margin + numstr_size[0],
@@ -838,7 +891,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immUnbindProgram();
/* draw text */
- {
+ if (proj_ok[0] && proj_ok[2]) {
BLF_color3ubv(blf_mono_font, color_text);
BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
BLF_draw(blf_mono_font, numstr, sizeof(numstr));
@@ -849,27 +902,10 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
BLF_disable(blf_mono_font, BLF_ROTATION);
-#undef ARC_STEPS
-
- /* draw snap */
- if ((ruler_info->snap_flag & RULER_SNAP_OK) && (ruler_info->state == RULER_STATE_DRAG) &&
- (ruler_item->gz.interaction_data != NULL)) {
- RulerInteraction *inter = ruler_item->gz.interaction_data;
- /* size from drawSnapping */
- const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
- float co_ss_snap[3];
- ED_view3d_project_float_global(
- region, ruler_item->co[inter->co_index], co_ss_snap, V3D_PROJ_TEST_NOP);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPU_matrix_pop();
+ GPU_matrix_pop_projection();
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor3(TH_GIZMO_VIEW_ALIGN);
-
- imm_draw_circle_wire_2d(pos, co_ss_snap[0], co_ss_snap[1], size * U.pixelsize, 32);
-
- immUnbindProgram();
- }
+#undef ARC_STEPS
}
static int gizmo_ruler_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
@@ -902,35 +938,36 @@ static int gizmo_ruler_modal(bContext *C,
RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
RulerItem *ruler_item = (RulerItem *)gz;
ARegion *region = CTX_wm_region(C);
- bool do_cursor_update = false;
+ bool do_cursor_update = (event->val == KM_RELEASE) || (event->type == MOUSEMOVE);
ruler_info->region = region;
- switch (event->type) {
- case MOUSEMOVE: {
- do_cursor_update = true;
- break;
- }
- }
-
- const bool do_snap = tweak_flag & WM_GIZMO_TWEAK_SNAP;
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ const bool do_snap = !(tweak_flag & WM_GIZMO_TWEAK_SNAP);
+#endif
const bool do_thickness = tweak_flag & WM_GIZMO_TWEAK_PRECISE;
- if ((ruler_info->drag_state_prev.do_snap != do_snap) ||
- (ruler_info->drag_state_prev.do_thickness != do_thickness)) {
+ if ((ruler_info->drag_state_prev.do_thickness != do_thickness)) {
do_cursor_update = true;
}
if (do_cursor_update) {
if (ruler_info->state == RULER_STATE_DRAG) {
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- if (view3d_ruler_item_mousemove(
- depsgraph, ruler_info, ruler_item, event->mval, do_thickness, do_snap)) {
+ if (view3d_ruler_item_mousemove(depsgraph,
+ ruler_info,
+ ruler_item,
+ event->mval,
+ do_thickness
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ ,
+ do_snap
+#endif
+ )) {
do_draw = true;
}
}
}
- ruler_info->drag_state_prev.do_snap = do_snap;
ruler_info->drag_state_prev.do_thickness = do_thickness;
if (do_draw) {
@@ -957,7 +994,7 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
/* Add Center Point */
ruler_item_pick->flag |= RULERITEM_USE_ANGLE;
inter->co_index = 1;
- ruler_state_set(C, ruler_info, RULER_STATE_DRAG);
+ ruler_state_set(ruler_info, RULER_STATE_DRAG);
/* find the factor */
{
@@ -978,13 +1015,21 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
/* update the new location */
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- view3d_ruler_item_mousemove(
- depsgraph, ruler_info, ruler_item_pick, event->mval, false, false);
+ view3d_ruler_item_mousemove(depsgraph,
+ ruler_info,
+ ruler_item_pick,
+ event->mval,
+ false
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ ,
+ false
+#endif
+ );
}
}
else {
inter->co_index = gz->highlight_part;
- ruler_state_set(C, ruler_info, RULER_STATE_DRAG);
+ ruler_state_set(ruler_info, RULER_STATE_DRAG);
/* store the initial depth */
copy_v3_v3(inter->drag_start_co, ruler_item_pick->co[inter->co_index]);
@@ -997,6 +1042,28 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
ruler_item_pick->flag &= ~RULERITEM_USE_ANGLE_ACTIVE;
}
+ {
+ /* Set Snap prev point. */
+ float *prev_point;
+ if (ruler_item_pick->flag & RULERITEM_USE_ANGLE) {
+ prev_point = (inter->co_index != 1) ? ruler_item_pick->co[1] : NULL;
+ }
+ else if (inter->co_index == 0) {
+ prev_point = ruler_item_pick->co[2];
+ }
+ else {
+ prev_point = ruler_item_pick->co[0];
+ }
+
+ if (prev_point) {
+ RNA_property_float_set_array(
+ ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint, prev_point);
+ }
+ else {
+ RNA_property_unset(ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint);
+ }
+ }
+
ruler_info->item_active = ruler_item_pick;
return OPERATOR_RUNNING_MODAL;
@@ -1009,10 +1076,9 @@ static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel)
if (!cancel) {
if (ruler_info->state == RULER_STATE_DRAG) {
- if (ruler_info->snap_flag & RULER_SNAP_OK) {
- ruler_info->snap_flag &= ~RULER_SNAP_OK;
- }
- ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
+ WM_gizmo_set_flag(ruler_info->snap_data.gizmo, WM_GIZMO_HIDDEN, false);
+ RNA_property_unset(ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint);
+ ruler_state_set(ruler_info, RULER_STATE_NORMAL);
}
/* We could convert only the current gizmo, for now just re-generate. */
view3d_ruler_to_gpencil(C, gzgroup);
@@ -1022,7 +1088,7 @@ static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel)
MEM_SAFE_FREE(gz->interaction_data);
}
- ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
+ ruler_state_set(ruler_info, RULER_STATE_NORMAL);
}
static int gizmo_ruler_cursor_get(wmGizmo *gz)
@@ -1059,16 +1125,39 @@ static void WIDGETGROUP_ruler_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
RulerInfo *ruler_info = MEM_callocN(sizeof(RulerInfo), __func__);
+ wmGizmo *gizmo;
+ {
+ /* The gizmo snap has to be the first gizmo. */
+ const wmGizmoType *gzt_snap;
+ gzt_snap = WM_gizmotype_find("GIZMO_GT_snap_3d", true);
+ gizmo = WM_gizmo_new_ptr(gzt_snap, gzgroup, NULL);
+ RNA_enum_set(gizmo->ptr,
+ "snap_elements_force",
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
+ /* SCE_SNAP_MODE_VOLUME | SCE_SNAP_MODE_GRID | SCE_SNAP_MODE_INCREMENT | */
+ SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT));
+
+ WM_gizmo_set_color(gizmo, (float[4]){1.0f, 1.0f, 1.0f, 1.0f});
+
+ wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_ruler_add", true);
+ WM_gizmo_operator_set(gizmo, 0, ot, NULL);
+ }
+
if (view3d_ruler_from_gpencil(C, gzgroup)) {
/* nop */
}
+ wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
+
+ ruler_info->wm = wm;
ruler_info->win = win;
ruler_info->area = area;
ruler_info->region = region;
+ ruler_info->snap_data.gizmo = gizmo;
+ ruler_info->snap_data.prop_prevpoint = RNA_struct_find_property(gizmo->ptr, "prev_point");
gzgroup->customdata = ruler_info;
}
@@ -1078,7 +1167,7 @@ void VIEW3D_GGT_ruler(wmGizmoGroupType *gzgt)
gzgt->name = "Ruler Widgets";
gzgt->idname = view3d_gzgt_ruler_id;
- gzgt->flag |= WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
@@ -1132,8 +1221,20 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *e
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
/* snap the first point added, not essential but handy */
inter->co_index = 0;
- view3d_ruler_item_mousemove(depsgraph, ruler_info, ruler_item, event->mval, false, true);
+ view3d_ruler_item_mousemove(depsgraph,
+ ruler_info,
+ ruler_item,
+ event->mval,
+ false
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ ,
+ true
+#endif
+ );
copy_v3_v3(inter->drag_start_co, ruler_item->co[inter->co_index]);
+ RNA_property_float_set_array(ruler_info->snap_data.gizmo->ptr,
+ ruler_info->snap_data.prop_prevpoint,
+ inter->drag_start_co);
}
else {
negate_v3_v3(inter->drag_start_co, rv3d->ofs);
@@ -1152,6 +1253,7 @@ void VIEW3D_OT_ruler_add(wmOperatorType *ot)
/* identifiers */
ot->name = "Ruler Add";
ot->idname = "VIEW3D_OT_ruler_add";
+ ot->description = "Add ruler";
ot->invoke = view3d_ruler_add_invoke;
ot->poll = view3d_ruler_poll;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index c16131c8317..50cd71d7edc 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -213,6 +213,7 @@ 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);
+void viewplace_modal_keymap(struct wmKeyConfig *keyconf);
/* view3d_buttons.c */
void VIEW3D_OT_object_mode_pie_or_toggle(struct wmOperatorType *ot);
@@ -243,6 +244,9 @@ void VIEW3D_OT_snap_cursor_to_center(struct wmOperatorType *ot);
void VIEW3D_OT_snap_cursor_to_selected(struct wmOperatorType *ot);
void VIEW3D_OT_snap_cursor_to_active(struct wmOperatorType *ot);
+/* view3d_placement.c */
+void VIEW3D_OT_interactive_add(struct wmOperatorType *ot);
+
/* space_view3d.c */
extern const char *view3d_context_dir[]; /* doc access */
@@ -268,6 +272,8 @@ void VIEW3D_OT_ruler_remove(struct wmOperatorType *ot);
void VIEW3D_GT_navigate_rotate(struct wmGizmoType *gzt);
+void VIEW3D_GGT_placement(struct wmGizmoGroupType *gzgt);
+
/* workaround for trivial but noticeable camera bug caused by imprecision
* between view border calculation in 2D/3D space, workaround for bug [#28037].
* without this define we get the old behavior which is to try and align them
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index 2ad7797f6c8..91e629147f4 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -406,6 +406,7 @@ void nurbs_foreachScreenVert(ViewContext *vc,
BPoint *bp,
BezTriple *bezt,
int beztindex,
+ bool handles_visible,
const float screen_co_b[2]),
void *userData,
const eV3DProjTest clip_flag)
@@ -414,6 +415,8 @@ void nurbs_foreachScreenVert(ViewContext *vc,
Nurb *nu;
int i;
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ /* If no point in the triple is selected, the handles are invisible. */
+ const bool only_selected = (vc->v3d->overlay.handle_display == CURVE_HANDLE_SELECTED);
ED_view3d_check_mats_rv3d(vc->rv3d);
@@ -427,15 +430,17 @@ void nurbs_foreachScreenVert(ViewContext *vc,
BezTriple *bezt = &nu->bezt[i];
if (bezt->hide == 0) {
+ const bool handles_visible = (vc->v3d->overlay.handle_display != CURVE_HANDLE_NONE) &&
+ (!only_selected || BEZT_ISSEL_ANY(bezt));
float screen_co[2];
- if ((vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+ if (!handles_visible) {
if (ED_view3d_project_float_object(vc->region,
bezt->vec[1],
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
- func(userData, nu, NULL, bezt, 1, screen_co);
+ func(userData, nu, NULL, bezt, 1, false, screen_co);
}
}
else {
@@ -444,21 +449,21 @@ void nurbs_foreachScreenVert(ViewContext *vc,
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
- func(userData, nu, NULL, bezt, 0, screen_co);
+ func(userData, nu, NULL, bezt, 0, true, screen_co);
}
if (ED_view3d_project_float_object(vc->region,
bezt->vec[1],
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
- func(userData, nu, NULL, bezt, 1, screen_co);
+ func(userData, nu, NULL, bezt, 1, true, screen_co);
}
if (ED_view3d_project_float_object(vc->region,
bezt->vec[2],
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
- func(userData, nu, NULL, bezt, 2, screen_co);
+ func(userData, nu, NULL, bezt, 2, true, screen_co);
}
}
}
@@ -473,7 +478,7 @@ void nurbs_foreachScreenVert(ViewContext *vc,
if (ED_view3d_project_float_object(
vc->region, bp->vec, screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
- func(userData, nu, bp, NULL, -1, screen_co);
+ func(userData, nu, bp, NULL, -1, false, screen_co);
}
}
}
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 1ad3f8bb1f5..0770bac1313 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -211,6 +211,8 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_selected);
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_active);
+ WM_operatortype_append(VIEW3D_OT_interactive_add);
+
WM_operatortype_append(VIEW3D_OT_toggle_shading);
WM_operatortype_append(VIEW3D_OT_toggle_xray);
WM_operatortype_append(VIEW3D_OT_toggle_matcap_flip);
@@ -234,4 +236,5 @@ void view3d_keymap(wmKeyConfig *keyconf)
viewmove_modal_keymap(keyconf);
viewzoom_modal_keymap(keyconf);
viewdolly_modal_keymap(keyconf);
+ viewplace_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c
new file mode 100644
index 00000000000..f2b78bc2aaf
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_placement.c
@@ -0,0 +1,1153 @@
+/*
+ * 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
+ *
+ * Operator to interactively place data.
+ *
+ * Currently only adds meshes, but could add other kinds of data
+ * including library assets & non-mesh types.
+ */
+
+#include "BLI_math_vector.h"
+#include "MEM_guardedalloc.h"
+
+#include "DNA_collection_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_vfont_types.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_main.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_api.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "ED_gizmo_library.h"
+#include "ED_gizmo_utils.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_transform.h"
+#include "ED_transform_snap_object_context.h"
+#include "ED_view3d.h"
+
+#include "UI_resources.h"
+
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_state.h"
+
+#include "view3d_intern.h"
+
+static const char *view3d_gzgt_placement_id = "VIEW3D_GGT_placement";
+
+/* -------------------------------------------------------------------- */
+/** \name Local Types
+ * \{ */
+
+enum ePlace_PrimType {
+ PLACE_PRIMITIVE_TYPE_CUBE = 1,
+ PLACE_PRIMITIVE_TYPE_CYLINDER = 2,
+ PLACE_PRIMITIVE_TYPE_CONE = 3,
+ PLACE_PRIMITIVE_TYPE_SPHERE_UV = 4,
+ PLACE_PRIMITIVE_TYPE_SPHERE_ICO = 5,
+};
+
+enum ePlace_Origin {
+ PLACE_ORIGIN_BASE = 1,
+ PLACE_ORIGIN_CENTER = 2,
+};
+
+enum ePlace_Depth {
+ PLACE_DEPTH_SURFACE = 1,
+ PLACE_DEPTH_CURSOR_PLANE = 2,
+ PLACE_DEPTH_CURSOR_VIEW = 3,
+};
+
+struct InteractivePlaceData {
+ /* Window manager variables (set these even when waiting for input). */
+ Scene *scene;
+ ScrArea *area;
+ View3D *v3d;
+ ARegion *region;
+
+ /** Draw object preview region draw callback. */
+ void *draw_handle_view;
+
+ float co_src[3];
+
+ /** Primary & secondary steps. */
+ struct {
+ bool is_centered;
+ bool is_fixed_aspect;
+ float plane[4];
+ float co_dst[3];
+ } step[2];
+
+ float matrix_orient[3][3];
+ int orient_axis;
+
+ /** The tool option, if we start centered, invert toggling behavior. */
+ bool is_centered_init;
+
+ bool use_snap, is_snap_found, is_snap_invert;
+ float snap_co[3];
+
+ /** Can index into #InteractivePlaceData.step. */
+ enum {
+ STEP_BASE = 0,
+ STEP_DEPTH = 1,
+ } step_index;
+
+ enum ePlace_PrimType primitive_type;
+
+ /** Activated from the tool-system. */
+ bool use_tool;
+
+ /** Event used to start the operator. */
+ short launch_event;
+
+ /** When activated without a tool. */
+ bool wait_for_input;
+
+ /** Optional snap gizmo, needed for snapping. */
+ wmGizmo *snap_gizmo;
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Utilities
+ * \{ */
+
+/* On-screen snap distance. */
+#define MVAL_MAX_PX_DIST 12.0f
+
+static bool idp_snap_point_from_gizmo(wmGizmo *gz, float r_location[3])
+{
+ if (gz->state & WM_GIZMO_STATE_HIGHLIGHT) {
+ PropertyRNA *prop_location = RNA_struct_find_property(gz->ptr, "location");
+ RNA_property_float_get_array(gz->ptr, prop_location, r_location);
+ return true;
+ }
+ return false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Primitive Drawing (Cube, Cone, Cylinder...)
+ * \{ */
+
+static void draw_line_loop(float coords[][3], int coords_len, const float color[4])
+{
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ GPUVertBuf *vert = GPU_vertbuf_create_with_format(format);
+ GPU_vertbuf_data_alloc(vert, coords_len);
+
+ for (int i = 0; i < coords_len; i++) {
+ GPU_vertbuf_attr_set(vert, pos, i, coords[i]);
+ }
+
+ GPU_blend(true);
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vert, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+
+ GPU_batch_bind(batch);
+
+ GPU_batch_uniform_4fv(batch, "color", color);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
+ GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
+
+ GPU_batch_draw(batch);
+
+ GPU_batch_program_use_end(batch);
+
+ GPU_batch_discard(batch);
+ GPU_blend(false);
+}
+
+static void draw_line_pairs(float coords_a[][3],
+ float coords_b[][3],
+ int coords_len,
+ const float color[4])
+{
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ GPUVertBuf *vert = GPU_vertbuf_create_with_format(format);
+ GPU_vertbuf_data_alloc(vert, coords_len * 2);
+
+ for (int i = 0; i < coords_len; i++) {
+ GPU_vertbuf_attr_set(vert, pos, i * 2, coords_a[i]);
+ GPU_vertbuf_attr_set(vert, pos, (i * 2) + 1, coords_b[i]);
+ }
+
+ GPU_blend(true);
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_LINES, vert, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+
+ GPU_batch_bind(batch);
+
+ GPU_batch_uniform_4fv(batch, "color", color);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
+ GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
+
+ GPU_batch_draw(batch);
+
+ GPU_batch_program_use_end(batch);
+
+ GPU_batch_discard(batch);
+ GPU_blend(false);
+}
+
+static void draw_line_bounds(const BoundBox *bounds, const float color[4])
+{
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ int edges[12][2] = {
+ /* First side. */
+ {0, 1},
+ {1, 2},
+ {2, 3},
+ {3, 0},
+ /* Second side. */
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {7, 4},
+ /* Edges between. */
+ {0, 4},
+ {1, 5},
+ {2, 6},
+ {3, 7},
+ };
+
+ GPUVertBuf *vert = GPU_vertbuf_create_with_format(format);
+ GPU_vertbuf_data_alloc(vert, ARRAY_SIZE(edges) * 2);
+
+ for (int i = 0, j = 0; i < ARRAY_SIZE(edges); i++) {
+ GPU_vertbuf_attr_set(vert, pos, j++, bounds->vec[edges[i][0]]);
+ GPU_vertbuf_attr_set(vert, pos, j++, bounds->vec[edges[i][1]]);
+ }
+
+ GPU_blend(true);
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_LINES, vert, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+
+ GPU_batch_bind(batch);
+
+ GPU_batch_uniform_4fv(batch, "color", color);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
+ GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
+
+ GPU_batch_draw(batch);
+
+ GPU_batch_program_use_end(batch);
+
+ GPU_batch_discard(batch);
+ GPU_blend(false);
+}
+
+static bool calc_bbox(struct InteractivePlaceData *ipd, BoundBox *bounds)
+{
+ memset(bounds, 0x0, sizeof(*bounds));
+
+ if (compare_v3v3(ipd->co_src, ipd->step[0].co_dst, FLT_EPSILON)) {
+ return false;
+ }
+
+ float matrix_orient_inv[3][3];
+ invert_m3_m3(matrix_orient_inv, ipd->matrix_orient);
+
+ const int x_axis = (ipd->orient_axis + 1) % 3;
+ const int y_axis = (ipd->orient_axis + 2) % 3;
+
+ float quad_base[4][3];
+ float quad_secondary[4][3];
+
+ copy_v3_v3(quad_base[0], ipd->co_src);
+ copy_v3_v3(quad_base[2], ipd->step[0].co_dst);
+
+ /* Only set when we have a fixed aspect. */
+ float fixed_aspect_dimension;
+
+ /* *** Primary *** */
+
+ {
+ float delta_local[3];
+ float delta_a[3];
+ float delta_b[3];
+
+ sub_v3_v3v3(delta_local, ipd->step[0].co_dst, ipd->co_src);
+ mul_m3_v3(matrix_orient_inv, delta_local);
+
+ copy_v3_v3(delta_a, delta_local);
+ copy_v3_v3(delta_b, delta_local);
+ delta_a[ipd->orient_axis] = 0.0f;
+ delta_b[ipd->orient_axis] = 0.0f;
+
+ delta_a[x_axis] = 0.0f;
+ delta_b[y_axis] = 0.0f;
+
+ /* Assign here in case secondary */
+ fixed_aspect_dimension = max_ff(fabsf(delta_a[y_axis]), fabsf(delta_b[x_axis]));
+
+ if (ipd->step[0].is_fixed_aspect) {
+ delta_a[y_axis] = copysignf(fixed_aspect_dimension, delta_a[y_axis]);
+ delta_b[x_axis] = copysignf(fixed_aspect_dimension, delta_b[x_axis]);
+ }
+
+ mul_m3_v3(ipd->matrix_orient, delta_a);
+ mul_m3_v3(ipd->matrix_orient, delta_b);
+
+ if (ipd->step[0].is_fixed_aspect) {
+ /* Recalculate the destination point. */
+ copy_v3_v3(quad_base[2], ipd->co_src);
+ add_v3_v3(quad_base[2], delta_a);
+ add_v3_v3(quad_base[2], delta_b);
+ }
+
+ add_v3_v3v3(quad_base[1], ipd->co_src, delta_a);
+ add_v3_v3v3(quad_base[3], ipd->co_src, delta_b);
+ }
+
+ if (ipd->step[0].is_centered) {
+ /* Use a copy in case aspect was applied to the quad. */
+ float base_co_dst[3];
+ copy_v3_v3(base_co_dst, quad_base[2]);
+ for (int i = 0; i < 4; i++) {
+ sub_v3_v3(quad_base[i], base_co_dst);
+ mul_v3_fl(quad_base[i], 2.0f);
+ add_v3_v3(quad_base[i], base_co_dst);
+ }
+ }
+
+ /* *** Secondary *** */
+
+ float delta_local[3];
+ if (ipd->step_index == STEP_DEPTH) {
+ sub_v3_v3v3(delta_local, ipd->step[1].co_dst, ipd->step[0].co_dst);
+ }
+ else {
+ zero_v3(delta_local);
+ }
+
+ if (ipd->step[1].is_fixed_aspect) {
+ if (!is_zero_v3(delta_local)) {
+ normalize_v3_length(delta_local, fixed_aspect_dimension);
+ }
+ }
+
+ if (ipd->step[1].is_centered) {
+ for (int i = 0; i < ARRAY_SIZE(quad_base); i++) {
+ sub_v3_v3(quad_base[i], delta_local);
+ }
+ mul_v3_fl(delta_local, 2.0f);
+ }
+
+ if ((ipd->step_index == STEP_DEPTH) &&
+ (compare_v3v3(ipd->step[0].co_dst, ipd->step[1].co_dst, FLT_EPSILON) == false)) {
+
+ for (int i = 0; i < ARRAY_SIZE(quad_base); i++) {
+ add_v3_v3v3(quad_secondary[i], quad_base[i], delta_local);
+ }
+ }
+ else {
+ copy_v3_v3(quad_secondary[0], quad_base[0]);
+ copy_v3_v3(quad_secondary[1], quad_base[1]);
+ copy_v3_v3(quad_secondary[2], quad_base[2]);
+ copy_v3_v3(quad_secondary[3], quad_base[3]);
+ }
+
+ for (int i = 0; i < 4; i++) {
+ copy_v3_v3(bounds->vec[i], quad_base[i]);
+ copy_v3_v3(bounds->vec[i + 4], quad_secondary[i]);
+ }
+
+ return true;
+}
+
+static void draw_circle_in_quad(const float v1[2],
+ const float v2[2],
+ const float v3[2],
+ const float v4[2],
+ const int resolution,
+ const float color[4])
+{
+ /* This isn't so efficient. */
+ const float quad[4][2] = {
+ {-1, -1},
+ {+1, -1},
+ {+1, +1},
+ {-1, +1},
+ };
+
+ float(*coords)[3] = MEM_mallocN(sizeof(float[3]) * (resolution + 1), __func__);
+ for (int i = 0; i <= resolution; i++) {
+ float theta = ((2.0f * M_PI) * ((float)i / (float)resolution)) + 0.01f;
+ float x = cosf(theta);
+ float y = sinf(theta);
+ float pt[2] = {x, y};
+ float w[4];
+ barycentric_weights_v2_quad(UNPACK4(quad), pt, w);
+
+ float *co = coords[i];
+ zero_v3(co);
+ madd_v3_v3fl(co, v1, w[0]);
+ madd_v3_v3fl(co, v2, w[1]);
+ madd_v3_v3fl(co, v3, w[2]);
+ madd_v3_v3fl(co, v4, w[3]);
+ }
+ draw_line_loop(coords, resolution + 1, color);
+ MEM_freeN(coords);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Drawing Callbacks
+ * \{ */
+
+static void draw_primitive_view_impl(const struct bContext *C,
+ struct InteractivePlaceData *ipd,
+ const float color[4])
+{
+ UNUSED_VARS(C);
+
+ BoundBox bounds;
+ calc_bbox(ipd, &bounds);
+ draw_line_bounds(&bounds, color);
+
+ if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CUBE) {
+ /* pass */
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CYLINDER) {
+ draw_circle_in_quad(UNPACK4(bounds.vec), 32, color);
+ draw_circle_in_quad(UNPACK4((&bounds.vec[4])), 32, color);
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CONE) {
+ draw_circle_in_quad(UNPACK4(bounds.vec), 32, color);
+
+ float center[3];
+ mid_v3_v3v3v3v3(center, UNPACK4((&bounds.vec[4])));
+
+ float coords_a[4][3];
+ float coords_b[4][3];
+
+ for (int i = 0; i < 4; i++) {
+ copy_v3_v3(coords_a[i], center);
+ mid_v3_v3v3(coords_b[i], bounds.vec[i], bounds.vec[(i + 1) % 4]);
+ }
+
+ draw_line_pairs(coords_a, coords_b, 4, color);
+ }
+ else if (ELEM(ipd->primitive_type,
+ PLACE_PRIMITIVE_TYPE_SPHERE_UV,
+ PLACE_PRIMITIVE_TYPE_SPHERE_ICO)) {
+ /* See bound-box diagram for reference. */
+
+ /* Primary Side. */
+ float v01[3], v12[3], v23[3], v30[3];
+ mid_v3_v3v3(v01, bounds.vec[0], bounds.vec[1]);
+ mid_v3_v3v3(v12, bounds.vec[1], bounds.vec[2]);
+ mid_v3_v3v3(v23, bounds.vec[2], bounds.vec[3]);
+ mid_v3_v3v3(v30, bounds.vec[3], bounds.vec[0]);
+ /* Secondary Side. */
+ float v45[3], v56[3], v67[3], v74[3];
+ mid_v3_v3v3(v45, bounds.vec[4], bounds.vec[5]);
+ mid_v3_v3v3(v56, bounds.vec[5], bounds.vec[6]);
+ mid_v3_v3v3(v67, bounds.vec[6], bounds.vec[7]);
+ mid_v3_v3v3(v74, bounds.vec[7], bounds.vec[4]);
+ /* Edges between. */
+ float v04[3], v15[3], v26[3], v37[3];
+ mid_v3_v3v3(v04, bounds.vec[0], bounds.vec[4]);
+ mid_v3_v3v3(v15, bounds.vec[1], bounds.vec[5]);
+ mid_v3_v3v3(v26, bounds.vec[2], bounds.vec[6]);
+ mid_v3_v3v3(v37, bounds.vec[3], bounds.vec[7]);
+
+ draw_circle_in_quad(v01, v45, v67, v23, 32, color);
+ draw_circle_in_quad(v30, v12, v56, v74, 32, color);
+ draw_circle_in_quad(v04, v15, v26, v37, 32, color);
+ }
+}
+
+static void draw_primitive_view(const struct bContext *C, ARegion *UNUSED(region), void *arg)
+{
+ struct InteractivePlaceData *ipd = arg;
+ float color[4];
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, color);
+
+ const bool use_depth = !XRAY_ENABLED(ipd->v3d);
+ const bool depth_test_enabled = GPU_depth_test_enabled();
+
+ if (use_depth) {
+ GPU_depth_test(false);
+ color[3] = 0.15f;
+ draw_primitive_view_impl(C, ipd, color);
+ }
+
+ if (use_depth) {
+ GPU_depth_test(true);
+ }
+ color[3] = 1.0f;
+ draw_primitive_view_impl(C, ipd, color);
+
+ if (use_depth) {
+ if (depth_test_enabled == false) {
+ GPU_depth_test(false);
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Object Modal Operator
+ * \{ */
+
+/**
+ *
+ * */
+static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEvent *event)
+{
+
+ const int plane_axis = RNA_enum_get(op->ptr, "plane_axis");
+ const enum ePlace_Depth plane_depth = RNA_enum_get(op->ptr, "plane_depth");
+ const enum ePlace_Origin plane_origin = RNA_enum_get(op->ptr, "plane_origin");
+
+ struct InteractivePlaceData *ipd = op->customdata;
+
+ RegionView3D *rv3d = ipd->region->regiondata;
+
+ ipd->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
+
+ ED_transform_calc_orientation_from_type(C, ipd->matrix_orient);
+
+ ipd->orient_axis = plane_axis;
+ ipd->is_centered_init = (plane_origin == PLACE_ORIGIN_CENTER);
+ ipd->step[0].is_centered = ipd->is_centered_init;
+ ipd->step[1].is_centered = ipd->is_centered_init;
+ ipd->step_index = STEP_BASE;
+
+ /* Assign snap gizmo which is may be used as part of the tool. */
+ {
+ wmGizmoMap *gzmap = ipd->region->gizmo_map;
+ wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, view3d_gzgt_placement_id) : NULL;
+ if ((gzgroup != NULL) && gzgroup->gizmos.first) {
+ ipd->snap_gizmo = gzgroup->gizmos.first;
+ }
+ }
+
+ {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "primitive_type");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ ipd->primitive_type = RNA_property_enum_get(op->ptr, prop);
+ ipd->use_tool = false;
+ }
+ else {
+ ipd->use_tool = true;
+
+ /* Get from the tool, a bit of a non-standard way of operating. */
+ const bToolRef *tref = ipd->area->runtime.tool;
+ if (tref && STREQ(tref->idname, "builtin.primitive_cube_add")) {
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_CUBE;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.primitive_cylinder_add")) {
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_CYLINDER;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.primitive_cone_add")) {
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_CONE;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.primitive_uv_sphere_add")) {
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_SPHERE_UV;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.primitive_ico_sphere_add")) {
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_SPHERE_ICO;
+ }
+ else {
+ /* If the user runs this as an operator they should set the 'primitive_type',
+ * however running from operator search will end up at this point. */
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_CUBE;
+ ipd->use_tool = false;
+ }
+ }
+ }
+
+ UNUSED_VARS(C, event);
+
+ ipd->draw_handle_view = ED_region_draw_cb_activate(
+ ipd->region->type, draw_primitive_view, ipd, REGION_DRAW_POST_VIEW);
+
+ ED_region_tag_redraw(ipd->region);
+
+ plane_from_point_normal_v3(
+ ipd->step[0].plane, ipd->scene->cursor.location, ipd->matrix_orient[ipd->orient_axis]);
+
+ const float mval_fl[2] = {UNPACK2(event->mval)};
+
+ const bool is_snap_found = ipd->snap_gizmo ?
+ idp_snap_point_from_gizmo(ipd->snap_gizmo, ipd->co_src) :
+ false;
+ ipd->is_snap_invert = ipd->snap_gizmo ? ED_gizmotypes_snap_3d_invert_snap_get(ipd->snap_gizmo) :
+ false;
+ {
+ const ToolSettings *ts = ipd->scene->toolsettings;
+ ipd->use_snap = (ipd->is_snap_invert == !(ts->snap_flag & SCE_SNAP));
+ }
+
+ if (is_snap_found) {
+ /* pass */
+ }
+ else {
+ bool use_depth_fallback = true;
+ if (plane_depth == PLACE_DEPTH_CURSOR_VIEW) {
+ /* View plane. */
+ ED_view3d_win_to_3d(
+ ipd->v3d, ipd->region, ipd->scene->cursor.location, mval_fl, ipd->co_src);
+ use_depth_fallback = false;
+ }
+ else if (plane_depth == PLACE_DEPTH_SURFACE) {
+ SnapObjectContext *snap_context =
+ (ipd->snap_gizmo ? ED_gizmotypes_snap_3d_context_ensure(
+ ipd->scene, ipd->region, ipd->v3d, ipd->snap_gizmo) :
+ NULL);
+ if ((snap_context != NULL) &&
+ ED_transform_snap_object_project_view3d(snap_context,
+ CTX_data_ensure_evaluated_depsgraph(C),
+ SCE_SNAP_MODE_FACE,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ },
+ mval_fl,
+ NULL,
+ NULL,
+ ipd->co_src,
+ NULL)) {
+ use_depth_fallback = false;
+ }
+ }
+
+ /* Use as fallback to surface. */
+ if (use_depth_fallback || (plane_depth == PLACE_DEPTH_CURSOR_PLANE)) {
+ /* Cursor plane. */
+ float plane[4];
+ plane_from_point_normal_v3(
+ plane, ipd->scene->cursor.location, ipd->matrix_orient[ipd->orient_axis]);
+ if (ED_view3d_win_to_3d_on_plane(ipd->region, plane, mval_fl, false, ipd->co_src)) {
+ use_depth_fallback = false;
+ }
+ /* Even if the calculation works, it's possible the point found is behind the view. */
+ if (rv3d->is_persp) {
+ float dir[3];
+ sub_v3_v3v3(dir, rv3d->viewinv[3], ipd->co_src);
+ if (dot_v3v3(dir, rv3d->viewinv[2]) < ipd->v3d->clip_start) {
+ use_depth_fallback = true;
+ }
+ }
+ }
+
+ if (use_depth_fallback) {
+ float co_depth[3];
+ /* Fallback to view center. */
+ negate_v3_v3(co_depth, rv3d->ofs);
+ ED_view3d_win_to_3d(ipd->v3d, ipd->region, co_depth, mval_fl, ipd->co_src);
+ }
+ }
+
+ plane_from_point_normal_v3(
+ ipd->step[0].plane, ipd->co_src, ipd->matrix_orient[ipd->orient_axis]);
+
+ copy_v3_v3(ipd->step[0].co_dst, ipd->co_src);
+}
+
+static int view3d_interactive_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const bool wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input");
+
+ struct InteractivePlaceData *ipd = MEM_callocN(sizeof(*ipd), __func__);
+ op->customdata = ipd;
+
+ ipd->scene = CTX_data_scene(C);
+ ipd->area = CTX_wm_area(C);
+ ipd->region = CTX_wm_region(C);
+ ipd->v3d = CTX_wm_view3d(C);
+
+ if (wait_for_input) {
+ ipd->wait_for_input = true;
+ /* TODO: support snapping when not using with tool. */
+#if 0
+ WM_gizmo_group_type_ensure(view3d_gzgt_placement_id);
+#endif
+ }
+ else {
+ view3d_interactive_add_begin(C, op, event);
+ }
+
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void view3d_interactive_add_exit(bContext *C, wmOperator *op)
+{
+ UNUSED_VARS(C);
+
+ struct InteractivePlaceData *ipd = op->customdata;
+
+ ED_region_draw_cb_exit(ipd->region->type, ipd->draw_handle_view);
+
+ ED_region_tag_redraw(ipd->region);
+
+ MEM_freeN(ipd);
+}
+
+static void view3d_interactive_add_cancel(bContext *C, wmOperator *op)
+{
+ view3d_interactive_add_exit(C, op);
+}
+
+enum {
+ PLACE_MODAL_SNAP_ON,
+ PLACE_MODAL_SNAP_OFF,
+ PLACE_MODAL_FIXED_ASPECT_ON,
+ PLACE_MODAL_FIXED_ASPECT_OFF,
+ PLACE_MODAL_PIVOT_CENTER_ON,
+ PLACE_MODAL_PIVOT_CENTER_OFF,
+};
+
+void viewplace_modal_keymap(wmKeyConfig *keyconf)
+{
+ static const EnumPropertyItem modal_items[] = {
+ {PLACE_MODAL_SNAP_ON, "SNAP_ON", 0, "Snap On", ""},
+ {PLACE_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap Off", ""},
+ {PLACE_MODAL_FIXED_ASPECT_ON, "FIXED_ASPECT_ON", 0, "Fixed Aspect On", ""},
+ {PLACE_MODAL_FIXED_ASPECT_OFF, "FIXED_ASPECT_OFF", 0, "Fixed Aspect Off", ""},
+ {PLACE_MODAL_PIVOT_CENTER_ON, "PIVOT_CENTER_ON", 0, "Center Pivot On", ""},
+ {PLACE_MODAL_PIVOT_CENTER_OFF, "PIVOT_CENTER_OFF", 0, "Center Pivot Off", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ const char *keymap_name = "View3D Placement Modal Map";
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, keymap_name);
+
+ /* This function is called for each space-type, only needs to add map once. */
+ if (keymap && keymap->modal_items) {
+ return;
+ }
+
+ keymap = WM_modalkeymap_ensure(keyconf, keymap_name, modal_items);
+
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_interactive_add");
+}
+
+static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ UNUSED_VARS(C, op);
+
+ struct InteractivePlaceData *ipd = op->customdata;
+
+ ARegion *region = ipd->region;
+ bool do_redraw = false;
+ bool do_cursor_update = false;
+
+ /* Handle modal key-map. */
+ if (event->type == EVT_MODAL_MAP) {
+ bool is_fallthrough = false;
+ switch (event->val) {
+ case PLACE_MODAL_FIXED_ASPECT_ON: {
+ is_fallthrough = true;
+ ATTR_FALLTHROUGH;
+ }
+ case PLACE_MODAL_FIXED_ASPECT_OFF: {
+ ipd->step[ipd->step_index].is_fixed_aspect = is_fallthrough;
+ do_redraw = true;
+ break;
+ }
+ case PLACE_MODAL_PIVOT_CENTER_ON: {
+ is_fallthrough = true;
+ ATTR_FALLTHROUGH;
+ }
+ case PLACE_MODAL_PIVOT_CENTER_OFF: {
+ ipd->step[ipd->step_index].is_centered = is_fallthrough;
+ do_redraw = true;
+ break;
+ }
+ case PLACE_MODAL_SNAP_ON: {
+ is_fallthrough = true;
+ ATTR_FALLTHROUGH;
+ }
+ case PLACE_MODAL_SNAP_OFF: {
+ const ToolSettings *ts = ipd->scene->toolsettings;
+ ipd->is_snap_invert = is_fallthrough;
+ ipd->use_snap = (ipd->is_snap_invert == !(ts->snap_flag & SCE_SNAP));
+ do_cursor_update = true;
+ break;
+ }
+ }
+ }
+
+ if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
+ view3d_interactive_add_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ else if (event->type == MOUSEMOVE) {
+ do_cursor_update = true;
+ }
+
+ if (ipd->wait_for_input) {
+ if (ELEM(event->type, LEFTMOUSE)) {
+ if (event->val == KM_PRESS) {
+ view3d_interactive_add_begin(C, op, event);
+ ipd->wait_for_input = false;
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ if (ipd->step_index == STEP_BASE) {
+ if (ELEM(event->type, ipd->launch_event, LEFTMOUSE)) {
+ if (event->val == KM_RELEASE) {
+ /* Set secondary plane. */
+
+ /* Create normal. */
+ {
+ RegionView3D *rv3d = region->regiondata;
+ float no_temp[3];
+ float no[3];
+ cross_v3_v3v3(no_temp, ipd->step[0].plane, rv3d->viewinv[2]);
+ cross_v3_v3v3(no, no_temp, ipd->step[0].plane);
+ normalize_v3(no);
+
+ plane_from_point_normal_v3(ipd->step[1].plane, ipd->step[0].co_dst, no);
+ }
+
+ copy_v3_v3(ipd->step[1].co_dst, ipd->step[0].co_dst);
+ ipd->step_index = STEP_DEPTH;
+
+ /* Keep these values from the previous step. */
+ ipd->step[1].is_centered = ipd->step[0].is_centered;
+ ipd->step[1].is_fixed_aspect = ipd->step[0].is_fixed_aspect;
+ }
+ }
+ }
+ else if (ipd->step_index == STEP_DEPTH) {
+ if (ELEM(event->type, ipd->launch_event, LEFTMOUSE)) {
+ if (event->val == KM_PRESS) {
+
+ BoundBox bounds;
+ calc_bbox(ipd, &bounds);
+
+ float location[3];
+ float rotation[3];
+ float scale[3];
+
+ float matrix_orient_axis[3][3];
+ copy_m3_m3(matrix_orient_axis, ipd->matrix_orient);
+ if (ipd->orient_axis != 2) {
+ swap_v3_v3(matrix_orient_axis[2], matrix_orient_axis[ipd->orient_axis]);
+ swap_v3_v3(matrix_orient_axis[0], matrix_orient_axis[1]);
+ }
+ /* Needed for shapes where the sign matters (cone for eg). */
+ {
+ float delta[3];
+ sub_v3_v3v3(delta, bounds.vec[0], bounds.vec[4]);
+ if (dot_v3v3(ipd->matrix_orient[ipd->orient_axis], delta) > 0.0f) {
+ negate_v3(matrix_orient_axis[2]);
+
+ /* Only flip Y so we don't flip a single axis which causes problems. */
+ negate_v3(matrix_orient_axis[1]);
+ }
+ }
+
+ mat3_to_eul(rotation, matrix_orient_axis);
+
+ mid_v3_v3v3(location, bounds.vec[0], bounds.vec[6]);
+ const int cube_verts[3] = {3, 1, 4};
+ for (int i = 0; i < 3; i++) {
+ scale[i] = len_v3v3(bounds.vec[0], bounds.vec[cube_verts[i]]);
+ }
+
+ wmOperatorType *ot = NULL;
+ PointerRNA op_props;
+ if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CUBE) {
+ ot = WM_operatortype_find("MESH_OT_primitive_cube_add", false);
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CYLINDER) {
+ ot = WM_operatortype_find("MESH_OT_primitive_cylinder_add", false);
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CONE) {
+ ot = WM_operatortype_find("MESH_OT_primitive_cone_add", false);
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_SPHERE_UV) {
+ ot = WM_operatortype_find("MESH_OT_primitive_uv_sphere_add", false);
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_SPHERE_ICO) {
+ ot = WM_operatortype_find("MESH_OT_primitive_ico_sphere_add", false);
+ }
+
+ if (ot != NULL) {
+ WM_operator_properties_create_ptr(&op_props, ot);
+
+ if (ipd->use_tool) {
+ bToolRef *tref = ipd->area->runtime.tool;
+ PointerRNA temp_props;
+ WM_toolsystem_ref_properties_init_for_keymap(tref, &temp_props, &op_props, ot);
+ SWAP(PointerRNA, temp_props, op_props);
+ WM_operator_properties_free(&temp_props);
+ }
+
+ RNA_float_set_array(&op_props, "rotation", rotation);
+ RNA_float_set_array(&op_props, "location", location);
+ RNA_float_set_array(&op_props, "scale", scale);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props);
+ WM_operator_properties_free(&op_props);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ view3d_interactive_add_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (do_cursor_update) {
+ const float mval_fl[2] = {UNPACK2(event->mval)};
+
+ /* Calculate the snap location on mouse-move or when toggling snap. */
+ bool is_snap_found_prev = ipd->is_snap_found;
+ ipd->is_snap_found = false;
+ if (ipd->use_snap) {
+ if (ipd->snap_gizmo != NULL) {
+ ED_gizmotypes_snap_3d_toggle_set(ipd->snap_gizmo, ipd->use_snap);
+ if (ED_gizmotypes_snap_3d_update(ipd->snap_gizmo,
+ CTX_data_ensure_evaluated_depsgraph(C),
+ ipd->region,
+ ipd->v3d,
+ NULL,
+ mval_fl,
+ ipd->snap_co,
+ NULL)) {
+ ipd->is_snap_found = true;
+ }
+ ED_gizmotypes_snap_3d_toggle_clear(ipd->snap_gizmo);
+ }
+ }
+
+ /* Workaround because test_select doesn't run at the same time as the modal operator. */
+ if (is_snap_found_prev != ipd->is_snap_found) {
+ wmGizmoMap *gzmap = ipd->region->gizmo_map;
+ WM_gizmo_highlight_set(gzmap, ipd->is_snap_found ? ipd->snap_gizmo : NULL);
+ }
+
+ if (ipd->step_index == STEP_BASE) {
+ if (ipd->is_snap_found) {
+ closest_to_plane_normalized_v3(ipd->step[0].co_dst, ipd->step[0].plane, ipd->snap_co);
+ }
+ else {
+ if (ED_view3d_win_to_3d_on_plane(
+ region, ipd->step[0].plane, mval_fl, false, ipd->step[0].co_dst)) {
+ /* pass */
+ }
+ }
+ }
+ else if (ipd->step_index == STEP_DEPTH) {
+ if (ipd->is_snap_found) {
+ closest_to_plane_normalized_v3(ipd->step[1].co_dst, ipd->step[1].plane, ipd->snap_co);
+ }
+ else {
+ if (ED_view3d_win_to_3d_on_plane(
+ region, ipd->step[1].plane, mval_fl, false, ipd->step[1].co_dst)) {
+ /* pass */
+ }
+ }
+
+ /* Correct the point so it's aligned with the 'ipd->step[0].co_dst'. */
+ float close[3], delta[3];
+ closest_to_plane_normalized_v3(close, ipd->step[0].plane, ipd->step[1].co_dst);
+ sub_v3_v3v3(delta, close, ipd->step[0].co_dst);
+ sub_v3_v3(ipd->step[1].co_dst, delta);
+ }
+ do_redraw = true;
+ }
+
+ if (do_redraw) {
+ ED_region_tag_redraw(region);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static bool view3d_interactive_add_poll(bContext *C)
+{
+ const enum eContextObjectMode mode = CTX_data_mode_enum(C);
+ return ELEM(mode, CTX_MODE_OBJECT, CTX_MODE_EDIT_MESH);
+}
+
+void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Primitive Object";
+ ot->description = "Interactively add an object";
+ ot->idname = "VIEW3D_OT_interactive_add";
+
+ /* api callbacks */
+ ot->invoke = view3d_interactive_add_invoke;
+ ot->modal = view3d_interactive_add_modal;
+ ot->cancel = view3d_interactive_add_cancel;
+ ot->poll = view3d_interactive_add_poll;
+
+ /* Note, let the operator we call handle undo and registering it's self. */
+ /* flags */
+ ot->flag = 0;
+
+ /* properties */
+ PropertyRNA *prop;
+
+ /* Normally not accessed directly, leave unset and check the active tool. */
+ static const EnumPropertyItem primitive_type[] = {
+ {PLACE_PRIMITIVE_TYPE_CUBE, "CUBE", 0, "Cube", ""},
+ {PLACE_PRIMITIVE_TYPE_CYLINDER, "CYLINDER", 0, "Cylinder", ""},
+ {PLACE_PRIMITIVE_TYPE_CONE, "CONE", 0, "Cone", ""},
+ {PLACE_PRIMITIVE_TYPE_SPHERE_UV, "SPHERE_UV", 0, "UV Sphere", ""},
+ {PLACE_PRIMITIVE_TYPE_SPHERE_ICO, "SPHERE_ICO", 0, "ICO Sphere", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ prop = RNA_def_property(ot->srna, "primitive_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Primitive", "");
+ RNA_def_property_enum_items(prop, primitive_type);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_property(ot->srna, "plane_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Plane Axis", "The axis used for placing the base region");
+ RNA_def_property_enum_default(prop, 2);
+ RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ static const EnumPropertyItem plane_depth_items[] = {
+ {PLACE_DEPTH_SURFACE,
+ "SURFACE",
+ 0,
+ "Surface",
+ "Start placing on the surface, using the 3D cursor position as a fallback"},
+ {PLACE_DEPTH_CURSOR_PLANE,
+ "CURSOR_PLANE",
+ 0,
+ "3D Cursor Plane",
+ "Start placement using a point projected onto the selected axis at the 3D cursor position"},
+ {PLACE_DEPTH_CURSOR_VIEW,
+ "CURSOR_VIEW",
+ 0,
+ "3D Cursor View",
+ "Start placement using the mouse cursor projected onto the view plane"},
+ {0, NULL, 0, NULL, NULL},
+ };
+ prop = RNA_def_property(ot->srna, "plane_depth", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Position", "The initial depth used when placing the cursor");
+ RNA_def_property_enum_default(prop, PLACE_DEPTH_SURFACE);
+ RNA_def_property_enum_items(prop, plane_depth_items);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ static const EnumPropertyItem origin_items[] = {
+ {PLACE_ORIGIN_BASE, "BASE", 0, "Base", "Start placing the corner position"},
+ {PLACE_ORIGIN_CENTER, "CENTER", 0, "Center", "Start placing the center position"},
+ {0, NULL, 0, NULL, NULL},
+ };
+ prop = RNA_def_property(ot->srna, "plane_origin", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Origin", "The initial position for placement");
+ RNA_def_property_enum_default(prop, PLACE_ORIGIN_BASE);
+ RNA_def_property_enum_items(prop, origin_items);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ /* When not accessed via a tool. */
+ prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Placement Gizmo Group
+ *
+ * This is currently only used for snapping before the tool is initialized,
+ * we could show a placement plane here.
+ * \{ */
+
+static void WIDGETGROUP_placement_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
+{
+ wmGizmo *gizmo;
+
+ {
+ /* The gizmo snap has to be the first gizmo. */
+ const wmGizmoType *gzt_snap;
+ gzt_snap = WM_gizmotype_find("GIZMO_GT_snap_3d", true);
+ gizmo = WM_gizmo_new_ptr(gzt_snap, gzgroup, NULL);
+ RNA_enum_set(gizmo->ptr,
+ "snap_elements_force",
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
+ /* SCE_SNAP_MODE_VOLUME | SCE_SNAP_MODE_GRID | SCE_SNAP_MODE_INCREMENT | */
+ SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT));
+
+ WM_gizmo_set_color(gizmo, (float[4]){1.0f, 1.0f, 1.0f, 1.0f});
+
+ /* Don't handle any events, this is for display only. */
+ gizmo->flag |= WM_GIZMO_HIDDEN_KEYMAP;
+ }
+}
+
+void VIEW3D_GGT_placement(wmGizmoGroupType *gzgt)
+{
+ gzgt->name = "Placement Widget";
+ gzgt->idname = view3d_gzgt_placement_id;
+
+ gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
+
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+
+ gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
+ gzgt->setup = WIDGETGROUP_placement_setup;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 2ce2edb98fe..8c60e36a141 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -411,6 +411,7 @@ typedef struct LassoSelectUserData {
const int (*mcoords)[2];
int mcoords_len;
eSelectOp sel_op;
+ eBezTriple_Flag select_flag;
/* runtime */
int pass;
@@ -434,6 +435,8 @@ static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
r_data->mcoords = mcoords;
r_data->mcoords_len = mcoords_len;
r_data->sel_op = sel_op;
+ /* SELECT by default, but can be changed if needed (only few cases use and respect this). */
+ r_data->select_flag = SELECT;
/* runtime */
r_data->pass = 0;
@@ -903,6 +906,7 @@ static void do_lasso_select_curve__doSelect(void *userData,
BPoint *bp,
BezTriple *bezt,
int beztindex,
+ bool handles_visible,
const float screen_co[2])
{
LassoSelectUserData *data = userData;
@@ -913,17 +917,17 @@ static void do_lasso_select_curve__doSelect(void *userData,
const bool is_select = bp->f1 & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(bp->f1, sel_op_result, data->select_flag);
data->is_changed = true;
}
}
else {
- if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- /* can only be (beztindex == 0) here since handles are hidden */
+ if (!handles_visible) {
+ /* can only be (beztindex == 1) here since handles are hidden */
const bool is_select = bezt->f2 & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, data->select_flag);
}
bezt->f1 = bezt->f3 = bezt->f2;
data->is_changed = true;
@@ -933,7 +937,7 @@ static void do_lasso_select_curve__doSelect(void *userData,
const bool is_select = *flag_p & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(*flag_p, sel_op_result, data->select_flag);
data->is_changed = true;
}
}
@@ -945,6 +949,7 @@ static bool do_lasso_select_curve(ViewContext *vc,
const int mcoords_len,
const eSelectOp sel_op)
{
+ const bool deselect_all = (sel_op == SEL_OP_SET);
LassoSelectUserData data;
rcti rect;
@@ -952,13 +957,23 @@ static bool do_lasso_select_curve(ViewContext *vc,
view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- Curve *curve = (Curve *)vc->obedit->data;
- data.is_changed |= ED_curve_deselect_all(curve->editnurb);
+ Curve *curve = (Curve *)vc->obedit->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(curve);
+
+ /* For deselect all, items to be selected are tagged with temp flag. Clear that first. */
+ if (deselect_all) {
+ BKE_nurbList_flag_set(nurbs, BEZT_FLAG_TEMP_TAG, false);
+ data.select_flag = BEZT_FLAG_TEMP_TAG;
}
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ /* Deselect items that were not added to selection (indicated by temp flag). */
+ if (deselect_all) {
+ BKE_nurbList_flag_set_from_flag(nurbs, BEZT_FLAG_TEMP_TAG, SELECT);
+ }
+
if (data.is_changed) {
BKE_curve_nurb_vert_active_validate(vc->obedit->data);
}
@@ -2559,6 +2574,7 @@ typedef struct BoxSelectUserData {
const rctf *rect_fl;
rctf _rect_fl;
eSelectOp sel_op;
+ eBezTriple_Flag select_flag;
/* runtime */
bool is_done;
@@ -2577,6 +2593,8 @@ static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data,
BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
r_data->sel_op = sel_op;
+ /* SELECT by default, but can be changed if needed (only few cases use and respect this). */
+ r_data->select_flag = SELECT;
/* runtime */
r_data->is_done = false;
@@ -2707,6 +2725,7 @@ static void do_nurbs_box_select__doSelect(void *userData,
BPoint *bp,
BezTriple *bezt,
int beztindex,
+ bool handles_visible,
const float screen_co[2])
{
BoxSelectUserData *data = userData;
@@ -2716,17 +2735,17 @@ static void do_nurbs_box_select__doSelect(void *userData,
const bool is_select = bp->f1 & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(bp->f1, sel_op_result, data->select_flag);
data->is_changed = true;
}
}
else {
- if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- /* can only be (beztindex == 0) here since handles are hidden */
+ if (!handles_visible) {
+ /* can only be (beztindex == 1) here since handles are hidden */
const bool is_select = bezt->f2 & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, data->select_flag);
data->is_changed = true;
}
bezt->f1 = bezt->f3 = bezt->f2;
@@ -2736,7 +2755,7 @@ static void do_nurbs_box_select__doSelect(void *userData,
const bool is_select = *flag_p & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(*flag_p, sel_op_result, data->select_flag);
data->is_changed = true;
}
}
@@ -2744,17 +2763,28 @@ static void do_nurbs_box_select__doSelect(void *userData,
}
static bool do_nurbs_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
+ const bool deselect_all = (sel_op == SEL_OP_SET);
BoxSelectUserData data;
view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- Curve *curve = (Curve *)vc->obedit->data;
- data.is_changed |= ED_curve_deselect_all(curve->editnurb);
+ Curve *curve = (Curve *)vc->obedit->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(curve);
+
+ /* For deselect all, items to be selected are tagged with temp flag. Clear that first. */
+ if (deselect_all) {
+ BKE_nurbList_flag_set(nurbs, BEZT_FLAG_TEMP_TAG, false);
+ data.select_flag = BEZT_FLAG_TEMP_TAG;
}
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ /* Deselect items that were not added to selection (indicated by temp flag). */
+ if (deselect_all) {
+ BKE_nurbList_flag_set_from_flag(nurbs, BEZT_FLAG_TEMP_TAG, SELECT);
+ }
+
BKE_curve_nurb_vert_active_validate(vc->obedit->data);
return data.is_changed;
@@ -3393,6 +3423,7 @@ typedef struct CircleSelectUserData {
float mval_fl[2];
float radius;
float radius_squared;
+ eBezTriple_Flag select_flag;
/* runtime */
bool is_changed;
@@ -3413,6 +3444,9 @@ static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data,
r_data->radius = rad;
r_data->radius_squared = rad * rad;
+ /* SELECT by default, but can be changed if needed (only few cases use and respect this). */
+ r_data->select_flag = SELECT;
+
/* runtime */
r_data->is_changed = false;
}
@@ -3650,29 +3684,24 @@ static void nurbscurve_circle_doSelect(void *userData,
BPoint *bp,
BezTriple *bezt,
int beztindex,
+ bool UNUSED(handles_visible),
const float screen_co[2])
{
CircleSelectUserData *data = userData;
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
if (bp) {
- bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
+ SET_FLAG_FROM_TEST(bp->f1, data->select, data->select_flag);
}
else {
- if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- /* can only be (beztindex == 0) here since handles are hidden */
- bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
+ if (beztindex == 0) {
+ SET_FLAG_FROM_TEST(bezt->f1, data->select, data->select_flag);
+ }
+ else if (beztindex == 1) {
+ SET_FLAG_FROM_TEST(bezt->f2, data->select, data->select_flag);
}
else {
- if (beztindex == 0) {
- bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT);
- }
- else if (beztindex == 1) {
- bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
- }
- else {
- bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
- }
+ SET_FLAG_FROM_TEST(bezt->f3, data->select, data->select_flag);
}
}
data->is_changed = true;
@@ -3683,18 +3712,30 @@ static bool nurbscurve_circle_select(ViewContext *vc,
const int mval[2],
float rad)
{
+ const bool select = (sel_op != SEL_OP_SUB);
+ const bool deselect_all = (sel_op == SEL_OP_SET);
CircleSelectUserData data;
bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- Curve *curve = vc->obedit->data;
- changed |= ED_curve_deselect_all(curve->editnurb);
- }
- const bool select = (sel_op != SEL_OP_SUB);
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+ Curve *curve = (Curve *)vc->obedit->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(curve);
+
+ /* For deselect all, items to be selected are tagged with temp flag. Clear that first. */
+ if (deselect_all) {
+ BKE_nurbList_flag_set(nurbs, BEZT_FLAG_TEMP_TAG, false);
+ data.select_flag = BEZT_FLAG_TEMP_TAG;
+ }
+
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ /* Deselect items that were not added to selection (indicated by temp flag). */
+ if (deselect_all) {
+ BKE_nurbList_flag_set_from_flag(nurbs, BEZT_FLAG_TEMP_TAG, SELECT);
+ }
+
BKE_curve_nurb_vert_active_validate(vc->obedit->data);
return changed || data.is_changed;
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 09e1dca3152..377e8c58ba3 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -86,6 +86,26 @@ void ED_view3d_background_color_get(const Scene *scene, const View3D *v3d, float
UI_GetThemeColor3fv(TH_BACK, r_color);
}
+bool ED_view3d_has_workbench_in_texture_color(const Scene *scene,
+ const Object *ob,
+ const View3D *v3d)
+{
+ if (v3d->shading.type == OB_SOLID) {
+ if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) {
+ return true;
+ }
+ if (ob->mode == OB_MODE_TEXTURE_PAINT) {
+ return true;
+ }
+ }
+ else if (v3d->shading.type == OB_RENDER) {
+ if (STREQ(scene->r.engine, RE_engine_id_BLENDER_WORKBENCH)) {
+ return scene->display.shading.color_type == V3D_SHADING_TEXTURE_COLOR;
+ }
+ }
+ return false;
+}
+
Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
{
/* establish the camera object,
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 8ee52756f27..7aefd173953 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -374,16 +374,19 @@ static bool walk_floor_distance_get(RegionView3D *rv3d,
mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
add_v3_v3(ray_start, dvec_tmp);
- ret = ED_transform_snap_object_project_ray(walk->snap_context,
- walk->depsgraph,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- },
- ray_start,
- ray_normal,
- r_distance,
- r_location,
- r_normal_dummy);
+ ret = ED_transform_snap_object_project_ray(
+ walk->snap_context,
+ walk->depsgraph,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ /* Avoid having to convert the edit-mesh to a regular mesh. */
+ .use_object_edit_cage = true,
+ },
+ ray_start,
+ ray_normal,
+ r_distance,
+ r_location,
+ r_normal_dummy);
/* artificially scale the distance to the scene size */
*r_distance /= walk->grid;
@@ -449,7 +452,6 @@ static float userdef_speed = -1.f;
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
- Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
walk->rv3d = CTX_wm_region_view3d(C);
@@ -553,7 +555,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->rv3d->rflag |= RV3D_NAVIGATING;
walk->snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, walk->scene, 0, walk->region, walk->v3d);
+ walk->scene, 0, walk->region, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
walk->depsgraph,
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index bb4291555d0..79090bd633e 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -49,6 +49,7 @@
#include "ED_space_api.h"
#include "WM_api.h"
+#include "WM_message.h"
#include "WM_types.h"
#include "UI_interface_icons.h"
@@ -825,17 +826,17 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, bool is
}
}
else if (!edit_2d) {
- if (t->orientation.index == 0 || ELEM(cmode, '\0', axis)) {
+ if (t->orient_curr == 0 || ELEM(cmode, '\0', axis)) {
/* Successive presses on existing axis, cycle orientation modes. */
- t->orientation.index = (t->orientation.index + 1) % ARRAY_SIZE(t->orientation.types);
- initTransformOrientation(t->context, t, t->orientation.types[t->orientation.index]);
+ t->orient_curr = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient));
+ transform_orientations_current_set(t, t->orient_curr);
}
- if (t->orientation.index == 0) {
+ if (t->orient_curr == 0) {
stopConstraint(t);
}
else {
- const short orientation = t->orientation.types[t->orientation.index];
+ const short orientation = t->orient[t->orient_curr].type;
if (is_plane == false) {
setUserConstraint(t, orientation, constraint_axis, msg2);
}
@@ -983,7 +984,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
}
else if (transform_mode_is_changeable(t->mode)) {
/* Scale isn't normally very useful after extrude along normals, see T39756 */
- if ((t->con.mode & CON_APPLY) && (t->con.orientation == V3D_ORIENT_NORMAL)) {
+ if ((t->con.mode & CON_APPLY) && (t->orient[t->orient_curr].type == V3D_ORIENT_NORMAL)) {
stopConstraint(t);
}
@@ -1195,7 +1196,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
stopConstraint(t);
}
else {
- initSelectConstraint(t, event->shift);
+ initSelectConstraint(t);
postSelectConstraint(t);
}
}
@@ -1601,8 +1602,8 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
mul_m3_v3(t->spacemtx, t->values_final);
unit_m3(t->spacemtx);
- BLI_assert(t->orientation.index == 0);
- t->orientation.types[0] = V3D_ORIENT_GLOBAL;
+ BLI_assert(t->orient_curr == 0);
+ t->orient[0].type = V3D_ORIENT_GLOBAL;
}
// Save back mode in case we're in the generic operator
@@ -1672,11 +1673,14 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
if (t->flag & T_MODAL) {
/* do we check for parameter? */
if (transformModeUseSnap(t)) {
- if (t->modifiers & MOD_SNAP) {
- ts->snap_flag |= SCE_SNAP;
- }
- else {
- ts->snap_flag &= ~SCE_SNAP;
+ if (!(t->modifiers & MOD_SNAP) != !(ts->snap_flag & SCE_SNAP)) {
+ if (t->modifiers & MOD_SNAP) {
+ ts->snap_flag |= SCE_SNAP;
+ }
+ else {
+ ts->snap_flag &= ~SCE_SNAP;
+ }
+ WM_msg_publish_rna_prop(t->mbus, &t->scene->id, ts, ToolSettings, use_snap);
}
}
}
@@ -1713,19 +1717,20 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
if ((prop = RNA_struct_find_property(op->ptr, "orient_type"))) {
- short orient_set, orient_cur;
- orient_set = RNA_property_is_set(op->ptr, prop) ? RNA_property_enum_get(op->ptr, prop) : -1;
- orient_cur = t->orientation.types[t->orientation.index];
+ short orient_type_set, orient_type_curr;
+ orient_type_set = RNA_property_is_set(op->ptr, prop) ? RNA_property_enum_get(op->ptr, prop) :
+ -1;
+ orient_type_curr = t->orient[t->orient_curr].type;
- if (!ELEM(orient_cur, orient_set, V3D_ORIENT_CUSTOM_MATRIX)) {
- RNA_property_enum_set(op->ptr, prop, orient_cur);
- orient_set = orient_cur;
+ if (!ELEM(orient_type_curr, orient_type_set, V3D_ORIENT_CUSTOM_MATRIX)) {
+ RNA_property_enum_set(op->ptr, prop, orient_type_curr);
+ orient_type_set = orient_type_curr;
}
if (((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) &&
!RNA_property_is_set(op->ptr, prop))) {
/* Set the first time to register on redo. */
- RNA_property_enum_set(op->ptr, prop, orient_set);
+ RNA_property_enum_set(op->ptr, prop, orient_type_set);
RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]);
}
}
@@ -1873,11 +1878,8 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
initTransInfo(C, t, op, event);
/* Use the custom orientation when it is set. */
- short orientation = t->orientation.types[0] == V3D_ORIENT_CUSTOM_MATRIX ?
- V3D_ORIENT_CUSTOM_MATRIX :
- t->orientation.types[t->orientation.index];
-
- initTransformOrientation(C, t, orientation);
+ short orient_index = t->orient[0].type == V3D_ORIENT_CUSTOM_MATRIX ? 0 : t->orient_curr;
+ transform_orientations_current_set(t, orient_index);
if (t->spacetype == SPACE_VIEW3D) {
t->draw_handle_apply = ED_region_draw_cb_activate(
@@ -1886,62 +1888,38 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_pixel = ED_region_draw_cb_activate(
t->region->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_IMAGE) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_CLIP) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_NODE) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_GRAPH) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_ACTION) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
createTransData(C, t); // make TransData structs from selection
@@ -2033,7 +2011,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
/* Constraint init from operator */
if (t->con.mode & CON_APPLY) {
- setUserConstraint(t, t->orientation.types[t->orientation.index], t->con.mode, "%s");
+ setUserConstraint(t, t->orient[t->orient_curr].type, t->con.mode, "%s");
}
/* Don't write into the values when non-modal because they are already set from operator redo
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 9f4b3773fd8..192728f63d2 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -113,13 +113,8 @@ typedef struct TransSnap {
} TransSnap;
typedef struct TransCon {
- short orientation;
/** Description of the constraint for header_print. */
char text[50];
- /** Matrix of the constraint space. */
- float mtx[3][3];
- /** Inverse matrix of the constraint space. */
- float imtx[3][3];
/** Projection constraint matrix (same as #imtx with some axis == 0). */
float pmtx[3][3];
/** Initial mouse value for visual calculation
@@ -531,13 +526,11 @@ typedef struct TransInfo {
bool is_launch_event_tweak;
struct {
- short index;
- short types[3];
- /* this gets used when orientation.type[x] is V3D_ORIENT_CUSTOM */
- struct TransformOrientation *custom;
- /* this gets used when orientation.type[0] is V3D_ORIENT_CUSTOM_MATRIX */
- float custom_matrix[3][3];
- } orientation;
+ short type;
+ float matrix[3][3];
+ } orient[3];
+ short orient_curr;
+
/** backup from view3d, to restore on end. */
short gizmo_flag;
@@ -567,6 +560,7 @@ typedef struct TransInfo {
void *view;
/** Only valid (non null) during an operator called function. */
struct bContext *context;
+ struct wmMsgBus *mbus;
struct ScrArea *area;
struct ARegion *region;
struct Depsgraph *depsgraph;
@@ -617,56 +611,53 @@ enum {
T_CURSOR = 1 << 5,
/** Transform points, having no rotation/scale. */
T_POINTS = 1 << 6,
-
- /* empty slot - (1 << 7) */
-
/** restrictions flags */
- T_NO_CONSTRAINT = 1 << 8,
- T_NULL_ONE = 1 << 9,
- T_NO_ZERO = 1 << 10,
+ T_NO_CONSTRAINT = 1 << 7,
+ T_NULL_ONE = 1 << 8,
+ T_NO_ZERO = 1 << 9,
T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO,
- T_PROP_EDIT = 1 << 11,
- T_PROP_CONNECTED = 1 << 12,
- T_PROP_PROJECTED = 1 << 13,
+ T_PROP_EDIT = 1 << 10,
+ T_PROP_CONNECTED = 1 << 11,
+ T_PROP_PROJECTED = 1 << 12,
T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED,
- T_V3D_ALIGN = 1 << 14,
+ T_V3D_ALIGN = 1 << 13,
/** For 2d views like uv or fcurve. */
- T_2D_EDIT = 1 << 15,
- T_CLIP_UV = 1 << 16,
+ T_2D_EDIT = 1 << 14,
+ T_CLIP_UV = 1 << 15,
/** Auto-ik is on. */
- T_AUTOIK = 1 << 18,
+ T_AUTOIK = 1 << 16,
/** Don't use mirror even if the data-block option is set. */
- T_NO_MIRROR = 1 << 19,
+ T_NO_MIRROR = 1 << 17,
/** To indicate that the value set in the `value` parameter is the final
* value of the transformation, modified only by the constrain. */
- T_INPUT_IS_VALUES_FINAL = 1 << 20,
+ T_INPUT_IS_VALUES_FINAL = 1 << 18,
/** To specify if we save back settings at the end. */
- T_MODAL = 1 << 21,
+ T_MODAL = 1 << 19,
/** No retopo. */
- T_NO_PROJECT = 1 << 22,
+ T_NO_PROJECT = 1 << 20,
- T_RELEASE_CONFIRM = 1 << 23,
+ T_RELEASE_CONFIRM = 1 << 21,
/** Alternative transformation. used to add offset to tracking markers. */
- T_ALT_TRANSFORM = 1 << 24,
+ T_ALT_TRANSFORM = 1 << 22,
/** #TransInfo.center has been set, don't change it. */
- T_OVERRIDE_CENTER = 1 << 25,
+ T_OVERRIDE_CENTER = 1 << 23,
- T_MODAL_CURSOR_SET = 1 << 26,
+ T_MODAL_CURSOR_SET = 1 << 24,
- T_CLNOR_REBUILD = 1 << 27,
+ T_CLNOR_REBUILD = 1 << 25,
/* Special Aftertrans. */
- T_AUTOMERGE = 1 << 28,
- T_AUTOSPLIT = 1 << 29,
+ T_AUTOMERGE = 1 << 26,
+ T_AUTOSPLIT = 1 << 27,
};
/** #TransInfo.modifiers */
@@ -713,40 +704,39 @@ enum {
/** #TransData.flag */
enum {
TD_SELECTED = 1 << 0,
- TD_NOACTION = 1 << 2,
- TD_USEQUAT = 1 << 3,
- TD_NOTCONNECTED = 1 << 4,
+ TD_USEQUAT = 1 << 1,
+ TD_NOTCONNECTED = 1 << 2,
/** Used for scaling of #MetaElem.rad */
- TD_SINGLESIZE = 1 << 5,
+ TD_SINGLESIZE = 1 << 3,
/** Scale relative to individual element center */
- TD_INDIVIDUAL_SCALE = 1 << 8,
- TD_NOCENTER = 1 << 9,
+ TD_INDIVIDUAL_SCALE = 1 << 4,
+ TD_NOCENTER = 1 << 5,
/** #TransData.ext abused for particle key timing. */
- TD_NO_EXT = 1 << 10,
+ TD_NO_EXT = 1 << 6,
/** don't transform this data */
- TD_SKIP = 1 << 11,
+ TD_SKIP = 1 << 7,
/** if this is a bez triple, we need to restore the handles,
* if this is set #TransData.hdata needs freeing */
- TD_BEZTRIPLE = 1 << 12,
+ TD_BEZTRIPLE = 1 << 8,
/** when this is set, don't apply translation changes to this element */
- TD_NO_LOC = 1 << 13,
+ TD_NO_LOC = 1 << 9,
/** For Graph Editor autosnap, indicates that point should not undergo autosnapping */
- TD_NOTIMESNAP = 1 << 14,
+ TD_NOTIMESNAP = 1 << 10,
/** For Graph Editor - curves that can only have int-values
* need their keyframes tagged with this. */
- TD_INTVALUES = 1 << 15,
+ TD_INTVALUES = 1 << 11,
/** For editmode mirror, clamp axis to 0 */
- TD_MIRROR_EDGE_X = 1 << 16,
- TD_MIRROR_EDGE_Y = 1 << 17,
- TD_MIRROR_EDGE_Z = 1 << 18,
+ TD_MIRROR_EDGE_X = 1 << 12,
+ TD_MIRROR_EDGE_Y = 1 << 13,
+ TD_MIRROR_EDGE_Z = 1 << 14,
/** For fcurve handles, move them along with their keyframes */
- TD_MOVEHANDLE1 = 1 << 19,
- TD_MOVEHANDLE2 = 1 << 20,
+ TD_MOVEHANDLE1 = 1 << 15,
+ TD_MOVEHANDLE2 = 1 << 16,
/** Exceptional case with pose bone rotating when a parent bone has 'Local Location'
* option enabled and rotating also transforms it. */
- TD_PBONE_LOCAL_MTX_P = 1 << 21,
+ TD_PBONE_LOCAL_MTX_P = 1 << 17,
/** Same as above but for a child bone. */
- TD_PBONE_LOCAL_MTX_C = 1 << 22,
+ TD_PBONE_LOCAL_MTX_C = 1 << 18,
};
/** #TransSnap.status */
@@ -911,8 +901,13 @@ void getViewVector(const TransInfo *t, const float coord[3], float vec[3]);
void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot);
/*********************** Transform Orientations ******************************/
-
-void initTransformOrientation(struct bContext *C, TransInfo *t, short orientation);
+short transform_orientation_matrix_get(struct bContext *C,
+ TransInfo *t,
+ const short orientation,
+ const float custom[3][3],
+ float r_spacemtx[3][3]);
+const char *transform_orientations_spacename_get(TransInfo *t, const short orient_type);
+void transform_orientations_current_set(struct TransInfo *t, const short orient_index);
/* Those two fill in mat and return non-zero on success */
bool createSpaceNormal(float mat[3][3], const float normal[3]);
@@ -922,7 +917,7 @@ struct TransformOrientation *addMatrixSpace(struct bContext *C,
float mat[3][3],
const char *name,
const bool overwrite);
-bool applyTransformOrientation(const struct TransformOrientation *ts,
+void applyTransformOrientation(const struct TransformOrientation *ts,
float r_mat[3][3],
char r_name[64]);
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index b05b99d9601..0347522b8e8 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -42,6 +42,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_scene.h"
#include "ED_view3d.h"
@@ -57,6 +58,27 @@
static void drawObjectConstraint(TransInfo *t);
+static void projection_matrix_calc(const TransInfo *t, float r_pmtx[3][3])
+{
+ unit_m3(r_pmtx);
+
+ if (!(t->con.mode & CON_AXIS0)) {
+ zero_v3(r_pmtx[0]);
+ }
+
+ if (!(t->con.mode & CON_AXIS1)) {
+ zero_v3(r_pmtx[1]);
+ }
+
+ if (!(t->con.mode & CON_AXIS2)) {
+ zero_v3(r_pmtx[2]);
+ }
+
+ float mat[3][3];
+ mul_m3_m3m3(mat, r_pmtx, t->spacemtx_inv);
+ mul_m3_m3m3(r_pmtx, t->spacemtx, mat);
+}
+
/* ************************** CONSTRAINTS ************************* */
static void constraintValuesFinal(TransInfo *t, float vec[3])
{
@@ -123,7 +145,7 @@ void constraintNumInput(TransInfo *t, float vec[3])
static void postConstraintChecks(TransInfo *t, float vec[3])
{
- mul_m3_v3(t->con.imtx, vec);
+ mul_m3_v3(t->spacemtx_inv, vec);
snapGridIncrement(t, vec);
@@ -153,7 +175,7 @@ static void postConstraintChecks(TransInfo *t, float vec[3])
/* inverse transformation at the end */
}
- mul_m3_v3(t->con.mtx, vec);
+ mul_m3_v3(t->spacemtx, vec);
}
static void viewAxisCorrectCenter(const TransInfo *t, float t_con_center[3])
@@ -286,7 +308,7 @@ static bool isPlaneProjectionViewAligned(const TransInfo *t)
int n = 0;
for (int i = 0; i < 3; i++) {
if (t->con.mode & (CON_AXIS0 << i)) {
- constraint_vector[n++] = t->con.mtx[i];
+ constraint_vector[n++] = t->spacemtx[i];
if (n == 2) {
break;
}
@@ -355,13 +377,13 @@ static void applyAxisConstraintVec(
float c[3];
if (t->con.mode & CON_AXIS0) {
- copy_v3_v3(c, t->con.mtx[0]);
+ copy_v3_v3(c, t->spacemtx[0]);
}
else if (t->con.mode & CON_AXIS1) {
- copy_v3_v3(c, t->con.mtx[1]);
+ copy_v3_v3(c, t->spacemtx[1]);
}
else if (t->con.mode & CON_AXIS2) {
- copy_v3_v3(c, t->con.mtx[2]);
+ copy_v3_v3(c, t->spacemtx[2]);
}
axisProjection(t, c, in, out);
}
@@ -373,7 +395,7 @@ static void applyAxisConstraintVec(
/*
* Generic callback for object based spatial constraints applied to linear motion
*
- * At first, the following is applied to the first data in the array
+ * At first, the following is applied without orientation
* The IN vector in projected into the constrained space and then further
* projected along the view vector.
* (in perspective mode, the view vector is relative to the position on screen)
@@ -384,40 +406,16 @@ static void applyAxisConstraintVec(
static void applyObjectConstraintVec(
TransInfo *t, TransDataContainer *tc, TransData *td, const float in[3], float out[3])
{
- copy_v3_v3(out, in);
- if (t->con.mode & CON_APPLY) {
- if (!td) {
- mul_m3_v3(t->con.pmtx, out);
-
- const int dims = getConstraintSpaceDimension(t);
- if (dims == 2) {
- if (!is_zero_v3(out)) {
- if (!isPlaneProjectionViewAligned(t)) {
- planeProjection(t, in, out);
- }
- }
- }
- else if (dims == 1) {
- float c[3];
-
- if (t->con.mode & CON_AXIS0) {
- copy_v3_v3(c, t->con.mtx[0]);
- }
- else if (t->con.mode & CON_AXIS1) {
- copy_v3_v3(c, t->con.mtx[1]);
- }
- else if (t->con.mode & CON_AXIS2) {
- copy_v3_v3(c, t->con.mtx[2]);
- }
- axisProjection(t, c, in, out);
- }
- postConstraintChecks(t, out);
- }
- else {
- mul_m3_v3(td->axismtx, out);
- if (t->flag & T_EDIT) {
- mul_m3_v3(tc->mat3_unit, out);
- }
+ if (!td) {
+ applyAxisConstraintVec(t, tc, td, in, out);
+ }
+ else {
+ /* Specific TransData's space. */
+ copy_v3_v3(out, in);
+ mul_m3_v3(t->spacemtx_inv, out);
+ mul_m3_v3(td->axismtx, out);
+ if (t->flag & T_EDIT) {
+ mul_m3_v3(tc->mat3_unit, out);
}
}
}
@@ -444,8 +442,8 @@ static void applyAxisConstraintSize(TransInfo *t,
smat[2][2] = 1.0f;
}
- mul_m3_m3m3(tmat, smat, t->con.imtx);
- mul_m3_m3m3(smat, t->con.mtx, tmat);
+ mul_m3_m3m3(tmat, smat, t->spacemtx_inv);
+ mul_m3_m3m3(smat, t->spacemtx, tmat);
}
}
@@ -505,15 +503,15 @@ static void applyAxisConstraintRot(
switch (mode) {
case CON_AXIS0:
case (CON_AXIS1 | CON_AXIS2):
- copy_v3_v3(vec, t->con.mtx[0]);
+ copy_v3_v3(vec, t->spacemtx[0]);
break;
case CON_AXIS1:
case (CON_AXIS0 | CON_AXIS2):
- copy_v3_v3(vec, t->con.mtx[1]);
+ copy_v3_v3(vec, t->spacemtx[1]);
break;
case CON_AXIS2:
case (CON_AXIS0 | CON_AXIS1):
- copy_v3_v3(vec, t->con.mtx[2]);
+ copy_v3_v3(vec, t->spacemtx[2]);
break;
}
/* don't flip axis if asked to or if num input */
@@ -586,12 +584,11 @@ static void applyObjectConstraintRot(
/*--------------------- INTERNAL SETUP CALLS ------------------*/
-void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[])
+void setConstraint(TransInfo *t, int mode, const char text[])
{
BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
- copy_m3_m3(t->con.mtx, space);
t->con.mode = mode;
- getConstraintMatrix(t);
+ projection_matrix_calc(t, t->con.pmtx);
startConstraint(t);
@@ -605,41 +602,25 @@ void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[])
/* applies individual td->axismtx constraints */
void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[])
{
- TransDataContainer *tc = t->data_container;
- if (t->data_len_all == 1) {
- float axismtx[3][3];
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(axismtx, tc->mat3_unit, tc->data->axismtx);
- }
- else {
- copy_m3_m3(axismtx, tc->data->axismtx);
- }
-
- setConstraint(t, axismtx, mode, text);
- }
- else {
- BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
- unit_m3(t->con.mtx);
- t->con.mode = mode;
- getConstraintMatrix(t);
+ BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
+ t->con.mode = mode;
+ projection_matrix_calc(t, t->con.pmtx);
- startConstraint(t);
+ startConstraint(t);
- t->con.drawExtra = drawObjectConstraint;
- t->con.applyVec = applyObjectConstraintVec;
- t->con.applySize = applyObjectConstraintSize;
- t->con.applyRot = applyObjectConstraintRot;
- t->redraw = TREDRAW_HARD;
- }
+ t->con.drawExtra = drawObjectConstraint;
+ t->con.applyVec = applyObjectConstraintVec;
+ t->con.applySize = applyObjectConstraintSize;
+ t->con.applyRot = applyObjectConstraintRot;
+ t->redraw = TREDRAW_HARD;
}
void setLocalConstraint(TransInfo *t, int mode, const char text[])
{
- /* edit-mode now allows local transforms too */
if (t->flag & T_EDIT) {
- /* Use the active (first) edit object. */
- TransDataContainer *tc = t->data_container;
- setConstraint(t, tc->mat3_unit, mode, text);
+ /* Although in edit-mode each object has its local space, use the
+ * orientation of the active object. */
+ setConstraint(t, mode, text);
}
else {
setAxisMatrixConstraint(t, mode, text);
@@ -655,61 +636,30 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[])
void setUserConstraint(TransInfo *t, short orientation, int mode, const char ftext[])
{
char text[256];
+ const char *spacename = transform_orientations_spacename_get(t, orientation);
+ BLI_snprintf(text, sizeof(text), ftext, spacename);
switch (orientation) {
- case V3D_ORIENT_GLOBAL: {
- float mtx[3][3];
- BLI_snprintf(text, sizeof(text), ftext, TIP_("global"));
- unit_m3(mtx);
- setConstraint(t, mtx, mode, text);
- break;
- }
case V3D_ORIENT_LOCAL:
- BLI_snprintf(text, sizeof(text), ftext, TIP_("local"));
setLocalConstraint(t, mode, text);
break;
case V3D_ORIENT_NORMAL:
- BLI_snprintf(text, sizeof(text), ftext, TIP_("normal"));
if (checkUseAxisMatrix(t)) {
setAxisMatrixConstraint(t, mode, text);
+ break;
}
- else {
- setConstraint(t, t->spacemtx, mode, text);
- }
- break;
+ ATTR_FALLTHROUGH;
+ case V3D_ORIENT_GLOBAL:
case V3D_ORIENT_VIEW:
- BLI_snprintf(text, sizeof(text), ftext, TIP_("view"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
case V3D_ORIENT_CURSOR:
- BLI_snprintf(text, sizeof(text), ftext, TIP_("cursor"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
case V3D_ORIENT_GIMBAL:
- BLI_snprintf(text, sizeof(text), ftext, TIP_("gimbal"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
case V3D_ORIENT_CUSTOM_MATRIX:
- BLI_snprintf(text, sizeof(text), ftext, TIP_("custom matrix"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
case V3D_ORIENT_CUSTOM:
default: {
- BLI_assert(orientation >= V3D_ORIENT_CUSTOM);
- char orientation_str[128];
- BLI_snprintf(orientation_str,
- sizeof(orientation_str),
- "%s \"%s\"",
- TIP_("custom orientation"),
- t->orientation.custom->name);
- BLI_snprintf(text, sizeof(text), ftext, orientation_str);
- setConstraint(t, t->spacemtx, mode, text);
+ setConstraint(t, mode, text);
break;
}
}
-
- t->con.orientation = orientation;
-
t->con.mode |= CON_USER;
}
@@ -740,9 +690,9 @@ void drawConstraint(TransInfo *t)
convertViewVec(t, vec, (t->mval[0] - t->con.imval[0]), (t->mval[1] - t->con.imval[1]));
add_v3_v3(vec, t->center_global);
- drawLine(t, t->center_global, tc->mtx[0], 'X', 0);
- drawLine(t, t->center_global, tc->mtx[1], 'Y', 0);
- drawLine(t, t->center_global, tc->mtx[2], 'Z', 0);
+ drawLine(t, t->center_global, t->spacemtx[0], 'X', 0);
+ drawLine(t, t->center_global, t->spacemtx[1], 'Y', 0);
+ drawLine(t, t->center_global, t->spacemtx[2], 'Z', 0);
depth_test_enabled = GPU_depth_test_enabled();
if (depth_test_enabled) {
@@ -776,13 +726,13 @@ void drawConstraint(TransInfo *t)
}
if (tc->mode & CON_AXIS0) {
- drawLine(t, t->center_global, tc->mtx[0], 'X', DRAWLIGHT);
+ drawLine(t, t->center_global, t->spacemtx[0], 'X', DRAWLIGHT);
}
if (tc->mode & CON_AXIS1) {
- drawLine(t, t->center_global, tc->mtx[1], 'Y', DRAWLIGHT);
+ drawLine(t, t->center_global, t->spacemtx[1], 'Y', DRAWLIGHT);
}
if (tc->mode & CON_AXIS2) {
- drawLine(t, t->center_global, tc->mtx[2], 'Z', DRAWLIGHT);
+ drawLine(t, t->center_global, t->spacemtx[2], 'Z', DRAWLIGHT);
}
}
}
@@ -879,11 +829,7 @@ static void drawObjectConstraint(TransInfo *t)
}
}
- if (t->flag & T_OBJECT) {
- copy_v3_v3(co, td->ob->obmat[3]);
- axismtx = td->axismtx;
- }
- else if (t->flag & T_EDIT) {
+ if (t->flag & T_EDIT) {
mul_v3_m4v3(co, tc->mat, td->center);
mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
@@ -928,45 +874,17 @@ void stopConstraint(TransInfo *t)
t->num.idx_max = t->idx_max;
}
-void getConstraintMatrix(TransInfo *t)
-{
- float mat[3][3];
- invert_m3_m3(t->con.imtx, t->con.mtx);
- unit_m3(t->con.pmtx);
-
- if (!(t->con.mode & CON_AXIS0)) {
- zero_v3(t->con.pmtx[0]);
- }
-
- if (!(t->con.mode & CON_AXIS1)) {
- zero_v3(t->con.pmtx[1]);
- }
-
- if (!(t->con.mode & CON_AXIS2)) {
- zero_v3(t->con.pmtx[2]);
- }
-
- mul_m3_m3m3(mat, t->con.pmtx, t->con.imtx);
- mul_m3_m3m3(t->con.pmtx, t->con.mtx, mat);
-}
-
/*------------------------- MMB Select -------------------------------*/
-void initSelectConstraint(TransInfo *t, bool force_global)
+void initSelectConstraint(TransInfo *t)
{
- short orientation;
- if (force_global) {
- orientation = V3D_ORIENT_GLOBAL;
- }
- else {
- if (t->orientation.index == 0) {
- t->orientation.index = 1;
- initTransformOrientation(t->context, t, t->orientation.types[t->orientation.index]);
- }
- orientation = t->orientation.types[t->orientation.index];
+ if (t->orient_curr == 0) {
+ t->orient_curr = 1;
+ transform_orientations_current_set(t, t->orient_curr);
}
- setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, "");
+ short orientation = t->orient[t->orient_curr].type;
+ setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, "%s");
setNearestAxis(t);
}
@@ -1033,7 +951,7 @@ static void setNearestAxis3d(TransInfo *t)
for (i = 0; i < 3; i++) {
float axis[3], axis_2d[2];
- copy_v3_v3(axis, t->con.mtx[i]);
+ copy_v3_v3(axis, t->spacemtx[i]);
mul_v3_fl(axis, zfac);
/* now we can project to get window coordinate */
@@ -1102,7 +1020,7 @@ void setNearestAxis(TransInfo *t)
setNearestAxis2d(t);
}
- getConstraintMatrix(t);
+ projection_matrix_calc(t, t->con.pmtx);
}
/*-------------- HELPER FUNCTIONS ----------------*/
diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h
index c98234c83da..c41b9361ca4 100644
--- a/source/blender/editors/transform/transform_constraints.h
+++ b/source/blender/editors/transform/transform_constraints.h
@@ -27,7 +27,7 @@
struct TransInfo;
void constraintNumInput(TransInfo *t, float vec[3]);
-void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[]);
+void setConstraint(TransInfo *t, int mode, const char text[]);
void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[]);
void setLocalConstraint(TransInfo *t, int mode, const char text[]);
void setUserConstraint(TransInfo *t, short orientation, int mode, const char text[]);
@@ -35,8 +35,7 @@ void drawConstraint(TransInfo *t);
void drawPropCircle(const struct bContext *C, TransInfo *t);
void startConstraint(TransInfo *t);
void stopConstraint(TransInfo *t);
-void getConstraintMatrix(TransInfo *t);
-void initSelectConstraint(TransInfo *t, bool force_global);
+void initSelectConstraint(TransInfo *t);
void selectConstraint(TransInfo *t);
void postSelectConstraint(TransInfo *t);
void setNearestAxis(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 7295a8623d9..cf60990d09c 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -111,8 +111,10 @@ void transform_around_single_fallback(TransInfo *t)
}
if (tc->data_len == 3) {
const TransData *td = tc->data;
- if ((td[0].loc == td[1].loc) && (td[1].loc == td[2].loc)) {
- is_data_single = true;
+ if ((td[0].flag | td[1].flag | td[2].flag) & TD_BEZTRIPLE) {
+ if ((td[0].loc == td[1].loc) && (td[1].loc == td[2].loc)) {
+ is_data_single = true;
+ }
}
}
break;
@@ -827,10 +829,6 @@ void clipUVData(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (int a = 0; a < tc->data_len; a++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if ((td->flag & TD_SKIP) || (!td->loc)) {
continue;
}
@@ -1848,7 +1846,10 @@ static void special_aftertrans_update__mask(bContext *C, TransInfo *t)
if (IS_AUTOKEY_ON(t->scene)) {
Scene *scene = t->scene;
- ED_mask_layer_shape_auto_key_select(mask, CFRA);
+ if (ED_mask_layer_shape_auto_key_select(mask, CFRA)) {
+ WM_event_add_notifier(C, NC_MASK | ND_DATA, &mask->id);
+ DEG_id_tag_update(&mask->id, 0);
+ }
}
}
@@ -2387,10 +2388,6 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
PTCacheID *pid;
ob = td->ob;
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c
index 42ffe675dc5..1f113a36a89 100644
--- a/source/blender/editors/transform/transform_convert_curve.c
+++ b/source/blender/editors/transform/transform_convert_curve.c
@@ -93,9 +93,8 @@ void createTransCurveVerts(TransInfo *t)
int count = 0, countsel = 0;
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
View3D *v3d = t->view;
- short hide_handles = (v3d != NULL) ?
- ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) :
- false;
+ short hide_handles = (v3d != NULL) ? (v3d->overlay.handle_display == CURVE_HANDLE_NONE) :
+ false;
/* count total of vertices, check identical as in 2nd loop for making transdata! */
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
@@ -163,9 +162,8 @@ void createTransCurveVerts(TransInfo *t)
int a;
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
View3D *v3d = t->view;
- short hide_handles = (v3d != NULL) ?
- ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) :
- false;
+ short hide_handles = (v3d != NULL) ? (v3d->overlay.handle_display == CURVE_HANDLE_NONE) :
+ false;
bool use_around_origins_for_handles_test = ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
transform_mode_use_local_origins(t));
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 24dda8c8464..07b2f07bf2c 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -1450,7 +1450,6 @@ static void UVsToTransData(const float aspect[2],
void createTransUVs(bContext *C, TransInfo *t)
{
SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
Scene *scene = t->scene;
ToolSettings *ts = CTX_data_tool_settings(C);
@@ -1500,7 +1499,7 @@ void createTransUVs(bContext *C, TransInfo *t)
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BMLoop *l;
- if (!uvedit_face_visible_test(scene, tc->obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
continue;
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 2f3b50a7c1a..6de962a3ed1 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -174,9 +174,6 @@ static void clipMirrorModifier(TransInfo *t)
int clip;
float loc[3], iloc[3];
- if (td->flag & TD_NOACTION) {
- break;
- }
if (td->loc == NULL) {
break;
}
@@ -1068,11 +1065,6 @@ static void recalcData_objects(TransInfo *t)
for (int i = 0; i < tc->data_len; i++, td++) {
Object *ob = td->ob;
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
@@ -1379,6 +1371,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
bGPdata *gpd = CTX_data_gpencil_data(C);
PropertyRNA *prop;
+ t->mbus = CTX_wm_message_bus(C);
t->depsgraph = CTX_data_depsgraph_pointer(C);
t->scene = sce;
t->view_layer = view_layer;
@@ -1626,7 +1619,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
if (t_values_set_is_array && t->flag & T_INPUT_IS_VALUES_FINAL) {
- /* For operators whose `t->values` is array, set contrain so that the
+ /* For operators whose `t->values` is array, set constraint so that the
* orientation is more intuitive in the Redo Panel. */
for (int i = 3; i--;) {
constraint_axis[i] |= t->values[i] != 0.0f;
@@ -1649,29 +1642,26 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
{
- TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
- TransformOrientation *custom_orientation = NULL;
short orient_type_set = -1;
short orient_type_matrix_set = -1;
- short orient_type_scene = orient_slot->type;
- if (orient_type_scene == V3D_ORIENT_CUSTOM) {
- const int index_custom = orient_slot->index_custom;
- custom_orientation = BKE_scene_transform_orientation_find(t->scene, index_custom);
- orient_type_scene += index_custom;
- }
+ short orient_type_scene = V3D_ORIENT_GLOBAL;
- short orient_type_default;
- short orient_type_constraint[2];
- if ((t->flag & T_MODAL) && transform_mode_is_changeable(t->mode)) {
- /* During modal, rotation starts with the View orientation. */
- orient_type_default = V3D_ORIENT_VIEW;
- }
- else {
- orient_type_default = orient_type_scene;
+ if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
+ TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
+ orient_type_scene = orient_slot->type;
+ if (orient_type_scene == V3D_ORIENT_CUSTOM) {
+ const int index_custom = orient_slot->index_custom;
+ orient_type_scene += index_custom;
+ }
}
+ short orient_types[3];
+ float custom_matrix[3][3];
+ bool use_orient_axis = false;
+
if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
t->orient_axis = RNA_property_enum_get(op->ptr, prop);
+ use_orient_axis = true;
}
if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop);
@@ -1684,26 +1674,28 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
if (orient_type_set >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) {
orient_type_set = V3D_ORIENT_GLOBAL;
}
- else {
- custom_orientation = BKE_scene_transform_orientation_find(
- t->scene, orient_type_set - V3D_ORIENT_CUSTOM);
- }
}
/* Change the default orientation to be used when redoing. */
- orient_type_default = orient_type_set;
- orient_type_constraint[0] = orient_type_set;
- orient_type_constraint[1] = orient_type_scene;
+ orient_types[0] = orient_type_set;
+ orient_types[1] = orient_type_set;
+ orient_types[2] = orient_type_scene;
}
else {
- orient_type_constraint[0] = orient_type_scene;
- orient_type_constraint[1] = orient_type_scene != V3D_ORIENT_GLOBAL ? V3D_ORIENT_GLOBAL :
- V3D_ORIENT_LOCAL;
+ if ((t->flag & T_MODAL) && (use_orient_axis || transform_mode_is_changeable(t->mode))) {
+ orient_types[0] = V3D_ORIENT_VIEW;
+ }
+ else {
+ orient_types[0] = orient_type_scene;
+ }
+ orient_types[1] = orient_type_scene;
+ orient_types[2] = orient_type_scene != V3D_ORIENT_GLOBAL ? V3D_ORIENT_GLOBAL :
+ V3D_ORIENT_LOCAL;
}
if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) &&
RNA_property_is_set(op->ptr, prop))) {
- RNA_property_float_get_array(op->ptr, prop, &t->orientation.custom_matrix[0][0]);
+ RNA_property_float_get_array(op->ptr, prop, &custom_matrix[0][0]);
if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) &&
RNA_property_is_set(op->ptr, prop)) {
@@ -1718,18 +1710,30 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
if (orient_type_matrix_set == orient_type_set) {
/* Constraints are forced to use the custom matrix when redoing. */
- orient_type_default = V3D_ORIENT_CUSTOM_MATRIX;
+ orient_types[0] = V3D_ORIENT_CUSTOM_MATRIX;
}
}
- t->orientation.types[0] = orient_type_default;
- t->orientation.types[1] = orient_type_constraint[0];
- t->orientation.types[2] = orient_type_constraint[1];
- t->orientation.custom = custom_orientation;
-
if (t->con.mode & CON_APPLY) {
- t->orientation.index = 1;
+ t->orient_curr = 1;
+ }
+
+ /* For efficiency, avoid calculating the same orientation twice. */
+ for (int i = 1; i < 3; i++) {
+ t->orient[i].type = transform_orientation_matrix_get(
+ C, t, orient_types[i], custom_matrix, t->orient[i].matrix);
+ }
+
+ if (orient_types[0] != orient_types[1]) {
+ t->orient[0].type = transform_orientation_matrix_get(
+ C, t, orient_types[0], custom_matrix, t->orient[0].matrix);
}
+ else {
+ memcpy(&t->orient[0], &t->orient[1], sizeof(t->orient[0]));
+ }
+
+ const char *spacename = transform_orientations_spacename_get(t, orient_types[0]);
+ BLI_strncpy(t->spacename, spacename, sizeof(t->spacename));
}
if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
@@ -1922,7 +1926,7 @@ void postTrans(bContext *C, TransInfo *t)
ED_region_draw_cb_exit(t->region->type, t->draw_handle_pixel);
}
if (t->draw_handle_cursor) {
- WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
+ WM_paint_cursor_end(t->draw_handle_cursor);
}
if (t->flag & T_MODAL_CURSOR_SET) {
@@ -2401,19 +2405,11 @@ void calculatePropRatio(TransInfo *t)
}
else if ((connected && (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size)) ||
(connected == 0 && td->rdist > t->prop_size)) {
- /*
- * The elements are sorted according to their dist member in the array,
- * that means we can stop when it finds one element outside of the propsize.
- * do not set 'td->flag |= TD_NOACTION', the prop circle is being changed.
- */
-
td->factor = 0.0f;
restoreElement(td);
}
else {
/* Use rdist for falloff calculations, it is the real distance */
- td->flag &= ~TD_NOACTION;
-
if (connected) {
dist = (t->prop_size - td->dist) / t->prop_size;
}
diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c
index 50317d8b395..c63e90ac2b7 100644
--- a/source/blender/editors/transform/transform_gizmo_2d.c
+++ b/source/blender/editors/transform/transform_gizmo_2d.c
@@ -217,14 +217,12 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
ScrArea *area = CTX_wm_area(C);
bool changed = false;
if (area->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = area->spacedata.first;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = ED_space_image(sima);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
view_layer, NULL, &objects_len);
- if (ED_uvedit_minmax_multi(scene, ima, objects, objects_len, r_min, r_max)) {
+ if (ED_uvedit_minmax_multi(scene, objects, objects_len, r_min, r_max)) {
changed = true;
}
MEM_freeN(objects);
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index f143d4c2993..ebc021cd983 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -635,101 +635,6 @@ bool gimbal_axis(Object *ob, float gmat[3][3])
return 0;
}
-void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3])
-{
- ARegion *region = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
- RegionView3D *rv3d = region->regiondata;
- Object *ob = OBACT(view_layer);
- const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
- const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
- const int pivot_point = scene->toolsettings->transform_pivot_point;
-
- ED_transform_calc_orientation_from_type_ex(
- C, r_mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
-}
-
-void ED_transform_calc_orientation_from_type_ex(const bContext *C,
- float r_mat[3][3],
- /* extra args (can be accessed from context) */
- Scene *scene,
- RegionView3D *rv3d,
- Object *ob,
- Object *obedit,
- const short orientation_type,
- int orientation_index_custom,
- const int pivot_point)
-{
- bool ok = false;
-
- switch (orientation_type) {
- case V3D_ORIENT_GLOBAL: {
- break; /* nothing to do */
- }
- case V3D_ORIENT_GIMBAL: {
- if (gimbal_axis(ob, r_mat)) {
- ok = true;
- break;
- }
- /* if not gimbal, fall through to normal */
- ATTR_FALLTHROUGH;
- }
- case V3D_ORIENT_NORMAL: {
- if (obedit || ob->mode & OB_MODE_POSE) {
- ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
- ok = true;
- break;
- }
- /* no break we define 'normal' as 'local' in Object mode */
- ATTR_FALLTHROUGH;
- }
- case V3D_ORIENT_LOCAL: {
- if (ob->mode & OB_MODE_POSE) {
- /* each bone moves on its own local axis, but to avoid confusion,
- * use the active pones axis for display [#33575], this works as expected on a single bone
- * and users who select many bones will understand what's going on and what local means
- * when they start transforming */
- ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
- ok = true;
- break;
- }
- copy_m3_m4(r_mat, ob->obmat);
- normalize_m3(r_mat);
- ok = true;
- break;
- }
- case V3D_ORIENT_VIEW: {
- if (rv3d != NULL) {
- copy_m3_m4(r_mat, rv3d->viewinv);
- normalize_m3(r_mat);
- ok = true;
- }
- break;
- }
- case V3D_ORIENT_CURSOR: {
- BKE_scene_cursor_rot_to_mat3(&scene->cursor, r_mat);
- ok = true;
- break;
- }
- case V3D_ORIENT_CUSTOM:
- default: {
- BLI_assert(orientation_type >= V3D_ORIENT_CUSTOM);
- TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find(
- scene, orientation_index_custom);
- if (applyTransformOrientation(custom_orientation, r_mat, NULL)) {
- ok = true;
- }
- break;
- }
- }
-
- if (!ok) {
- unit_m3(r_mat);
- }
-}
-
/* centroid, boundbox, of selection */
/* returns total items selected */
int ED_transform_calc_gizmo_stats(const bContext *C,
@@ -929,7 +834,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
* if handles are hidden then only check the center points.
* If the center knot is selected then only use this as the center point.
*/
- if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+ if (v3d->overlay.handle_display == CURVE_HANDLE_NONE) {
if (bezt->f2 & SELECT) {
calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
totsel++;
@@ -1390,16 +1295,16 @@ void drawDial3d(const TransInfo *t)
if (tc->mode & CON_APPLY) {
if (tc->mode & CON_AXIS0) {
axis_idx = MAN_AXIS_ROT_X;
- negate_v3_v3(mat_basis[2], tc->mtx[0]);
+ negate_v3_v3(mat_basis[2], t->spacemtx[0]);
}
else if (tc->mode & CON_AXIS1) {
axis_idx = MAN_AXIS_ROT_Y;
- negate_v3_v3(mat_basis[2], tc->mtx[1]);
+ negate_v3_v3(mat_basis[2], t->spacemtx[1]);
}
else {
BLI_assert((tc->mode & CON_AXIS2) != 0);
axis_idx = MAN_AXIS_ROT_Z;
- negate_v3_v3(mat_basis[2], tc->mtx[2]);
+ negate_v3_v3(mat_basis[2], t->spacemtx[2]);
}
}
else {
diff --git a/source/blender/editors/transform/transform_mode_align.c b/source/blender/editors/transform/transform_mode_align.c
index 9bce793809b..4fd4599b940 100644
--- a/source/blender/editors/transform/transform_mode_align.c
+++ b/source/blender/editors/transform/transform_mode_align.c
@@ -52,10 +52,6 @@ static void applyAlign(TransInfo *t, const int UNUSED(mval[2]))
for (i = 0; i < tc->data_len; i++, td++) {
float mat[3][3], invmat[3][3];
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_baketime.c b/source/blender/editors/transform/transform_mode_baketime.c
index bb8fd0df13d..4e7fc3578ce 100644
--- a/source/blender/editors/transform/transform_mode_baketime.c
+++ b/source/blender/editors/transform/transform_mode_baketime.c
@@ -97,10 +97,6 @@ static void applyBakeTime(TransInfo *t, const int mval[2])
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_bbone_resize.c b/source/blender/editors/transform/transform_mode_bbone_resize.c
index c81049ac379..77850e74785 100644
--- a/source/blender/editors/transform/transform_mode_bbone_resize.c
+++ b/source/blender/editors/transform/transform_mode_bbone_resize.c
@@ -141,10 +141,6 @@ static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_bend.c b/source/blender/editors/transform/transform_mode_bend.c
index 721d226050a..3b51626b170 100644
--- a/source/blender/editors/transform/transform_mode_bend.c
+++ b/source/blender/editors/transform/transform_mode_bend.c
@@ -186,10 +186,6 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
float delta[3];
float fac, fac_scaled;
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_boneenvelope.c b/source/blender/editors/transform/transform_mode_boneenvelope.c
index aa20a5ade95..7045d190478 100644
--- a/source/blender/editors/transform/transform_mode_boneenvelope.c
+++ b/source/blender/editors/transform/transform_mode_boneenvelope.c
@@ -73,10 +73,6 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_boneroll.c b/source/blender/editors/transform/transform_mode_boneroll.c
index 0564a946148..1503519c519 100644
--- a/source/blender/editors/transform/transform_mode_boneroll.c
+++ b/source/blender/editors/transform/transform_mode_boneroll.c
@@ -75,10 +75,6 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
index 057f13ac068..84e4e950804 100644
--- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
+++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
@@ -73,10 +73,6 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_edge_bevelweight.c b/source/blender/editors/transform/transform_mode_edge_bevelweight.c
index 5db7895232c..399cec2d62c 100644
--- a/source/blender/editors/transform/transform_mode_edge_bevelweight.c
+++ b/source/blender/editors/transform/transform_mode_edge_bevelweight.c
@@ -87,10 +87,6 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->val) {
*td->val = td->ival + weight * td->factor;
if (*td->val < 0.0f) {
diff --git a/source/blender/editors/transform/transform_mode_edge_crease.c b/source/blender/editors/transform/transform_mode_edge_crease.c
index 4a92a57fef6..53c948c742b 100644
--- a/source/blender/editors/transform/transform_mode_edge_crease.c
+++ b/source/blender/editors/transform/transform_mode_edge_crease.c
@@ -87,10 +87,6 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
index 8690cd54a3b..c1cb4325c09 100644
--- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c
+++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
@@ -81,10 +81,6 @@ static void applySeqSlideValue(TransInfo *t, const float val[2])
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_gpopacity.c b/source/blender/editors/transform/transform_mode_gpopacity.c
index 267d297a31c..4712fb7ba01 100644
--- a/source/blender/editors/transform/transform_mode_gpopacity.c
+++ b/source/blender/editors/transform/transform_mode_gpopacity.c
@@ -73,10 +73,6 @@ static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c
index 7c49d107703..ab9a0aa79ed 100644
--- a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c
+++ b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c
@@ -73,10 +73,6 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c
index e42439920db..68f3abda85b 100644
--- a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c
+++ b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c
@@ -78,10 +78,6 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
@@ -97,10 +93,6 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (td = tc->data, i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_mirror.c b/source/blender/editors/transform/transform_mode_mirror.c
index dae17374481..8d953610eb8 100644
--- a/source/blender/editors/transform/transform_mode_mirror.c
+++ b/source/blender/editors/transform/transform_mode_mirror.c
@@ -69,10 +69,6 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
@@ -93,10 +89,6 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_push_pull.c b/source/blender/editors/transform/transform_mode_push_pull.c
index 6eb038ea9b0..4a2f979ec38 100644
--- a/source/blender/editors/transform/transform_mode_push_pull.c
+++ b/source/blender/editors/transform/transform_mode_push_pull.c
@@ -82,10 +82,6 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c
index 00644b9bfdc..d919d5c889d 100644
--- a/source/blender/editors/transform/transform_mode_resize.c
+++ b/source/blender/editors/transform/transform_mode_resize.c
@@ -93,10 +93,6 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c
index 55c97630487..6480cb6c30e 100644
--- a/source/blender/editors/transform/transform_mode_rotate.c
+++ b/source/blender/editors/transform/transform_mode_rotate.c
@@ -82,10 +82,6 @@ static void applyRotationValue(TransInfo *t,
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c
index dc0479f4e60..fa33c1550e7 100644
--- a/source/blender/editors/transform/transform_mode_shear.c
+++ b/source/blender/editors/transform/transform_mode_shear.c
@@ -56,7 +56,7 @@ static void initShear_mouseInputMode(TransInfo *t)
copy_v3_v3(dir, t->spacemtx[t->orient_axis_ortho]);
/* Needed for axis aligned view gizmo. */
- if (t->orientation.types[t->orientation.index] == V3D_ORIENT_VIEW) {
+ if (t->orient[t->orient_curr].type == V3D_ORIENT_VIEW) {
if (t->orient_axis_ortho == 0) {
if (t->center2d[1] > t->mouse.imval[1]) {
dir_flip = !dir_flip;
@@ -165,11 +165,6 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
const float *center, *co;
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c
index ed082e86b6d..78d3efa0d69 100644
--- a/source/blender/editors/transform/transform_mode_shrink_fatten.c
+++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c
@@ -95,10 +95,6 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
float tdistance; /* temp dist */
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_skin_resize.c b/source/blender/editors/transform/transform_mode_skin_resize.c
index b53dbb55c62..23d83050613 100644
--- a/source/blender/editors/transform/transform_mode_skin_resize.c
+++ b/source/blender/editors/transform/transform_mode_skin_resize.c
@@ -73,11 +73,6 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
for (i = 0; i < tc->data_len; i++, td++) {
float tmat[3][3], smat[3][3];
float fsize[3];
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_tilt.c b/source/blender/editors/transform/transform_mode_tilt.c
index 2f56f4bd162..ca0a8818477 100644
--- a/source/blender/editors/transform/transform_mode_tilt.c
+++ b/source/blender/editors/transform/transform_mode_tilt.c
@@ -77,10 +77,6 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_tosphere.c b/source/blender/editors/transform/transform_mode_tosphere.c
index 841ccf41365..f6c5448a906 100644
--- a/source/blender/editors/transform/transform_mode_tosphere.c
+++ b/source/blender/editors/transform/transform_mode_tosphere.c
@@ -79,10 +79,6 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
float tratio;
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_trackball.c b/source/blender/editors/transform/transform_mode_trackball.c
index c6e0b205204..ca5a749b275 100644
--- a/source/blender/editors/transform/transform_mode_trackball.c
+++ b/source/blender/editors/transform/transform_mode_trackball.c
@@ -63,10 +63,6 @@ static void applyTrackballValue(TransInfo *t,
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c
index 69552eda5bf..96820ca6385 100644
--- a/source/blender/editors/transform/transform_mode_translate.c
+++ b/source/blender/editors/transform/transform_mode_translate.c
@@ -236,10 +236,6 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
TransData *td = tc->data;
for (int i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index ff15bbfb5d6..cd170b144d8 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -397,14 +397,12 @@ int BIF_countTransformOrientation(const bContext *C)
return BLI_listbase_count(transform_orientations);
}
-bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name)
+void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name)
{
if (r_name) {
BLI_strncpy(r_name, ts->name, MAX_NAME);
}
copy_m3_m3(r_mat, ts->mat);
-
- return true;
}
/* Updates all `BONE_TRANSFORM` flags.
@@ -438,79 +436,176 @@ static int armature_bone_transflags_update_recursive(bArmature *arm,
return total;
}
-void initTransformOrientation(bContext *C, TransInfo *t, short orientation)
+void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3])
{
- Object *ob = CTX_data_active_object(C);
- Object *obedit = CTX_data_active_object(C);
+ ARegion *region = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = CTX_data_edit_object(C);
+ RegionView3D *rv3d = region->regiondata;
+ Object *ob = OBACT(view_layer);
+ const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+ const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
+ const int pivot_point = scene->toolsettings->transform_pivot_point;
- switch (orientation) {
- case V3D_ORIENT_GLOBAL:
- unit_m3(t->spacemtx);
- BLI_strncpy(t->spacename, TIP_("global"), sizeof(t->spacename));
- break;
+ ED_transform_calc_orientation_from_type_ex(
+ C, r_mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
+}
- case V3D_ORIENT_GIMBAL:
- unit_m3(t->spacemtx);
- if (ob && gimbal_axis(ob, t->spacemtx)) {
- BLI_strncpy(t->spacename, TIP_("gimbal"), sizeof(t->spacename));
- break;
+short ED_transform_calc_orientation_from_type_ex(const bContext *C,
+ float r_mat[3][3],
+ /* extra args (can be accessed from context) */
+ Scene *scene,
+ RegionView3D *rv3d,
+ Object *ob,
+ Object *obedit,
+ const short orientation_type,
+ int orientation_index_custom,
+ const int pivot_point)
+{
+ switch (orientation_type) {
+ case V3D_ORIENT_GLOBAL: {
+ unit_m3(r_mat);
+ return V3D_ORIENT_GLOBAL;
+ }
+ case V3D_ORIENT_GIMBAL: {
+ if (gimbal_axis(ob, r_mat)) {
+ return V3D_ORIENT_GIMBAL;
}
- ATTR_FALLTHROUGH; /* no gimbal fallthrough to normal */
- case V3D_ORIENT_NORMAL:
- if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
- BLI_strncpy(t->spacename, TIP_("normal"), sizeof(t->spacename));
- ED_getTransformOrientationMatrix(C, t->spacemtx, t->around);
- break;
+ /* if not gimbal, fall through to normal */
+ ATTR_FALLTHROUGH;
+ }
+ case V3D_ORIENT_NORMAL: {
+ if (obedit || ob->mode & OB_MODE_POSE) {
+ ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
+ return V3D_ORIENT_NORMAL;
}
- ATTR_FALLTHROUGH; /* we define 'normal' as 'local' in Object mode */
- case V3D_ORIENT_LOCAL:
- BLI_strncpy(t->spacename, TIP_("local"), sizeof(t->spacename));
-
+ /* no break we define 'normal' as 'local' in Object mode */
+ ATTR_FALLTHROUGH;
+ }
+ case V3D_ORIENT_LOCAL: {
if (ob) {
- copy_m3_m4(t->spacemtx, ob->obmat);
- normalize_m3(t->spacemtx);
- }
- else {
- unit_m3(t->spacemtx);
+ if (ob->mode & OB_MODE_POSE) {
+ /* each bone moves on its own local axis, but to avoid confusion,
+ * use the active pones axis for display [#33575], this works as expected on a single
+ * bone and users who select many bones will understand what's going on and what local
+ * means when they start transforming */
+ ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
+ }
+ else {
+ copy_m3_m4(r_mat, ob->obmat);
+ normalize_m3(r_mat);
+ }
+ return V3D_ORIENT_LOCAL;
}
-
- break;
-
+ unit_m3(r_mat);
+ return V3D_ORIENT_GLOBAL;
+ }
case V3D_ORIENT_VIEW: {
- float mat[3][3];
- if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
- BLI_strncpy(t->spacename, TIP_("view"), sizeof(t->spacename));
- copy_m3_m4(mat, t->viewinv);
- normalize_m3(mat);
+ if (rv3d != NULL) {
+ copy_m3_m4(r_mat, rv3d->viewinv);
+ normalize_m3(r_mat);
}
else {
- unit_m3(mat);
+ unit_m3(r_mat);
}
- copy_m3_m3(t->spacemtx, mat);
- break;
+ return V3D_ORIENT_VIEW;
}
case V3D_ORIENT_CURSOR: {
- BLI_strncpy(t->spacename, TIP_("cursor"), sizeof(t->spacename));
- BKE_scene_cursor_rot_to_mat3(&t->scene->cursor, t->spacemtx);
+ BKE_scene_cursor_rot_to_mat3(&scene->cursor, r_mat);
+ return V3D_ORIENT_CURSOR;
+ }
+ case V3D_ORIENT_CUSTOM_MATRIX: {
+ /* Do nothing. */;
break;
}
- case V3D_ORIENT_CUSTOM_MATRIX:
- BLI_strncpy(t->spacename, TIP_("custom"), sizeof(t->spacename));
- copy_m3_m3(t->spacemtx, t->orientation.custom_matrix);
+ case V3D_ORIENT_CUSTOM:
+ default: {
+ BLI_assert(orientation_type >= V3D_ORIENT_CUSTOM);
+ TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find(
+ scene, orientation_index_custom);
+ applyTransformOrientation(custom_orientation, r_mat, NULL);
break;
+ }
+ }
+
+ return orientation_type;
+}
+
+/* Sets the matrix of the specified space orientation.
+ * If the matrix cannot be obtained, an orientation different from the one
+ * informed is returned */
+short transform_orientation_matrix_get(bContext *C,
+ TransInfo *t,
+ const short orientation,
+ const float custom[3][3],
+ float r_spacemtx[3][3])
+{
+ if (orientation == V3D_ORIENT_CUSTOM_MATRIX) {
+ copy_m3_m3(r_spacemtx, custom);
+ return V3D_ORIENT_CUSTOM_MATRIX;
+ }
+
+ if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
+ Object *ob = CTX_data_active_object(C);
+ Object *obedit = CTX_data_active_object(C);
+ RegionView3D *rv3d = t->region->regiondata;
+ int orientation_index_custom = 0;
+
+ if (orientation >= V3D_ORIENT_CUSTOM) {
+ orientation_index_custom = orientation - V3D_ORIENT_CUSTOM;
+ }
+
+ return ED_transform_calc_orientation_from_type_ex(
+ C,
+ r_spacemtx,
+ /* extra args (can be accessed from context) */
+ t->scene,
+ rv3d,
+ ob,
+ obedit,
+ orientation,
+ orientation_index_custom,
+ t->around);
+ }
+
+ unit_m3(r_spacemtx);
+ return V3D_ORIENT_GLOBAL;
+}
+
+const char *transform_orientations_spacename_get(TransInfo *t, const short orient_type)
+{
+ switch (orient_type) {
+ case V3D_ORIENT_GLOBAL:
+ return TIP_("global");
+ case V3D_ORIENT_GIMBAL:
+ return TIP_("gimbal");
+ case V3D_ORIENT_NORMAL:
+ return TIP_("normal");
+ case V3D_ORIENT_LOCAL:
+ return TIP_("local");
+ case V3D_ORIENT_VIEW:
+ return TIP_("view");
+ case V3D_ORIENT_CURSOR:
+ return TIP_("cursor");
+ case V3D_ORIENT_CUSTOM_MATRIX:
+ return TIP_("custom");
case V3D_ORIENT_CUSTOM:
default:
- BLI_assert(orientation >= V3D_ORIENT_CUSTOM);
- BLI_strncpy(t->spacename, t->orientation.custom->name, sizeof(t->spacename));
- if (applyTransformOrientation(t->orientation.custom, t->spacemtx, t->spacename)) {
- /* pass */
- }
- else {
- unit_m3(t->spacemtx);
- }
- break;
+ BLI_assert(orient_type >= V3D_ORIENT_CUSTOM);
+ TransformOrientation *ts = BKE_scene_transform_orientation_find(
+ t->scene, orient_type - V3D_ORIENT_CUSTOM);
+ return ts->name;
}
+}
+
+void transform_orientations_current_set(TransInfo *t, const short orient_index)
+{
+ const short orientation = t->orient[orient_index].type;
+ const char *spacename = transform_orientations_spacename_get(t, orientation);
+ BLI_strncpy(t->spacename, spacename, sizeof(t->spacename));
+ copy_m3_m3(t->spacemtx, t->orient[orient_index].matrix);
invert_m3_m3(t->spacemtx_inv, t->spacemtx);
}
@@ -853,7 +948,7 @@ int getTransformOrientation_ex(const bContext *C,
}
}
else {
- const bool use_handle = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0;
+ const bool use_handle = v3d->overlay.handle_display != CURVE_HANDLE_NONE;
for (nu = nurbs->first; nu; nu = nu->next) {
/* only bezier has a normal */
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index cb4446deb99..82602e7d828 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -56,6 +56,7 @@
#include "WM_types.h"
+#include "ED_gizmo_library.h"
#include "ED_image.h"
#include "ED_markers.h"
#include "ED_node.h"
@@ -178,99 +179,53 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
(t->scene->toolsettings->snap_mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR);
if (draw_target || validSnap(t)) {
- TransSnapPoint *p;
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float imat[4][4];
- float size;
+ const float *loc_cur = NULL;
+ const float *loc_prev = NULL;
+ const float *normal = NULL;
GPU_depth_test(false);
- size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (!BLI_listbase_is_empty(&t->tsnap.points)) {
+ /* Draw snap points. */
- invert_m4_m4(imat, rv3d->viewmat);
+ float size = 2.0f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+ float view_inv[4][4];
+ copy_m4_m4(view_inv, rv3d->viewinv);
- uint pos = GPU_vertformat_attr_add(
- immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- for (p = t->tsnap.points.first; p; p = p->next) {
- if (p == t->tsnap.selectedPoint) {
- immUniformColor4ubv(selectedCol);
- }
- else {
- immUniformColor4ubv(col);
+ LISTBASE_FOREACH (TransSnapPoint *, p, &t->tsnap.points) {
+ if (p == t->tsnap.selectedPoint) {
+ immUniformColor4ubv(selectedCol);
+ }
+ else {
+ immUniformColor4ubv(col);
+ }
+ imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size, view_inv, pos);
}
- imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat, pos);
- }
-
- if (t->tsnap.status & POINT_INIT) {
- immUniformColor4ubv(activeCol);
-
- imm_drawcircball(
- t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat, pos);
+ immUnbindProgram();
}
/* draw normal if needed */
if (usingSnappingNormal(t) && validSnappingNormal(t)) {
- immUniformColor4ubv(activeCol);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3f(pos, t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
- immVertex3f(pos,
- t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
- t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
- t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]);
- immEnd();
+ normal = t->tsnap.snapNormal;
}
if (draw_target) {
- /* Draw snapTarget */
- float targ_co[3], vx[3], vy[3], v1[3], v2[3], v3[3], v4[4];
- copy_v3_v3(targ_co, t->tsnap.snapTarget);
- float px_size = 0.75f * size * ED_view3d_pixel_size(rv3d, targ_co);
-
- mul_v3_v3fl(vx, imat[0], px_size);
- mul_v3_v3fl(vy, imat[1], px_size);
-
- add_v3_v3v3(v1, vx, vy);
- sub_v3_v3v3(v2, vx, vy);
- negate_v3_v3(v3, v1);
- negate_v3_v3(v4, v2);
-
- add_v3_v3(v1, targ_co);
- add_v3_v3(v2, targ_co);
- add_v3_v3(v3, targ_co);
- add_v3_v3(v4, targ_co);
-
- immUniformColor4ubv(col);
- immBegin(GPU_PRIM_LINES, 4);
- immVertex3fv(pos, v3);
- immVertex3fv(pos, v1);
- immVertex3fv(pos, v4);
- immVertex3fv(pos, v2);
- immEnd();
-
- if (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE_PERPENDICULAR) {
- immUnbindProgram();
-
- immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- immUniform1f("dash_width", 6.0f * U.pixelsize);
- immUniform1f("dash_factor", 1.0f / 4.0f);
- immUniformColor4ubv(col);
+ loc_prev = t->tsnap.snapTarget;
+ }
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, targ_co);
- immVertex3fv(pos, t->tsnap.snapPoint);
- immEnd();
- }
+ if (validSnap(t)) {
+ loc_cur = t->tsnap.snapPoint;
}
- immUnbindProgram();
+ ED_gizmotypes_snap_3d_draw_util(
+ rv3d, loc_prev, loc_cur, normal, col, activeCol, t->tsnap.snapElem);
GPU_depth_test(true);
}
@@ -351,11 +306,6 @@ void applyProject(TransInfo *t)
for (i = 0; i < tc->data_len; i++, td++) {
float iloc[3], loc[3], no[3];
float mval_fl[2];
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
@@ -462,11 +412,6 @@ void applyGridAbsolute(TransInfo *t)
for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
float iloc[3], loc[3], tvec[3];
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
@@ -590,7 +535,6 @@ static bool bm_face_is_snap_target(BMFace *f, void *UNUSED(user_data))
static void initSnappingMode(TransInfo *t)
{
- Main *bmain = CTX_data_main(t->context);
ToolSettings *ts = t->settings;
/* All obedit types will match. */
const int obedit_type = t->data_container->obedit ? t->data_container->obedit->type : -1;
@@ -687,7 +631,7 @@ static void initSnappingMode(TransInfo *t)
if (t->spacetype == SPACE_VIEW3D) {
if (t->tsnap.object_context == NULL) {
t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
- bmain, t->scene, 0, t->region, t->view);
+ t->scene, 0, t->region, t->view);
ED_transform_snap_object_context_set_editmesh_callbacks(
t->tsnap.object_context,
@@ -1106,7 +1050,6 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
}
else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) {
if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) {
- Image *ima = ED_space_image(t->area->spacedata.first);
float co[2];
UI_view2d_region_to_view(&t->region->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
@@ -1117,7 +1060,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
float dist_sq = FLT_MAX;
if (ED_uvedit_nearest_uv_multi(
- t->scene, ima, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) {
+ t->scene, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) {
t->tsnap.snapPoint[0] *= t->aspect[0];
t->tsnap.snapPoint[1] *= t->aspect[1];
@@ -1750,8 +1693,8 @@ static void applyGridIncrement(
float local_axis[3];
float pos_on_axis[3];
- copy_v3_v3(local_axis, t->con.mtx[i]);
- copy_v3_v3(pos_on_axis, t->con.mtx[i]);
+ copy_v3_v3(local_axis, t->spacemtx[i]);
+ copy_v3_v3(pos_on_axis, t->spacemtx[i]);
/* amount of movement on axis from initial pos */
mul_v3_fl(pos_on_axis, val[i]);
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index acd76a2e3f5..c30b8d59dc0 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -104,13 +104,12 @@ typedef struct SnapObjectData {
/* SNAP_EDIT_MESH */
BVHTreeFromEditMesh treedata_editmesh;
float min[3], max[3];
- struct LinkNode **bvh_cache_p;
+ struct Mesh_Runtime *mesh_runtime;
};
};
} SnapObjectData;
struct SnapObjectContext {
- Main *bmain;
Scene *scene;
int flag;
@@ -145,6 +144,17 @@ struct SnapObjectContext {
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+static bool editmesh_eval_final_is_bmesh(const BMEditMesh *em)
+{
+ return (em->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Snap Object Data
* \{ */
@@ -245,17 +255,17 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object
return sod;
}
-static struct LinkNode **snap_object_data_editmesh_bvh_cache_get(Object *ob)
+static struct Mesh_Runtime *snap_object_data_editmesh_runtime_get(Object *ob)
{
BMEditMesh *em = BKE_editmesh_from_object(ob);
if (em->mesh_eval_final) {
- return &em->mesh_eval_final->runtime.bvh_cache;
+ return &em->mesh_eval_final->runtime;
}
if (em->mesh_eval_cage) {
- return &em->mesh_eval_cage->runtime.bvh_cache;
+ return &em->mesh_eval_cage->runtime;
}
- return &((Mesh *)ob->data)->runtime.bvh_cache;
+ return &((Mesh *)ob->data)->runtime;
}
static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
@@ -292,23 +302,23 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
clear_cache = true;
init = true;
}
- else if (sod->bvh_cache_p) {
- if (sod->bvh_cache_p != snap_object_data_editmesh_bvh_cache_get(ob)) {
+ else if (sod->mesh_runtime) {
+ if (sod->mesh_runtime != snap_object_data_editmesh_runtime_get(ob)) {
clear_cache = true;
init = true;
}
else if (sod->treedata_editmesh.tree && sod->treedata_editmesh.cached &&
- !bvhcache_has_tree(*sod->bvh_cache_p, sod->treedata_editmesh.tree)) {
+ !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->treedata_editmesh.tree)) {
/* The tree is owned by the EditMesh and may have been freed since we last used! */
clear = true;
}
else if (sod->bvhtree[0] && sod->cached[0] &&
- !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[0])) {
+ !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[0])) {
/* The tree is owned by the EditMesh and may have been freed since we last used! */
clear = true;
}
else if (sod->bvhtree[1] && sod->cached[1] &&
- !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[1])) {
+ !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[1])) {
/* The tree is owned by the EditMesh and may have been freed since we last used! */
clear = true;
}
@@ -347,7 +357,7 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
bm_mesh_minmax(em->bm, sod->min, sod->max);
}
- sod->bvh_cache_p = snap_object_data_editmesh_bvh_cache_get(ob);
+ sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob);
}
return sod;
@@ -360,7 +370,7 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
* \{ */
typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx,
- bool is_obedit,
+ bool use_obedit,
bool use_backface_culling,
Object *ob,
float obmat[4][4],
@@ -836,14 +846,19 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_looptri_ex(
- treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL);
+ treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL, NULL);
MEM_freeN(elem_mask);
}
else {
/* Only cache if bvhtree is created without a mask.
* This helps keep a standardized bvhtree in cache. */
- BKE_bvhtree_from_editmesh_get(treedata, em, 4, BVHTREE_FROM_EM_LOOPTRI, sod->bvh_cache_p);
+ BKE_bvhtree_from_editmesh_get(treedata,
+ em,
+ 4,
+ BVHTREE_FROM_EM_LOOPTRI,
+ &sod->mesh_runtime->bvh_cache,
+ sod->mesh_runtime->eval_mutex);
}
if (treedata->tree == NULL) {
@@ -921,41 +936,52 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
return retval;
}
+struct RaycastObjUserData {
+ const float *ray_start;
+ const float *ray_dir;
+ uint ob_index;
+ /* read/write args */
+ float *ray_depth;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ int *r_index;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ ListBase *r_hit_list;
+ bool use_occlusion_test;
+ bool ret;
+};
+
/**
* \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping;
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static bool raycastObj(SnapObjectContext *sctx,
- const float ray_start[3],
- const float ray_dir[3],
- Object *ob,
- const float obmat[4][4],
- const uint ob_index,
- bool use_obedit,
- bool use_occlusion_test,
- bool use_backface_culling,
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3],
- float r_no[3],
- int *r_index,
- Object **r_ob,
- float r_obmat[4][4],
- ListBase *r_hit_list)
+static void raycast_obj_fn(SnapObjectContext *sctx,
+ bool use_obedit,
+ bool use_backface_culling,
+ Object *ob,
+ float obmat[4][4],
+ void *data)
{
+ struct RaycastObjUserData *dt = data;
+ const uint ob_index = dt->ob_index++;
+ bool use_occlusion_test = dt->use_occlusion_test;
+ /* read/write args */
+ float *ray_depth = dt->ray_depth;
+
bool retval = false;
if (use_occlusion_test) {
if (use_obedit && sctx->use_v3d && XRAY_FLAG_ENABLED(sctx->v3d_data.v3d)) {
/* Use of occlude geometry in editing mode disabled. */
- return false;
+ return;
}
if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) {
/* Do not hit objects that are in wire or bounding box
* display mode. */
- return false;
+ return;
}
}
@@ -964,22 +990,22 @@ static bool raycastObj(SnapObjectContext *sctx,
Mesh *me = ob->data;
bool use_hide = false;
if (BKE_object_is_in_editmode(ob)) {
- if (use_obedit) {
+ if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) {
/* Operators only update the editmesh looptris of the original mesh. */
BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
retval = raycastEditMesh(sctx,
- ray_start,
- ray_dir,
+ dt->ray_start,
+ dt->ray_dir,
ob,
em_orig,
obmat,
ob_index,
use_backface_culling,
ray_depth,
- r_loc,
- r_no,
- r_index,
- r_hit_list);
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_hit_list);
break;
}
else {
@@ -991,8 +1017,8 @@ static bool raycastObj(SnapObjectContext *sctx,
}
}
retval = raycastMesh(sctx,
- ray_start,
- ray_dir,
+ dt->ray_start,
+ dt->ray_dir,
ob,
me,
obmat,
@@ -1000,10 +1026,10 @@ static bool raycastObj(SnapObjectContext *sctx,
use_hide,
use_backface_culling,
ray_depth,
- r_loc,
- r_no,
- r_index,
- r_hit_list);
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_hit_list);
break;
}
case OB_CURVE:
@@ -1012,8 +1038,8 @@ static bool raycastObj(SnapObjectContext *sctx,
Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
if (mesh_eval) {
retval = raycastMesh(sctx,
- ray_start,
- ray_dir,
+ dt->ray_start,
+ dt->ray_dir,
ob,
mesh_eval,
obmat,
@@ -1021,70 +1047,24 @@ static bool raycastObj(SnapObjectContext *sctx,
false,
use_backface_culling,
ray_depth,
- r_loc,
- r_no,
- r_index,
- r_hit_list);
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_hit_list);
break;
}
}
}
if (retval) {
- if (r_ob) {
- *r_ob = ob;
+ if (dt->r_ob) {
+ *dt->r_ob = ob;
}
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
+ if (dt->r_obmat) {
+ copy_m4_m4(dt->r_obmat, obmat);
}
- return true;
+ dt->ret = true;
}
-
- return false;
-}
-
-struct RaycastObjUserData {
- const float *ray_start;
- const float *ray_dir;
- uint ob_index;
- /* read/write args */
- float *ray_depth;
- /* return args */
- float *r_loc;
- float *r_no;
- int *r_index;
- Object **r_ob;
- float (*r_obmat)[4];
- ListBase *r_hit_list;
- bool use_occlusion_test;
- bool ret;
-};
-
-static void raycast_obj_cb(SnapObjectContext *sctx,
- bool use_obedit,
- bool use_backface_culling,
- Object *ob,
- float obmat[4][4],
- void *data)
-{
- struct RaycastObjUserData *dt = data;
-
- dt->ret |= raycastObj(sctx,
- dt->ray_start,
- dt->ray_dir,
- ob,
- obmat,
- dt->ob_index++,
- use_obedit,
- dt->use_occlusion_test,
- use_backface_culling,
- dt->ray_depth,
- dt->r_loc,
- dt->r_no,
- dt->r_index,
- dt->r_ob,
- dt->r_obmat,
- dt->r_hit_list);
}
/**
@@ -1145,7 +1125,7 @@ static bool raycastObjects(SnapObjectContext *sctx,
.ret = false,
};
- iter_snap_objects(sctx, depsgraph, params, raycast_obj_cb, &data);
+ iter_snap_objects(sctx, depsgraph, params, raycast_obj_fn, &data);
return data.ret;
}
@@ -2525,11 +2505,16 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_verts_ex(
- &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL);
+ &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL, NULL);
MEM_freeN(verts_mask);
}
else {
- BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_VERTS, sod->bvh_cache_p);
+ BKE_bvhtree_from_editmesh_get(&treedata,
+ em,
+ 2,
+ BVHTREE_FROM_EM_VERTS,
+ &sod->mesh_runtime->bvh_cache,
+ (ThreadMutex *)sod->mesh_runtime->eval_mutex);
}
sod->bvhtree[0] = treedata.tree;
sod->cached[0] = treedata.cached;
@@ -2552,11 +2537,16 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_edges_ex(
- &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL);
+ &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL, NULL);
MEM_freeN(edges_mask);
}
else {
- BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_EDGES, sod->bvh_cache_p);
+ BKE_bvhtree_from_editmesh_get(&treedata,
+ em,
+ 2,
+ BVHTREE_FROM_EM_EDGES,
+ &sod->mesh_runtime->bvh_cache,
+ sod->mesh_runtime->eval_mutex);
}
sod->bvhtree[1] = treedata.tree;
sod->cached[1] = treedata.cached;
@@ -2645,45 +2635,51 @@ static short snapEditMesh(SnapObjectContext *sctx,
return 0;
}
+struct SnapObjUserData {
+ SnapData *snapdata;
+ /* read/write args */
+ float *dist_px;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ int *r_index;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ short ret;
+};
+
/**
* \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping;
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static short snapObject(SnapObjectContext *sctx,
- SnapData *snapdata,
- Object *ob,
- float obmat[4][4],
+static void sanp_obj_fn(SnapObjectContext *sctx,
bool use_obedit,
bool use_backface_culling,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3],
- float r_no[3],
- int *r_index,
- Object **r_ob,
- float r_obmat[4][4])
+ Object *ob,
+ float obmat[4][4],
+ void *data)
{
+ struct SnapObjUserData *dt = data;
short retval = 0;
switch (ob->type) {
case OB_MESH: {
Mesh *me = ob->data;
if (BKE_object_is_in_editmode(ob)) {
- if (use_obedit) {
+ if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) {
/* Operators only update the editmesh looptris of the original mesh. */
BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
retval = snapEditMesh(sctx,
- snapdata,
+ dt->snapdata,
ob,
em_orig,
obmat,
use_backface_culling,
- dist_px,
- r_loc,
- r_no,
- r_index);
+ dt->dist_px,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index);
break;
}
else {
@@ -2695,99 +2691,66 @@ static short snapObject(SnapObjectContext *sctx,
}
else if (ob->dt == OB_BOUNDBOX) {
/* Do not snap to objects that are in bounding box display mode */
- return 0;
+ return;
}
- retval = snapMesh(
- sctx, snapdata, ob, me, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index);
+ retval = snapMesh(sctx,
+ dt->snapdata,
+ ob,
+ me,
+ obmat,
+ use_backface_culling,
+ dt->dist_px,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index);
break;
}
case OB_ARMATURE:
- retval = snapArmature(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index);
+ retval = snapArmature(
+ dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
case OB_CURVE:
- retval = snapCurve(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index);
+ retval = snapCurve(
+ dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */
case OB_SURF:
case OB_FONT: {
Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
if (mesh_eval) {
retval |= snapMesh(sctx,
- snapdata,
+ dt->snapdata,
ob,
mesh_eval,
obmat,
use_backface_culling,
- dist_px,
- r_loc,
- r_no,
- r_index);
+ dt->dist_px,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index);
}
break;
}
case OB_EMPTY:
- retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
case OB_GPENCIL:
- retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
case OB_CAMERA:
- retval = snapCamera(sctx, snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ retval = snapCamera(
+ sctx, dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
}
if (retval) {
- if (r_ob) {
- *r_ob = ob;
+ if (dt->r_ob) {
+ *dt->r_ob = ob;
}
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
+ if (dt->r_obmat) {
+ copy_m4_m4(dt->r_obmat, obmat);
}
- return retval;
- }
-
- return 0;
-}
-
-struct SnapObjUserData {
- SnapData *snapdata;
- /* read/write args */
- float *dist_px;
- /* return args */
- float *r_loc;
- float *r_no;
- int *r_index;
- Object **r_ob;
- float (*r_obmat)[4];
- short ret;
-};
-
-static void sanp_obj_cb(SnapObjectContext *sctx,
- bool is_obedit,
- bool use_backface_culling,
- Object *ob,
- float obmat[4][4],
- void *data)
-{
- struct SnapObjUserData *dt = data;
-
- short elem = snapObject(sctx,
- dt->snapdata,
- ob,
- obmat,
- is_obedit,
- use_backface_culling,
- /* read/write args */
- dt->dist_px,
- /* return args */
- dt->r_loc,
- dt->r_no,
- dt->r_index,
- dt->r_ob,
- dt->r_obmat);
-
- if (elem) {
- dt->ret = elem;
+ dt->ret = retval;
}
}
@@ -2840,7 +2803,7 @@ static short snapObjectsRay(SnapObjectContext *sctx,
.ret = 0,
};
- iter_snap_objects(sctx, depsgraph, params, sanp_obj_cb, &data);
+ iter_snap_objects(sctx, depsgraph, params, sanp_obj_fn, &data);
return data.ret;
}
@@ -2851,13 +2814,12 @@ static short snapObjectsRay(SnapObjectContext *sctx,
/** \name Public Object Snapping API
* \{ */
-SnapObjectContext *ED_transform_snap_object_context_create(Main *bmain, Scene *scene, int flag)
+SnapObjectContext *ED_transform_snap_object_context_create(Scene *scene, int flag)
{
SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
sctx->flag = flag;
- sctx->bmain = bmain;
sctx->scene = scene;
sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
@@ -2868,14 +2830,13 @@ SnapObjectContext *ED_transform_snap_object_context_create(Main *bmain, Scene *s
return sctx;
}
-SnapObjectContext *ED_transform_snap_object_context_create_view3d(Main *bmain,
- Scene *scene,
+SnapObjectContext *ED_transform_snap_object_context_create_view3d(Scene *scene,
int flag,
/* extra args for view3d */
const ARegion *region,
const View3D *v3d)
{
- SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, flag);
+ SnapObjectContext *sctx = ED_transform_snap_object_context_create(scene, flag);
sctx->use_v3d = true;
sctx->v3d_data.region = region;
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c
index f22e18de7a1..2df26abe8b3 100644
--- a/source/blender/editors/undo/memfile_undo.c
+++ b/source/blender/editors/undo/memfile_undo.c
@@ -216,7 +216,7 @@ static void memfile_undosys_step_decode(struct bContext *C,
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) {
BKE_library_foreach_ID_link(
- bmain, id, memfile_undosys_step_id_reused_cb, bmain, IDWALK_READONLY);
+ bmain, id, memfile_undosys_step_id_reused_cb, NULL, IDWALK_READONLY);
}
/* Tag depsgraph to update data-block for changes that happened between the
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index f8e19b742e4..af387e4f7c2 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -153,10 +153,10 @@ void ED_editors_init(bContext *C)
ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, reports);
}
else if (mode == OB_MODE_VERTEX_PAINT) {
- ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob);
}
else if (mode == OB_MODE_WEIGHT_PAINT) {
- ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob);
}
else {
BLI_assert(0);
@@ -174,7 +174,7 @@ void ED_editors_init(bContext *C)
else {
/* TODO(campbell): avoid operator calls. */
if (obact == ob) {
- ED_object_mode_toggle(C, mode);
+ ED_object_mode_set(C, mode);
}
}
}
diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c
index c072220842e..edfbfd0cdc3 100644
--- a/source/blender/editors/uvedit/uvedit_buttons.c
+++ b/source/blender/editors/uvedit/uvedit_buttons.c
@@ -58,8 +58,7 @@
/* UV Utilities */
-static int uvedit_center(
- Scene *scene, Object **objects, uint objects_len, Image *ima, float center[2])
+static int uvedit_center(Scene *scene, Object **objects, uint objects_len, float center[2])
{
BMFace *f;
BMLoop *l;
@@ -75,7 +74,7 @@ static int uvedit_center(
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, f)) {
+ if (!uvedit_face_visible_test(scene, f)) {
continue;
}
@@ -97,8 +96,10 @@ static int uvedit_center(
return tot;
}
-static void uvedit_translate(
- Scene *scene, Object **objects, uint objects_len, Image *ima, const float delta[2])
+static void uvedit_translate(Scene *scene,
+ Object **objects,
+ uint objects_len,
+ const float delta[2])
{
BMFace *f;
BMLoop *l;
@@ -112,7 +113,7 @@ static void uvedit_translate(
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, f)) {
+ if (!uvedit_face_visible_test(scene, f)) {
continue;
}
@@ -134,7 +135,6 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
{
SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
- Image *ima = sima->image;
float center[2];
int imx, imy, step, digits;
float width = 8 * UI_UNIT_X;
@@ -144,7 +144,7 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
ED_space_image_get_size(sima, &imx, &imy);
- if (uvedit_center(scene, objects, objects_len, ima, center)) {
+ if (uvedit_center(scene, objects, objects_len, center)) {
float range_xy[2][2] = {
{-10.0f, 10.0f},
{-10.0f, 10.0f},
@@ -212,7 +212,6 @@ static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event)
{
SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
- Image *ima = sima->image;
float center[2], delta[2];
int imx, imy;
@@ -225,7 +224,7 @@ static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event)
CTX_data_view_layer(C), CTX_wm_view3d(C), &objects_len);
ED_space_image_get_size(sima, &imx, &imy);
- uvedit_center(scene, objects, objects_len, ima, center);
+ uvedit_center(scene, objects, objects_len, center);
if (sima->flag & SI_COORDFLOATS) {
delta[0] = uvedit_old_center[0] - center[0];
@@ -236,7 +235,7 @@ static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event)
delta[1] = uvedit_old_center[1] / imy - center[1];
}
- uvedit_translate(scene, objects, objects_len, ima, delta);
+ uvedit_translate(scene, objects, objects_len, delta);
WM_event_add_notifier(C, NC_IMAGE, sima->image);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index f8cef95c776..897e2f13774 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -39,6 +39,7 @@
#include "../../draw/intern/draw_cache_impl.h"
#include "BLI_math.h"
+#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_deform.h"
@@ -206,8 +207,10 @@ static void uvedit_get_batches(Object *ob,
else {
batches->faces = NULL;
}
-
- DRW_mesh_batch_cache_create_requested(ob, ob->data, scene, false, false);
+ struct TaskGraph *task_graph = BLI_task_graph_create();
+ DRW_mesh_batch_cache_create_requested(task_graph, ob, ob->data, scene, false, false);
+ BLI_task_graph_work_and_wait(task_graph);
+ BLI_task_graph_free(task_graph);
if (draw_stretch && (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA)) {
/* after create_requested we can load the actual areas */
@@ -229,7 +232,11 @@ static void draw_uvs_shadow(SpaceImage *sima,
DRW_mesh_batch_cache_validate(me);
GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me);
- DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false);
+
+ struct TaskGraph *task_graph = BLI_task_graph_create();
+ DRW_mesh_batch_cache_create_requested(task_graph, ob_eval, me, scene, false, false);
+ BLI_task_graph_work_and_wait(task_graph);
+ BLI_task_graph_free(task_graph);
if (edges) {
if (sima->flag & SI_SMOOTH_UV) {
@@ -269,7 +276,10 @@ static void draw_uvs_texpaint(const Scene *scene, Object *ob, Depsgraph *depsgra
DRW_mesh_batch_cache_validate(me);
GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me);
- DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false);
+ struct TaskGraph *task_graph = BLI_task_graph_create();
+ DRW_mesh_batch_cache_create_requested(task_graph, ob_eval, me, scene, false, false);
+ BLI_task_graph_work_and_wait(task_graph);
+ BLI_task_graph_free(task_graph);
GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_UV_UNIFORM_COLOR);
GPU_batch_uniform_4fv(geom, "color", col);
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index ffab5bd094f..31384d6df17 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -57,13 +57,11 @@ typedef struct UvNearestHit {
}
bool uv_find_nearest_vert(struct Scene *scene,
- struct Image *ima,
struct Object *obedit,
const float co[2],
const float penalty_dist,
struct UvNearestHit *hit_final);
bool uv_find_nearest_vert_multi(struct Scene *scene,
- struct Image *ima,
struct Object **objects,
const uint objects_len,
const float co[2],
@@ -71,24 +69,20 @@ bool uv_find_nearest_vert_multi(struct Scene *scene,
struct UvNearestHit *hit_final);
bool uv_find_nearest_edge(struct Scene *scene,
- struct Image *ima,
struct Object *obedit,
const float co[2],
struct UvNearestHit *hit_final);
bool uv_find_nearest_edge_multi(struct Scene *scene,
- struct Image *ima,
struct Object **objects,
const uint objects_len,
const float co[2],
struct UvNearestHit *hit_final);
bool uv_find_nearest_face(struct Scene *scene,
- struct Image *ima,
struct Object *obedit,
const float co[2],
struct UvNearestHit *hit_final);
bool uv_find_nearest_face_multi(struct Scene *scene,
- struct Image *ima,
struct Object **objects,
const uint objects_len,
const float co[2],
@@ -116,14 +110,11 @@ void UV_OT_stitch(struct wmOperatorType *ot);
/* uvedit_select.c */
-bool uvedit_select_is_any_selected(struct Scene *scene, struct Image *ima, struct Object *obedit);
+bool uvedit_select_is_any_selected(struct Scene *scene, struct Object *obedit);
bool uvedit_select_is_any_selected_multi(struct Scene *scene,
- struct Image *ima,
struct Object **objects,
const uint objects_len);
const float *uvedit_first_selected_uv_from_vertex(struct Scene *scene,
- struct Object *obedit,
- struct Image *ima,
struct BMVert *eve,
const int cd_loop_uv_offset);
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index a99e05cb52b..652d07f02db 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -252,12 +252,8 @@ void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float as
}
}
-bool ED_uvedit_minmax_multi(const Scene *scene,
- Image *ima,
- Object **objects_edit,
- uint objects_len,
- float r_min[2],
- float r_max[2])
+bool ED_uvedit_minmax_multi(
+ const Scene *scene, Object **objects_edit, uint objects_len, float r_min[2], float r_max[2])
{
bool changed = false;
INIT_MINMAX2(r_min, r_max);
@@ -274,7 +270,7 @@ bool ED_uvedit_minmax_multi(const Scene *scene,
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -290,10 +286,9 @@ bool ED_uvedit_minmax_multi(const Scene *scene,
return changed;
}
-bool ED_uvedit_minmax(
- const Scene *scene, Image *ima, Object *obedit, float r_min[2], float r_max[2])
+bool ED_uvedit_minmax(const Scene *scene, Object *obedit, float r_min[2], float r_max[2])
{
- return ED_uvedit_minmax_multi(scene, ima, &obedit, 1, r_min, r_max);
+ return ED_uvedit_minmax_multi(scene, &obedit, 1, r_min, r_max);
}
/* Be careful when using this, it bypasses all synchronization options */
@@ -314,8 +309,10 @@ void ED_uvedit_select_all(BMesh *bm)
}
}
-static bool ED_uvedit_median_multi(
- const Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float co[2])
+static bool ED_uvedit_median_multi(const Scene *scene,
+ Object **objects_edit,
+ uint objects_len,
+ float co[2])
{
uint sel = 0;
zero_v2(co);
@@ -332,7 +329,7 @@ static bool ED_uvedit_median_multi(
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -351,24 +348,20 @@ static bool ED_uvedit_median_multi(
return (sel != 0);
}
-bool ED_uvedit_center_multi(const Scene *scene,
- Image *ima,
- Object **objects_edit,
- uint objects_len,
- float cent[2],
- char mode)
+bool ED_uvedit_center_multi(
+ const Scene *scene, Object **objects_edit, uint objects_len, float cent[2], char mode)
{
bool changed = false;
if (mode == V3D_AROUND_CENTER_BOUNDS) { /* bounding box */
float min[2], max[2];
- if (ED_uvedit_minmax_multi(scene, ima, objects_edit, objects_len, min, max)) {
+ if (ED_uvedit_minmax_multi(scene, objects_edit, objects_len, min, max)) {
mid_v2_v2v2(cent, min, max);
changed = true;
}
}
else {
- if (ED_uvedit_median_multi(scene, ima, objects_edit, objects_len, cent)) {
+ if (ED_uvedit_median_multi(scene, objects_edit, objects_len, cent)) {
changed = true;
}
}
@@ -392,8 +385,7 @@ bool ED_uvedit_center_from_pivot_ex(SpaceImage *sima,
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
view_layer, ((View3D *)NULL), &objects_len);
- *r_has_select = uvedit_select_is_any_selected_multi(
- scene, sima->image, objects, objects_len);
+ *r_has_select = uvedit_select_is_any_selected_multi(scene, objects, objects_len);
MEM_freeN(objects);
}
break;
@@ -402,7 +394,7 @@ bool ED_uvedit_center_from_pivot_ex(SpaceImage *sima,
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
view_layer, ((View3D *)NULL), &objects_len);
- changed = ED_uvedit_center_multi(scene, sima->image, objects, objects_len, r_center, mode);
+ changed = ED_uvedit_center_multi(scene, objects, objects_len, r_center, mode);
MEM_freeN(objects);
if (r_has_select != NULL) {
*r_has_select = changed;
@@ -440,7 +432,6 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool)
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
const ToolSettings *ts = scene->toolsettings;
const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
float cent[2], min[2], max[2];
@@ -467,7 +458,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -482,7 +473,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool)
tool = (max[0] - min[0] >= max[1] - min[1]) ? UV_ALIGN_Y : UV_ALIGN_X;
}
- ED_uvedit_center_multi(scene, ima, objects, objects_len, cent, 0);
+ ED_uvedit_center_multi(scene, objects, objects_len, cent, 0);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
@@ -501,7 +492,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -521,7 +512,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -548,7 +539,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool)
/* tag verts with a selected UV */
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
- if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) {
+ if (!uvedit_face_visible_test(scene, l->f)) {
continue;
}
@@ -619,9 +610,9 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool)
/* we know the returns from these must be valid */
const float *uv_start = uvedit_first_selected_uv_from_vertex(
- scene, obedit, ima, eve_line[0], cd_loop_uv_offset);
+ scene, eve_line[0], cd_loop_uv_offset);
const float *uv_end = uvedit_first_selected_uv_from_vertex(
- scene, obedit, ima, eve_line[BLI_array_len(eve_line) - 1], cd_loop_uv_offset);
+ scene, eve_line[BLI_array_len(eve_line) - 1], cd_loop_uv_offset);
/* For UV_STRAIGHTEN_X & UV_STRAIGHTEN_Y modes */
float a = 0.0f;
eUVWeldAlign tool_local = tool;
@@ -646,7 +637,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool)
/* go over all verts except for endpoints */
for (i = 0; i < BLI_array_len(eve_line); i++) {
BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) {
- if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) {
+ if (!uvedit_face_visible_test(scene, l->f)) {
continue;
}
@@ -754,7 +745,6 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
const ToolSettings *ts = scene->toolsettings;
const float threshold = RNA_float_get(op->ptr, "threshold");
@@ -808,7 +798,7 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op)
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -899,7 +889,6 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
const ToolSettings *ts = scene->toolsettings;
const float threshold = RNA_float_get(op->ptr, "threshold");
@@ -939,7 +928,7 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op)
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -972,7 +961,7 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op)
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -1086,10 +1075,12 @@ static void uv_snap_cursor_to_pixels(SpaceImage *sima)
uv_snap_to_pixel(sima->cursor, width, height);
}
-static bool uv_snap_cursor_to_selection(
- Scene *scene, Image *ima, Object **objects_edit, uint objects_len, SpaceImage *sima)
+static bool uv_snap_cursor_to_selection(Scene *scene,
+ Object **objects_edit,
+ uint objects_len,
+ SpaceImage *sima)
{
- return ED_uvedit_center_multi(scene, ima, objects_edit, objects_len, sima->cursor, sima->around);
+ return ED_uvedit_center_multi(scene, objects_edit, objects_len, sima->cursor, sima->around);
}
static int uv_snap_cursor_exec(bContext *C, wmOperator *op)
@@ -1105,13 +1096,12 @@ static int uv_snap_cursor_exec(bContext *C, wmOperator *op)
break;
case 1: {
Scene *scene = CTX_data_scene(C);
- Image *ima = CTX_data_edit_image(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
view_layer, ((View3D *)NULL), &objects_len);
- changed = uv_snap_cursor_to_selection(scene, ima, objects, objects_len, sima);
+ changed = uv_snap_cursor_to_selection(scene, objects, objects_len, sima);
MEM_freeN(objects);
break;
}
@@ -1155,7 +1145,7 @@ static void UV_OT_snap_cursor(wmOperatorType *ot)
/** \name Snap Selection Operator
* \{ */
-static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, const float cursor[2])
+static bool uv_snap_uvs_to_cursor(Scene *scene, Object *obedit, const float cursor[2])
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMFace *efa;
@@ -1167,7 +1157,7 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, cons
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -1183,7 +1173,7 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, cons
return changed;
}
-static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const float offset[2])
+static bool uv_snap_uvs_offset(Scene *scene, Object *obedit, const float offset[2])
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMFace *efa;
@@ -1195,7 +1185,7 @@ static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const f
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -1211,7 +1201,7 @@ static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const f
return changed;
}
-static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit)
+static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Object *obedit)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -1225,7 +1215,7 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object
/* index every vert that has a selected UV using it, but only once so as to
* get unique indices and to count how much to malloc */
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, obedit, ima, f)) {
+ if (uvedit_face_visible_test(scene, f)) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
BM_elem_flag_set(l, BM_ELEM_TAG, uvedit_uv_select_test(scene, l, cd_loop_uv_offset));
@@ -1269,7 +1259,6 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object
static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- Image *ima = sima->image;
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
@@ -1285,7 +1274,7 @@ static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit
h = (float)height;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -1307,7 +1296,6 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
const ToolSettings *ts = scene->toolsettings;
const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
const int target = RNA_enum_get(op->ptr, "target");
@@ -1319,7 +1307,7 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op)
if (target == 2) {
float center[2];
- if (!ED_uvedit_center_multi(scene, ima, objects, objects_len, center, sima->around)) {
+ if (!ED_uvedit_center_multi(scene, objects, objects_len, center, sima->around)) {
MEM_freeN(objects);
return OPERATOR_CANCELLED;
}
@@ -1341,13 +1329,13 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op)
changed = uv_snap_uvs_to_pixels(sima, scene, obedit);
break;
case 1:
- changed = uv_snap_uvs_to_cursor(scene, ima, obedit, sima->cursor);
+ changed = uv_snap_uvs_to_cursor(scene, obedit, sima->cursor);
break;
case 2:
- changed = uv_snap_uvs_offset(scene, ima, obedit, offset);
+ changed = uv_snap_uvs_offset(scene, obedit, offset);
break;
case 3:
- changed = uv_snap_uvs_to_adjacent_unselected(scene, ima, obedit);
+ changed = uv_snap_uvs_to_adjacent_unselected(scene, obedit);
break;
}
@@ -1398,7 +1386,6 @@ static int uv_pin_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
@@ -1423,7 +1410,7 @@ static int uv_pin_exec(bContext *C, wmOperator *op)
}
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -1501,11 +1488,9 @@ static bool bm_face_is_all_uv_sel(BMFace *f, bool select_test, const int cd_loop
static int uv_hide_exec(bContext *C, wmOperator *op)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
- SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
const bool swap = RNA_boolean_get(op->ptr, "unselected");
- Image *ima = sima ? sima->image : NULL;
const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE);
uint objects_len = 0;
@@ -1532,7 +1517,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
int hide = 0;
- if (!uvedit_face_visible_test(scene, ob, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -1858,11 +1843,12 @@ static void UV_OT_cursor_set(wmOperatorType *ot)
static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
{
+ Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- int ret = OPERATOR_CANCELLED;
const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
const bool mark_seams = RNA_boolean_get(op->ptr, "mark_seams");
const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
+ bool changed_multi = false;
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
@@ -1873,111 +1859,76 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
Mesh *me = (Mesh *)ob->data;
BMEditMesh *em = me->edit_mesh;
BMesh *bm = em->bm;
-
- UvVertMap *vmap;
- BMEdge *editedge;
BMIter iter;
if (!EDBM_uv_check(em)) {
continue;
}
- ret = OPERATOR_FINISHED;
-
- /* This code sets editvert->tmp.l to the index. This will be useful later on. */
- BM_mesh_elem_table_ensure(bm, BM_FACE);
- vmap = BM_uv_vert_map_create(bm, limit, false, false);
-
- BM_ITER_MESH (editedge, &iter, bm, BM_EDGES_OF_MESH) {
- /* flags to determine if we uv is separated from first editface match */
- char separated1 = 0, separated2;
- /* set to denote edge must be flagged as seam */
- char faces_separated = 0;
- /* flag to keep track if uv1 is disconnected from first editface match */
- char v1coincident = 1;
- /* For use with v1coincident. v1coincident will change only if we've had commonFaces */
- int commonFaces = 0;
-
- BMFace *efa1, *efa2;
-
- UvMapVert *mv1, *mvinit1, *mv2, *mvinit2, *mviter;
- /* mv2cache stores the first of the list of coincident uv's for later comparison
- * mv2sep holds the last separator and is copied to mv2cache
- * when a hit is first found */
- UvMapVert *mv2cache = NULL, *mv2sep = NULL;
-
- mvinit1 = vmap->vert[BM_elem_index_get(editedge->v1)];
- if (mark_seams) {
- BM_elem_flag_disable(editedge, BM_ELEM_SEAM);
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ bool changed = false;
+
+ BMFace *f;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, f)) {
+ continue;
}
- for (mv1 = mvinit1; mv1 && !faces_separated; mv1 = mv1->next) {
- if (mv1->separate && commonFaces) {
- v1coincident = 0;
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (l_iter == l_iter->radial_next) {
+ continue;
+ }
+ if (!uvedit_edge_select_test(scene, l_iter, cd_loop_uv_offset)) {
+ continue;
}
- separated2 = 0;
- efa1 = BM_face_at_index(bm, mv1->poly_index);
- mvinit2 = vmap->vert[BM_elem_index_get(editedge->v2)];
+ const MLoopUV *luv_curr = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
+ const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset);
- for (mv2 = mvinit2; mv2; mv2 = mv2->next) {
- if (mv2->separate) {
- mv2sep = mv2;
+ bool mark = false;
+ BMLoop *l_other = l_iter->radial_next;
+ do {
+ const MLoopUV *luv_other_curr = BM_ELEM_CD_GET_VOID_P(l_other, cd_loop_uv_offset);
+ const MLoopUV *luv_other_next = BM_ELEM_CD_GET_VOID_P(l_other->next, cd_loop_uv_offset);
+ if (l_iter->v != l_other->v) {
+ SWAP(const MLoopUV *, luv_other_curr, luv_other_next);
}
- efa2 = BM_face_at_index(bm, mv2->poly_index);
- if (efa1 == efa2) {
- /* if v1 is not coincident no point in comparing */
- if (v1coincident) {
- /* have we found previously anything? */
- if (mv2cache) {
- /* flag seam unless proved to be coincident with previous hit */
- separated2 = 1;
- for (mviter = mv2cache; mviter; mviter = mviter->next) {
- if (mviter->separate && mviter != mv2cache) {
- break;
- }
- /* coincident with previous hit, do not flag seam */
- if (mviter == mv2) {
- separated2 = 0;
- }
- }
- }
- /* First hit case, store the hit in the cache */
- else {
- mv2cache = mv2sep;
- commonFaces = 1;
- }
- }
- else {
- separated1 = 1;
- }
+ if (!compare_ff(luv_curr->uv[0], luv_other_curr->uv[0], limit[0]) ||
+ !compare_ff(luv_curr->uv[1], luv_other_curr->uv[1], limit[1]) ||
- if (separated1 || separated2) {
- faces_separated = 1;
- break;
- }
+ !compare_ff(luv_next->uv[0], luv_other_next->uv[0], limit[0]) ||
+ !compare_ff(luv_next->uv[1], luv_other_next->uv[1], limit[1])) {
+ mark = true;
+ break;
}
- }
- }
+ } while ((l_other = l_other->radial_next) != l_iter);
- if (faces_separated) {
- if (mark_seams) {
- BM_elem_flag_enable(editedge, BM_ELEM_SEAM);
- }
- if (mark_sharp) {
- BM_elem_flag_disable(editedge, BM_ELEM_SMOOTH);
+ if (mark) {
+ if (mark_seams) {
+ BM_elem_flag_enable(l_iter->e, BM_ELEM_SEAM);
+ }
+ if (mark_sharp) {
+ BM_elem_flag_disable(l_iter->e, BM_ELEM_SMOOTH);
+ }
+ changed = true;
}
- }
+ } while ((l_iter = l_iter->next) != l_first);
}
- BM_uv_vert_map_free(vmap);
-
- DEG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ if (changed) {
+ changed_multi = true;
+ DEG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ }
}
MEM_freeN(objects);
- return ret;
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static void UV_OT_seams_from_islands(wmOperatorType *ot)
@@ -2006,8 +1957,6 @@ static void UV_OT_seams_from_islands(wmOperatorType *ot)
static int uv_mark_seam_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = sima ? sima->image : NULL;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
const ToolSettings *ts = scene->toolsettings;
@@ -2038,7 +1987,7 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op)
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, ob, ima, efa)) {
+ if (uvedit_face_visible_test(scene, efa)) {
BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_edge_select_test(scene, loop, cd_loop_uv_offset)) {
BM_elem_flag_set(loop->e, BM_ELEM_SEAM, flag_set);
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index 6e931b56a85..cc9be9d48c1 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -70,9 +70,11 @@
#include "uvedit_intern.h"
-static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action);
-static void uv_select_all_perform_multi(
- Scene *scene, Image *ima, Object **objects, const uint objects_len, int action);
+static void uv_select_all_perform(Scene *scene, Object *obedit, int action);
+static void uv_select_all_perform_multi(Scene *scene,
+ Object **objects,
+ const uint objects_len,
+ int action);
static void uv_select_flush_from_tag_face(SpaceImage *sima,
Scene *scene,
Object *obedit,
@@ -112,7 +114,7 @@ static void uvedit_vertex_select_tagged(BMEditMesh *em,
}
}
-bool uvedit_face_visible_nolocal_ex(const ToolSettings *ts, BMFace *efa)
+bool uvedit_face_visible_test_ex(const ToolSettings *ts, BMFace *efa)
{
if (ts->uv_flag & UV_SYNC_SELECTION) {
return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0);
@@ -121,25 +123,9 @@ bool uvedit_face_visible_nolocal_ex(const ToolSettings *ts, BMFace *efa)
return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT));
}
}
-bool uvedit_face_visible_nolocal(const Scene *scene, BMFace *efa)
+bool uvedit_face_visible_test(const Scene *scene, BMFace *efa)
{
- return uvedit_face_visible_nolocal_ex(scene->toolsettings, efa);
-}
-
-bool uvedit_face_visible_test_ex(const ToolSettings *ts, Object *obedit, Image *ima, BMFace *efa)
-{
- if (ts->uv_flag & UV_SHOW_SAME_IMAGE) {
- Image *face_image;
- ED_object_get_active_image(obedit, efa->mat_nr + 1, &face_image, NULL, NULL, NULL);
- return (face_image == ima) ? uvedit_face_visible_nolocal_ex(ts, efa) : false;
- }
- else {
- return uvedit_face_visible_nolocal_ex(ts, efa);
- }
-}
-bool uvedit_face_visible_test(const Scene *scene, Object *obedit, Image *ima, BMFace *efa)
-{
- return uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa);
+ return uvedit_face_visible_test_ex(scene->toolsettings, efa);
}
bool uvedit_face_select_test_ex(const ToolSettings *ts, BMFace *efa, const int cd_loop_uv_offset)
@@ -437,8 +423,7 @@ void uvedit_uv_select_disable(BMEditMesh *em,
/** \name Find Nearest Elements
* \{ */
-bool uv_find_nearest_edge(
- Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit)
+bool uv_find_nearest_edge(Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMFace *efa;
@@ -453,7 +438,7 @@ bool uv_find_nearest_edge(
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
@@ -479,7 +464,6 @@ bool uv_find_nearest_edge(
}
bool uv_find_nearest_edge_multi(Scene *scene,
- Image *ima,
Object **objects,
const uint objects_len,
const float co[2],
@@ -488,7 +472,7 @@ bool uv_find_nearest_edge_multi(Scene *scene,
bool found = false;
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
- if (uv_find_nearest_edge(scene, ima, obedit, co, hit_final)) {
+ if (uv_find_nearest_edge(scene, obedit, co, hit_final)) {
hit_final->ob = obedit;
found = true;
}
@@ -496,8 +480,7 @@ bool uv_find_nearest_edge_multi(Scene *scene,
return found;
}
-bool uv_find_nearest_face(
- Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit_final)
+bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit_final)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
bool found = false;
@@ -507,7 +490,7 @@ bool uv_find_nearest_face(
/* this will fill in hit.vert1 and hit.vert2 */
float dist_sq_init = hit_final->dist_sq;
UvNearestHit hit = *hit_final;
- if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
+ if (uv_find_nearest_edge(scene, obedit, co, &hit)) {
hit.dist_sq = dist_sq_init;
hit.l = NULL;
hit.luv = hit.luv_next = NULL;
@@ -516,7 +499,7 @@ bool uv_find_nearest_face(
BMFace *efa;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -539,7 +522,6 @@ bool uv_find_nearest_face(
}
bool uv_find_nearest_face_multi(Scene *scene,
- Image *ima,
Object **objects,
const uint objects_len,
const float co[2],
@@ -548,7 +530,7 @@ bool uv_find_nearest_face_multi(Scene *scene,
bool found = false;
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
- if (uv_find_nearest_face(scene, ima, obedit, co, hit_final)) {
+ if (uv_find_nearest_face(scene, obedit, co, hit_final)) {
hit_final->ob = obedit;
found = true;
}
@@ -567,7 +549,6 @@ static bool uv_nearest_between(const BMLoop *l, const float co[2], const int cd_
}
bool uv_find_nearest_vert(Scene *scene,
- Image *ima,
Object *obedit,
float const co[2],
const float penalty_dist,
@@ -578,7 +559,7 @@ bool uv_find_nearest_vert(Scene *scene,
/* this will fill in hit.vert1 and hit.vert2 */
float dist_sq_init = hit_final->dist_sq;
UvNearestHit hit = *hit_final;
- if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
+ if (uv_find_nearest_edge(scene, obedit, co, &hit)) {
hit.dist_sq = dist_sq_init;
hit.l = NULL;
@@ -593,7 +574,7 @@ bool uv_find_nearest_vert(Scene *scene,
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -639,7 +620,6 @@ bool uv_find_nearest_vert(Scene *scene,
}
bool uv_find_nearest_vert_multi(Scene *scene,
- Image *ima,
Object **objects,
const uint objects_len,
float const co[2],
@@ -649,7 +629,7 @@ bool uv_find_nearest_vert_multi(Scene *scene,
bool found = false;
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
- if (uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, hit_final)) {
+ if (uv_find_nearest_vert(scene, obedit, co, penalty_dist, hit_final)) {
hit_final->ob = obedit;
found = true;
}
@@ -657,12 +637,8 @@ bool uv_find_nearest_vert_multi(Scene *scene,
return found;
}
-bool ED_uvedit_nearest_uv(const Scene *scene,
- Object *obedit,
- Image *ima,
- const float co[2],
- float *dist_sq,
- float r_uv[2])
+bool ED_uvedit_nearest_uv(
+ const Scene *scene, Object *obedit, const float co[2], float *dist_sq, float r_uv[2])
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMIter iter;
@@ -671,7 +647,7 @@ bool ED_uvedit_nearest_uv(const Scene *scene,
float dist_best = *dist_sq;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
BMLoop *l_iter, *l_first;
@@ -697,7 +673,6 @@ bool ED_uvedit_nearest_uv(const Scene *scene,
}
bool ED_uvedit_nearest_uv_multi(const Scene *scene,
- Image *ima,
Object **objects,
const uint objects_len,
const float co[2],
@@ -707,7 +682,7 @@ bool ED_uvedit_nearest_uv_multi(const Scene *scene,
bool found = false;
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
- if (ED_uvedit_nearest_uv(scene, obedit, ima, co, dist_sq, r_uv)) {
+ if (ED_uvedit_nearest_uv(scene, obedit, co, dist_sq, r_uv)) {
found = true;
}
}
@@ -817,12 +792,8 @@ static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em,
return true;
}
-static int uv_select_edgeloop(Scene *scene,
- Image *ima,
- Object *obedit,
- UvNearestHit *hit,
- const float limit[2],
- const bool extend)
+static int uv_select_edgeloop(
+ Scene *scene, Object *obedit, UvNearestHit *hit, const float limit[2], const bool extend)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMFace *efa;
@@ -843,7 +814,7 @@ static int uv_select_edgeloop(Scene *scene,
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
if (!extend) {
- uv_select_all_perform(scene, ima, obedit, SEL_DESELECT);
+ uv_select_all_perform(scene, obedit, SEL_DESELECT);
}
BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
@@ -867,8 +838,7 @@ static int uv_select_edgeloop(Scene *scene,
/* find correct valence edges which are not tagged yet, but connect to tagged one */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG) &&
- uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, efa)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
/* check face not hidden and not tagged */
if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l))) {
@@ -930,7 +900,6 @@ static int uv_select_edgeloop(Scene *scene,
* \{ */
static void uv_select_linked_multi(Scene *scene,
- Image *ima,
Object **objects,
const uint objects_len,
const float limit[2],
@@ -980,7 +949,7 @@ static void uv_select_linked_multi(Scene *scene,
if (hit_final == NULL) {
/* Use existing selection */
BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (uvedit_face_visible_test(scene, efa)) {
if (select_faces) {
if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
stack[stacksize] = a;
@@ -1121,14 +1090,15 @@ static void uv_select_linked_multi(Scene *scene,
* \warning This returns first selected UV,
* not ideal in many cases since there could be multiple.
*/
-const float *uvedit_first_selected_uv_from_vertex(
- Scene *scene, Object *obedit, Image *ima, BMVert *eve, const int cd_loop_uv_offset)
+const float *uvedit_first_selected_uv_from_vertex(Scene *scene,
+ BMVert *eve,
+ const int cd_loop_uv_offset)
{
BMIter liter;
BMLoop *l;
BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
- if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) {
+ if (!uvedit_face_visible_test(scene, l->f)) {
continue;
}
@@ -1151,7 +1121,6 @@ static int uv_select_more_less(bContext *C, const bool select)
{
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
SpaceImage *sima = CTX_wm_space_image(C);
BMFace *efa;
@@ -1193,7 +1162,7 @@ static int uv_select_more_less(bContext *C, const bool select)
/* mark loops to be selected */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (uvedit_face_visible_test(scene, efa)) {
#define IS_SEL 1
#define IS_UNSEL 2
@@ -1233,7 +1202,7 @@ static int uv_select_more_less(bContext *C, const bool select)
/* mark loops to be selected */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (uvedit_face_visible_test(scene, efa)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -1308,7 +1277,7 @@ void UV_OT_select_less(wmOperatorType *ot)
/** \name (De)Select All Operator
* \{ */
-bool uvedit_select_is_any_selected(Scene *scene, Image *ima, Object *obedit)
+bool uvedit_select_is_any_selected(Scene *scene, Object *obedit)
{
const ToolSettings *ts = scene->toolsettings;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -1323,7 +1292,7 @@ bool uvedit_select_is_any_selected(Scene *scene, Image *ima, Object *obedit)
else {
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1337,15 +1306,12 @@ bool uvedit_select_is_any_selected(Scene *scene, Image *ima, Object *obedit)
return false;
}
-bool uvedit_select_is_any_selected_multi(Scene *scene,
- Image *ima,
- Object **objects,
- const uint objects_len)
+bool uvedit_select_is_any_selected_multi(Scene *scene, Object **objects, const uint objects_len)
{
bool found = false;
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
- if (uvedit_select_is_any_selected(scene, ima, obedit)) {
+ if (uvedit_select_is_any_selected(scene, obedit)) {
found = true;
break;
}
@@ -1353,7 +1319,7 @@ bool uvedit_select_is_any_selected_multi(Scene *scene,
return found;
}
-static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action)
+static void uv_select_all_perform(Scene *scene, Object *obedit, int action)
{
const ToolSettings *ts = scene->toolsettings;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -1365,7 +1331,7 @@ static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
if (action == SEL_TOGGLE) {
- action = uvedit_select_is_any_selected(scene, ima, obedit) ? SEL_DESELECT : SEL_SELECT;
+ action = uvedit_select_is_any_selected(scene, obedit) ? SEL_DESELECT : SEL_SELECT;
}
if (ts->uv_flag & UV_SYNC_SELECTION) {
@@ -1387,7 +1353,7 @@ static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int
}
else {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -1410,17 +1376,19 @@ static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int
}
}
-static void uv_select_all_perform_multi(
- Scene *scene, Image *ima, Object **objects, const uint objects_len, int action)
+static void uv_select_all_perform_multi(Scene *scene,
+ Object **objects,
+ const uint objects_len,
+ int action)
{
if (action == SEL_TOGGLE) {
- action = uvedit_select_is_any_selected_multi(scene, ima, objects, objects_len) ? SEL_DESELECT :
- SEL_SELECT;
+ action = uvedit_select_is_any_selected_multi(scene, objects, objects_len) ? SEL_DESELECT :
+ SEL_SELECT;
}
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
- uv_select_all_perform(scene, ima, obedit, action);
+ uv_select_all_perform(scene, obedit, action);
}
}
@@ -1429,7 +1397,6 @@ static int uv_select_all_exec(bContext *C, wmOperator *op)
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
- Image *ima = CTX_data_edit_image(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
int action = RNA_enum_get(op->ptr, "action");
@@ -1438,7 +1405,7 @@ static int uv_select_all_exec(bContext *C, wmOperator *op)
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
view_layer, ((View3D *)NULL), &objects_len);
- uv_select_all_perform_multi(scene, ima, objects, objects_len, action);
+ uv_select_all_perform_multi(scene, objects, objects_len, action);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
@@ -1510,7 +1477,6 @@ static int uv_mouse_select_multi(bContext *C,
SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
- Image *ima = CTX_data_edit_image(C);
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
@@ -1563,12 +1529,11 @@ static int uv_mouse_select_multi(bContext *C,
/* find nearest element */
if (loop) {
/* find edge */
- found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
+ found_item = uv_find_nearest_edge_multi(scene, objects, objects_len, co, &hit);
}
else if (selectmode == UV_SELECT_VERTEX) {
/* find vertex */
- found_item = uv_find_nearest_vert_multi(
- scene, ima, objects, objects_len, co, penalty_dist, &hit);
+ found_item = uv_find_nearest_vert_multi(scene, objects, objects_len, co, penalty_dist, &hit);
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
if (found_item) {
@@ -1585,7 +1550,7 @@ static int uv_mouse_select_multi(bContext *C,
}
else if (selectmode == UV_SELECT_EDGE) {
/* find edge */
- found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
+ found_item = uv_find_nearest_edge_multi(scene, objects, objects_len, co, &hit);
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
if (found_item) {
@@ -1604,7 +1569,7 @@ static int uv_mouse_select_multi(bContext *C,
}
else if (selectmode == UV_SELECT_FACE) {
/* find face */
- found_item = uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit);
+ found_item = uv_find_nearest_face_multi(scene, objects, objects_len, co, &hit);
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
if (found_item) {
@@ -1628,13 +1593,13 @@ static int uv_mouse_select_multi(bContext *C,
}
}
else if (selectmode == UV_SELECT_ISLAND) {
- found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
+ found_item = uv_find_nearest_edge_multi(scene, objects, objects_len, co, &hit);
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
}
if (!found_item) {
if (deselect_all) {
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
@@ -1654,19 +1619,18 @@ static int uv_mouse_select_multi(bContext *C,
if (loop) {
if (!extend) {
/* TODO(MULTI_EDIT): We only need to de-select non-active */
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT);
}
- flush = uv_select_edgeloop(scene, ima, obedit, &hit, limit, extend);
+ flush = uv_select_edgeloop(scene, obedit, &hit, limit, extend);
}
else if (selectmode == UV_SELECT_ISLAND) {
if (!extend) {
/* TODO(MULTI_EDIT): We only need to de-select non-active */
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT);
}
/* Current behavior of 'extend'
* is actually toggling, so pass extend flag as 'toggle' here */
- uv_select_linked_multi(
- scene, ima, objects, objects_len, limit, &hit, false, false, extend, false);
+ uv_select_linked_multi(scene, objects, objects_len, limit, &hit, false, false, extend, false);
}
else if (extend) {
if (selectmode == UV_SELECT_VERTEX) {
@@ -1701,7 +1665,7 @@ static int uv_mouse_select_multi(bContext *C,
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -1719,7 +1683,7 @@ static int uv_mouse_select_multi(bContext *C,
}
else {
/* deselect all */
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT);
if (selectmode == UV_SELECT_VERTEX) {
/* select vertex */
@@ -1739,7 +1703,7 @@ static int uv_mouse_select_multi(bContext *C,
/* select sticky uvs */
if (sticky != SI_STICKY_DISABLE) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -1946,7 +1910,6 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
float limit[2];
bool extend = true;
bool deselect = false;
@@ -1986,18 +1949,17 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
RNA_float_get_array(op->ptr, "location", co);
}
- if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
+ if (!uv_find_nearest_edge_multi(scene, objects, objects_len, co, &hit)) {
MEM_freeN(objects);
return OPERATOR_CANCELLED;
}
}
if (!extend) {
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT);
}
uv_select_linked_multi(scene,
- ima,
objects,
objects_len,
limit,
@@ -2117,7 +2079,6 @@ static int uv_select_split_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
const ToolSettings *ts = scene->toolsettings;
- Image *ima = CTX_data_edit_image(C);
BMFace *efa;
BMLoop *l;
@@ -2147,7 +2108,7 @@ static int uv_select_split_exec(bContext *C, wmOperator *op)
bool is_sel = false;
bool is_unsel = false;
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -2483,7 +2444,6 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
const ARegion *region = CTX_wm_region(C);
BMFace *efa;
BMLoop *l;
@@ -2518,7 +2478,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
view_layer, ((View3D *)NULL), &objects_len);
if (use_pre_deselect) {
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT);
}
/* don't indent to avoid diff noise! */
@@ -2539,7 +2499,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
/* assume not touched */
BM_elem_flag_disable(efa, BM_ELEM_TAG);
- if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (uvedit_face_visible_test(scene, efa)) {
uv_poly_center(efa, cent, cd_loop_uv_offset);
if (BLI_rctf_isect_pt_v(&rectf, cent)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -2558,7 +2518,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -2594,7 +2554,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
bool has_selected = false;
@@ -2623,7 +2583,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
.efa = efa,
};
uv_select_linked_multi(
- scene, ima, objects, objects_len, limit, &hit, true, !select, false, false);
+ scene, objects, objects_len, limit, &hit, true, !select, false, false);
}
}
@@ -2708,7 +2668,6 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
const ToolSettings *ts = scene->toolsettings;
@@ -2757,7 +2716,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op);
if (use_pre_deselect) {
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT);
}
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
@@ -2792,7 +2751,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -2826,7 +2785,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
bool has_selected = false;
@@ -2847,7 +2806,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
.efa = efa,
};
uv_select_linked_multi(
- scene, ima, objects, objects_len, limit, &hit, true, !select, false, false);
+ scene, objects, objects_len, limit, &hit, true, !select, false, false);
}
}
@@ -2920,7 +2879,6 @@ static bool do_lasso_select_mesh_uv(bContext *C,
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
const ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
@@ -2952,7 +2910,7 @@ static bool do_lasso_select_mesh_uv(bContext *C,
view_layer, ((View3D *)NULL), &objects_len);
if (use_pre_deselect) {
- uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+ uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT);
}
/* don't indent to avoid diff noise! */
@@ -2988,7 +2946,7 @@ static bool do_lasso_select_mesh_uv(bContext *C,
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -3025,7 +2983,7 @@ static bool do_lasso_select_mesh_uv(bContext *C,
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
bool has_selected = false;
@@ -3047,7 +3005,7 @@ static bool do_lasso_select_mesh_uv(bContext *C,
.efa = efa,
};
uv_select_linked_multi(
- scene, ima, objects, objects_len, limit, &hit, true, !select, false, false);
+ scene, objects, objects_len, limit, &hit, true, !select, false, false);
}
}
@@ -3116,7 +3074,6 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
@@ -3134,7 +3091,7 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
bool changed = false;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
@@ -3208,7 +3165,6 @@ static int uv_select_overlap(bContext *C, const bool extend)
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = CTX_data_edit_image(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
@@ -3224,13 +3180,13 @@ static int uv_select_overlap(bContext *C, const bool extend)
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
if (!extend) {
- uv_select_all_perform(scene, ima, obedit, SEL_DESELECT);
+ uv_select_all_perform(scene, obedit, SEL_DESELECT);
}
BMIter iter;
BMFace *efa;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test_ex(scene->toolsettings, efa)) {
continue;
}
uv_tri_len += efa->len - 2;
@@ -3261,7 +3217,7 @@ static int uv_select_overlap(bContext *C, const bool extend)
int face_index;
BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, face_index) {
- if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) {
+ if (!uvedit_face_visible_test_ex(scene->toolsettings, efa)) {
continue;
}
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 3a4f12acf9c..594847b7249 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -2550,12 +2550,11 @@ static StitchState *stitch_select(bContext *C,
float co[2];
UvNearestHit hit = UV_NEAREST_HIT_INIT;
ARegion *region = CTX_wm_region(C);
- Image *ima = CTX_data_edit_image(C);
UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
if (ssc->mode == STITCH_VERT) {
- if (uv_find_nearest_vert_multi(scene, ima, ssc->objects, ssc->objects_len, co, 0.0f, &hit)) {
+ if (uv_find_nearest_vert_multi(scene, ssc->objects, ssc->objects_len, co, 0.0f, &hit)) {
/* Add vertex to selection, deselect all common uv's of vert other than selected and
* update the preview. This behavior was decided so that you can do stuff like deselect
* the opposite stitchable vertex and the initial still gets deselected */
@@ -2576,7 +2575,7 @@ static StitchState *stitch_select(bContext *C,
return state;
}
}
- else if (uv_find_nearest_edge_multi(scene, ima, ssc->objects, ssc->objects_len, co, &hit)) {
+ else if (uv_find_nearest_edge_multi(scene, ssc->objects, ssc->objects_len, co, &hit)) {
/* find StitchState from hit->ob */
StitchState *state = NULL;
for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h
index 648eb4e453d..8503836e0ca 100644
--- a/source/blender/freestyle/intern/view_map/Silhouette.h
+++ b/source/blender/freestyle/intern/view_map/Silhouette.h
@@ -1592,15 +1592,15 @@ class SShape {
/*! Splits an edge into several edges.
* The edge's vertices are passed rather than the edge itself. This way, all feature edges
- * (SILHOUETTE, CREASE, BORDER) are splitted in the same time. The processed edges are flagged as
- * done (using the userdata flag).One single new vertex is created whereas several splitted edges
+ * (SILHOUETTE, CREASE, BORDER) are split in the same time. The processed edges are flagged as
+ * done (using the user-data flag).One single new vertex is created whereas several split edges
* might created for the different kinds of edges. These new elements are added to the lists
* maintained by the shape.
* New chains are also created.
* ioA
- * The first vertex for the edge that gets splitted
+ * The first vertex for the edge that gets split.
* ioB
- * The second vertex for the edge that gets splitted
+ * The second vertex for the edge that gets split.
* iParameters
* A vector containing 2D real vectors indicating the parameters giving the intersections
* coordinates in 3D and in 2D. These intersections points must be sorted from B to A. Each
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
index 546032c64ac..cb88b1abf92 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
@@ -181,9 +181,12 @@ static void deformStroke(GpencilModifierData *md,
float *noise_table_thickness = (mmd->factor_thickness > 0.0f) ? noise_table(len, seed) : NULL;
float *noise_table_uvs = (mmd->factor_uvs > 0.0f) ? noise_table(len, seed + 4) : NULL;
- /* calculate stroke normal*/
+ /* Calculate stroke normal. */
if (gps->totpoints > 2) {
BKE_gpencil_stroke_normal(gps, normal);
+ if (is_zero_v3(normal)) {
+ copy_v3_fl(normal, 1.0f);
+ }
}
else {
copy_v3_fl(normal, 1.0f);
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 3fb48292000..ab507d852e8 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -50,7 +50,7 @@ void GPU_paint_set_mipmap(struct Main *bmain, bool mipmap);
/* Anisotropic filtering settings
* - these will free textures on changes */
-void GPU_set_anisotropic(struct Main *bmain, float value);
+void GPU_set_anisotropic(float value);
float GPU_get_anisotropic(void);
/* Image updates and free
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 337c0b03308..eeb2d2caef2 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -29,6 +29,8 @@
#include "BLI_sys_types.h" /* for bool */
+#include "GPU_texture.h" /* for eGPUSamplerState */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -138,8 +140,14 @@ typedef enum eGPUMaterialStatus {
GPUNodeLink *GPU_constant(const float *num);
GPUNodeLink *GPU_uniform(const float *num);
GPUNodeLink *GPU_attribute(GPUMaterial *mat, CustomDataType type, const char *name);
-GPUNodeLink *GPU_image(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
-GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
+GPUNodeLink *GPU_image(GPUMaterial *mat,
+ struct Image *ima,
+ struct ImageUser *iuser,
+ eGPUSamplerState sampler_state);
+GPUNodeLink *GPU_image_tiled(GPUMaterial *mat,
+ struct Image *ima,
+ struct ImageUser *iuser,
+ eGPUSamplerState sampler_state);
GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer);
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name);
@@ -190,6 +198,7 @@ void GPU_materials_free(struct Main *bmain);
struct Scene *GPU_material_scene(GPUMaterial *material);
struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
+struct GPUShader *GPU_material_get_shader(GPUMaterial *material);
struct Material *GPU_material_get_material(GPUMaterial *material);
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat);
@@ -228,6 +237,7 @@ typedef struct GPUMaterialTexture {
char sampler_name[32]; /* Name of sampler in GLSL. */
char tiled_mapping_name[32]; /* Name of tile mapping sampler in GLSL. */
int users;
+ int sampler_state; /* eGPUSamplerState */
} GPUMaterialTexture;
typedef struct GPUMaterialVolumeGrid {
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 0e382f2225f..0ad472113c9 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -92,16 +92,18 @@ void *GPU_shader_get_interface(GPUShader *shader);
void GPU_shader_set_srgb_uniform(const struct GPUShaderInterface *interface);
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
-int GPU_shader_get_uniform_ensure(GPUShader *shader, const char *name);
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin);
+int GPU_shader_get_builtin_block(GPUShader *shader, int builtin);
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
+
+int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name);
+int GPU_shader_get_texture_binding(GPUShader *shader, const char *name);
+
void GPU_shader_uniform_vector(
GPUShader *shader, int location, int length, int arraysize, const float *value);
void GPU_shader_uniform_vector_int(
GPUShader *shader, int location, int length, int arraysize, const int *value);
-void GPU_shader_uniform_buffer(GPUShader *shader, int location, struct GPUUniformBuffer *ubo);
-void GPU_shader_uniform_texture(GPUShader *shader, int location, struct GPUTexture *tex);
void GPU_shader_uniform_float(GPUShader *shader, int location, float value);
void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h
index 3e7bad409a3..28ee162bdbd 100644
--- a/source/blender/gpu/GPU_shader_interface.h
+++ b/source/blender/gpu/GPU_shader_interface.h
@@ -33,9 +33,7 @@ extern "C" {
#endif
typedef enum {
- GPU_UNIFORM_NONE = 0, /* uninitialized/unknown */
-
- GPU_UNIFORM_MODEL, /* mat4 ModelMatrix */
+ GPU_UNIFORM_MODEL = 0, /* mat4 ModelMatrix */
GPU_UNIFORM_VIEW, /* mat4 ViewMatrix */
GPU_UNIFORM_MODELVIEW, /* mat4 ModelViewMatrix */
GPU_UNIFORM_PROJECTION, /* mat4 ProjectionMatrix */
@@ -58,49 +56,56 @@ typedef enum {
GPU_UNIFORM_RESOURCE_ID, /* int resourceId */
GPU_UNIFORM_SRGB_TRANSFORM, /* bool srgbTarget */
- GPU_UNIFORM_CUSTOM, /* custom uniform, not one of the above built-ins */
-
GPU_NUM_UNIFORMS, /* Special value, denotes number of builtin uniforms. */
} GPUUniformBuiltin;
+typedef enum {
+ GPU_UNIFORM_BLOCK_VIEW = 0, /* viewBlock */
+ GPU_UNIFORM_BLOCK_MODEL, /* modelBlock */
+ GPU_UNIFORM_BLOCK_INFO, /* infoBlock */
+
+ GPU_NUM_UNIFORM_BLOCKS, /* Special value, denotes number of builtin uniforms block. */
+} GPUUniformBlockBuiltin;
+
typedef struct GPUShaderInput {
- struct GPUShaderInput *next;
uint32_t name_offset;
- uint name_hash;
- /** Only for uniform inputs. */
- GPUUniformBuiltin builtin_type;
- /** Only for attribute inputs. */
- uint32_t gl_type;
- /** Only for attribute inputs. */
- int32_t size;
+ uint32_t name_hash;
int32_t location;
+ /** Defined at interface creation or in shader. Only for Samplers, UBOs and Vertex Attribs. */
+ int32_t binding;
} GPUShaderInput;
-#define GPU_NUM_SHADERINTERFACE_BUCKETS 257
#define GPU_SHADERINTERFACE_REF_ALLOC_COUNT 16
typedef struct GPUShaderInterface {
- int32_t program;
- uint32_t name_buffer_offset;
- GPUShaderInput *attr_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
- GPUShaderInput *uniform_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
- GPUShaderInput *ubo_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
- GPUShaderInput *builtin_uniforms[GPU_NUM_UNIFORMS];
+ /** Buffer containing all inputs names separated by '\0'. */
char *name_buffer;
- struct GPUBatch **batches; /* references to batches using this interface */
+ /** Reference to GPUBatches using this interface */
+ struct GPUBatch **batches;
uint batches_len;
- /** All enabled attributes in this shader. Used to set default values for unbound attributes. */
+ /** Input counts. */
+ uint attribute_len;
+ uint ubo_len;
+ uint uniform_len;
+ /** Enabled bindpoints that needs to be fed with data. */
uint16_t enabled_attr_mask;
+ uint16_t enabled_ubo_mask;
+ uint64_t enabled_tex_mask;
+ /** Opengl Location of builtin uniforms. Fast access, no lookup needed. */
+ int32_t builtins[GPU_NUM_UNIFORMS];
+ int32_t builtin_blocks[GPU_NUM_UNIFORM_BLOCKS];
+ /** Flat array. In this order: Attributes, Ubos, Uniforms. */
+ GPUShaderInput inputs[0];
} GPUShaderInterface;
GPUShaderInterface *GPU_shaderinterface_create(int32_t program_id);
void GPU_shaderinterface_discard(GPUShaderInterface *);
const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *, const char *name);
-const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *,
- const char *name);
-const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *,
- GPUUniformBuiltin);
+int32_t GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface,
+ GPUUniformBuiltin builtin);
+int32_t GPU_shaderinterface_block_builtin(const GPUShaderInterface *shaderface,
+ GPUUniformBlockBuiltin builtin);
const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *, const char *name);
const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *, const char *name);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 3d99a3c8a56..a13f61177e6 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -41,6 +41,31 @@ struct PreviewImage;
struct GPUFrameBuffer;
typedef struct GPUTexture GPUTexture;
+/* GPU Samplers state
+ * - Specify the sampler state to bind a texture with.
+ * - Internally used by textures.
+ * - All states are created at startup to avoid runtime costs.
+ */
+
+typedef enum eGPUSamplerState {
+ GPU_SAMPLER_FILTER = (1 << 0),
+ GPU_SAMPLER_MIPMAP = (1 << 1),
+ GPU_SAMPLER_REPEAT_S = (1 << 2),
+ GPU_SAMPLER_REPEAT_T = (1 << 3),
+ GPU_SAMPLER_REPEAT_R = (1 << 4),
+ GPU_SAMPLER_CLAMP_BORDER = (1 << 5), /* Clamp to border color instead of border texel. */
+ GPU_SAMPLER_COMPARE = (1 << 6),
+ GPU_SAMPLER_ANISO = (1 << 7),
+ /* Don't use that. */
+ GPU_SAMPLER_MAX = (1 << 8),
+} eGPUSamplerState;
+
+#define GPU_SAMPLER_DEFAULT GPU_SAMPLER_FILTER
+#define GPU_SAMPLER_REPEAT (GPU_SAMPLER_REPEAT_S | GPU_SAMPLER_REPEAT_T | GPU_SAMPLER_REPEAT_R)
+
+void GPU_samplers_init(void);
+void GPU_samplers_free(void);
+
/* GPU Texture
* - always returns unsigned char RGBA textures
* - if texture with non square dimensions is created, depending on the
@@ -236,8 +261,9 @@ void GPU_texture_free(GPUTexture *tex);
void GPU_texture_ref(GPUTexture *tex);
void GPU_texture_bind(GPUTexture *tex, int number);
+void GPU_texture_bind_ex(GPUTexture *tex, eGPUSamplerState state, int unit, const bool set_number);
void GPU_texture_unbind(GPUTexture *tex);
-int GPU_texture_bound_number(GPUTexture *tex);
+void GPU_texture_unbind_all(void);
void GPU_texture_copy(GPUTexture *dst, GPUTexture *src);
diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h
index 7adad2ff831..61b14a4c5c0 100644
--- a/source/blender/gpu/GPU_vertex_format.h
+++ b/source/blender/gpu/GPU_vertex_format.h
@@ -101,12 +101,11 @@ typedef struct GPUVertFormat {
char names[GPU_VERT_ATTR_NAMES_BUF_LEN];
} GPUVertFormat;
-struct GPUShaderInterface;
+struct GPUShader;
void GPU_vertformat_clear(GPUVertFormat *);
void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src);
-void GPU_vertformat_from_interface(GPUVertFormat *format,
- const struct GPUShaderInterface *shaderface);
+void GPU_vertformat_from_shader(GPUVertFormat *format, const struct GPUShader *shader);
uint GPU_vertformat_attr_add(
GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode);
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index 3e0a1e57664..5f77f13c135 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -375,7 +375,7 @@ void GPU_batch_program_set_no_use(GPUBatch *batch,
const GPUShaderInterface *shaderface)
{
#if TRUST_NO_ONE
- assert(glIsProgram(shaderface->program));
+ assert(glIsProgram(program));
assert(batch->program_in_use == 0);
#endif
batch->interface = shaderface;
@@ -551,11 +551,11 @@ void GPU_batch_program_use_end(GPUBatch *batch)
#if TRUST_NO_ONE
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name); \
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(batch->interface, name); \
assert(uniform);
#else
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name);
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(batch->interface, name);
#endif
void GPU_batch_uniform_1ui(GPUBatch *batch, const char *name, uint value)
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 8a46e24d459..c1e7933d7ba 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -1160,7 +1160,7 @@ static int count_active_texture_sampler(GPUShader *shader, char *source)
if (*code != '\0') {
char sampler_name[64];
code = gpu_str_skip_token(code, sampler_name, sizeof(sampler_name));
- int id = GPU_shader_get_uniform_ensure(shader, sampler_name);
+ int id = GPU_shader_get_uniform(shader, sampler_name);
if (id == -1) {
continue;
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 7871907a7d4..1c346217e9f 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -158,10 +158,10 @@ static GLenum gpu_get_mipmap_filter(bool mag)
}
/* Anisotropic filtering settings */
-void GPU_set_anisotropic(Main *bmain, float value)
+void GPU_set_anisotropic(float value)
{
if (GTS.anisotropic != value) {
- GPU_free_images(bmain);
+ GPU_samplers_free();
/* Clamp value to the maximum value the graphics card supports */
const float max = GPU_max_texture_anisotropy();
@@ -170,6 +170,8 @@ void GPU_set_anisotropic(Main *bmain, float value)
}
GTS.anisotropic = value;
+
+ GPU_samplers_init();
}
}
@@ -449,22 +451,12 @@ static uint gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
BKE_image_release_ibuf(ima, ibuf, NULL);
}
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
-
if (GPU_get_mipmap()) {
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
if (ima) {
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
}
}
- else {
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
-
- if (GLEW_EXT_texture_filter_anisotropic) {
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
- }
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
@@ -1098,18 +1090,12 @@ void GPU_create_gl_tex(uint *bind,
GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
}
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
-
if (GPU_get_mipmap() && mipmap) {
glGenerateMipmap(GL_TEXTURE_2D);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
if (ima) {
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
}
}
- else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
}
else if (textarget == GL_TEXTURE_CUBE_MAP) {
int w = rectw / 3, h = recth / 2;
@@ -1132,22 +1118,13 @@ void GPU_create_gl_tex(uint *bind,
}
}
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
-
if (GPU_get_mipmap() && mipmap) {
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
if (ima) {
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
}
}
- else {
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
gpu_del_cube_map(cube_map);
}
@@ -1156,10 +1133,6 @@ void GPU_create_gl_tex(uint *bind,
}
}
- if (GLEW_EXT_texture_filter_anisotropic) {
- glTexParameterf(textarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
- }
-
glBindTexture(textarget, 0);
if (ibuf) {
@@ -1211,10 +1184,6 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
- if (GLEW_EXT_texture_filter_anisotropic) {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
- }
-
blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16;
for (i = 0; i < ibuf->dds_data.nummipmaps && (width || height); i++) {
if (width == 0) {
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index ff745787630..8dd468b5414 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -304,8 +304,8 @@ void gpu_extensions_init(void)
GG.context_local_shaders_workaround = GLEW_ARB_get_program_binary;
}
- /* Special fix for theses specific GPUs. Without thoses workaround, blender crashes on strartup.
- * (see T72098) */
+ /* Special fix for theses specific GPUs.
+ * Without this workaround, blender crashes on startup. (see T72098) */
if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) &&
(strstr(renderer, "HD Graphics 620") || strstr(renderer, "HD Graphics 630"))) {
GG.mip_render_workaround = true;
@@ -355,11 +355,13 @@ void gpu_extensions_init(void)
}
GPU_invalid_tex_init();
+ GPU_samplers_init();
}
void gpu_extensions_exit(void)
{
GPU_invalid_tex_free();
+ GPU_samplers_free();
}
bool GPU_mem_stats_supported(void)
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
index d95904c0007..9ea273f33cf 100644
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -759,13 +759,11 @@ void immVertex2iv(uint attr_id, const int data[2])
#if 0
# if TRUST_NO_ONE
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \
- name); \
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); \
assert(uniform);
# else
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \
- name);
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name);
# endif
#else
/* NOTE: It is possible to have uniform fully optimized out from the shader.
@@ -773,8 +771,7 @@ void immVertex2iv(uint attr_id, const int data[2])
* TODO(sergey): How can we detect existing-but-optimized-out uniform but still
* catch typos in uniform names passed to immUniform*() functions? */
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \
- name); \
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); \
if (uniform == NULL) \
return;
#endif
@@ -812,20 +809,9 @@ void immUniform3fv(const char *name, const float data[3])
/* can increase this limit or move to another file */
#define MAX_UNIFORM_NAME_LEN 60
-void immUniformArray3fv(const char *bare_name, const float *data, int count)
+/* Note array index is not supported for name (i.e: "array[0]"). */
+void immUniformArray3fv(const char *name, const float *data, int count)
{
- /* look up "name[0]" when given "name" */
- const size_t len = strlen(bare_name);
-#if TRUST_NO_ONE
- assert(len <= MAX_UNIFORM_NAME_LEN);
-#endif
- char name[MAX_UNIFORM_NAME_LEN];
- strcpy(name, bare_name);
- name[len + 0] = '[';
- name[len + 1] = '0';
- name[len + 2] = ']';
- name[len + 3] = '\0';
-
GET_UNIFORM
glUniform3fv(uniform->location, count, data);
}
@@ -842,20 +828,9 @@ void immUniform4fv(const char *name, const float data[4])
glUniform4fv(uniform->location, 1, data);
}
-void immUniformArray4fv(const char *bare_name, const float *data, int count)
+/* Note array index is not supported for name (i.e: "array[0]"). */
+void immUniformArray4fv(const char *name, const float *data, int count)
{
- /* look up "name[0]" when given "name" */
- const size_t len = strlen(bare_name);
-#if TRUST_NO_ONE
- assert(len <= MAX_UNIFORM_NAME_LEN);
-#endif
- char name[MAX_UNIFORM_NAME_LEN];
- strcpy(name, bare_name);
- name[len + 0] = '[';
- name[len + 1] = '0';
- name[len + 2] = ']';
- name[len + 3] = '\0';
-
GET_UNIFORM
glUniform4fv(uniform->location, count, data);
}
@@ -882,12 +857,10 @@ void immUniform4iv(const char *name, const int data[4])
void immUniformColor4f(float r, float g, float b, float a)
{
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_builtin(imm.shader_interface,
- GPU_UNIFORM_COLOR);
-#if TRUST_NO_ONE
- assert(uniform != NULL);
-#endif
- glUniform4f(uniform->location, r, g, b, a);
+ int32_t uniform_loc = GPU_shaderinterface_uniform_builtin(imm.shader_interface,
+ GPU_UNIFORM_COLOR);
+ BLI_assert(uniform_loc != -1);
+ glUniform4f(uniform_loc, r, g, b, a);
}
void immUniformColor4fv(const float rgba[4])
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 97e4c880644..d2384b9c065 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -209,6 +209,11 @@ GPUPass *GPU_material_get_pass(GPUMaterial *material)
return material->pass;
}
+GPUShader *GPU_material_get_shader(GPUMaterial *material)
+{
+ return material->pass ? GPU_pass_shader_get(material->pass) : NULL;
+}
+
/* Return can be NULL if it's a world material. */
Material *GPU_material_get_material(GPUMaterial *material)
{
@@ -662,6 +667,9 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
/* Caller must re-use materials. */
BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
+ /* HACK: Eevee assume this to create Ghash keys. */
+ BLI_assert(sizeof(GPUPass) > 16);
+
/* allocate material */
GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");
mat->ma = ma;
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
index 8260e1496ff..2687f56ad27 100644
--- a/source/blender/gpu/intern/gpu_matrix.c
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -654,63 +654,59 @@ void GPU_matrix_bind(const GPUShaderInterface *shaderface)
* call glUseProgram before this, as glUniform expects program to be bound
*/
- const GPUShaderInput *MV = GPU_shaderinterface_uniform_builtin(shaderface,
- GPU_UNIFORM_MODELVIEW);
- const GPUShaderInput *P = GPU_shaderinterface_uniform_builtin(shaderface,
- GPU_UNIFORM_PROJECTION);
- const GPUShaderInput *MVP = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MVP);
-
- const GPUShaderInput *N = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_NORMAL);
- const GPUShaderInput *MV_inv = GPU_shaderinterface_uniform_builtin(shaderface,
- GPU_UNIFORM_MODELVIEW_INV);
- const GPUShaderInput *P_inv = GPU_shaderinterface_uniform_builtin(shaderface,
- GPU_UNIFORM_PROJECTION_INV);
-
- if (MV) {
+ int32_t MV = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MODELVIEW);
+ int32_t P = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_PROJECTION);
+ int32_t MVP = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MVP);
+
+ int32_t N = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_NORMAL);
+ int32_t MV_inv = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MODELVIEW_INV);
+ int32_t P_inv = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_PROJECTION_INV);
+
+ if (MV != -1) {
#if DEBUG_MATRIX_BIND
puts("setting MV matrix");
#endif
- glUniformMatrix4fv(MV->location, 1, GL_FALSE, (const float *)GPU_matrix_model_view_get(NULL));
+ glUniformMatrix4fv(MV, 1, GL_FALSE, (const float *)GPU_matrix_model_view_get(NULL));
}
- if (P) {
+ if (P != -1) {
#if DEBUG_MATRIX_BIND
puts("setting P matrix");
#endif
- glUniformMatrix4fv(P->location, 1, GL_FALSE, (const float *)GPU_matrix_projection_get(NULL));
+ glUniformMatrix4fv(P, 1, GL_FALSE, (const float *)GPU_matrix_projection_get(NULL));
}
- if (MVP) {
+ if (MVP != -1) {
#if DEBUG_MATRIX_BIND
puts("setting MVP matrix");
#endif
glUniformMatrix4fv(
- MVP->location, 1, GL_FALSE, (const float *)GPU_matrix_model_view_projection_get(NULL));
+ MVP, 1, GL_FALSE, (const float *)GPU_matrix_model_view_projection_get(NULL));
}
- if (N) {
+ if (N != -1) {
#if DEBUG_MATRIX_BIND
puts("setting normal matrix");
#endif
- glUniformMatrix3fv(N->location, 1, GL_FALSE, (const float *)GPU_matrix_normal_get(NULL));
+ glUniformMatrix3fv(N, 1, GL_FALSE, (const float *)GPU_matrix_normal_get(NULL));
}
- if (MV_inv) {
+ if (MV_inv != -1) {
Mat4 m;
GPU_matrix_model_view_get(m);
invert_m4(m);
- glUniformMatrix4fv(MV_inv->location, 1, GL_FALSE, (const float *)m);
+ glUniformMatrix4fv(MV_inv, 1, GL_FALSE, (const float *)m);
}
- if (P_inv) {
+ if (P_inv != -1) {
Mat4 m;
GPU_matrix_projection_get(m);
invert_m4(m);
- glUniformMatrix4fv(P_inv->location, 1, GL_FALSE, (const float *)m);
+ glUniformMatrix4fv(P_inv, 1, GL_FALSE, (const float *)m);
}
gpu_matrix_state_active_set_dirty(false);
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index 876a6bef670..17d97dc05e2 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -34,6 +34,8 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "GPU_texture.h"
+
#include "gpu_material_library.h"
#include "gpu_node_graph.h"
@@ -298,13 +300,14 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
Image *ima,
ImageUser *iuser,
struct GPUTexture **colorband,
- GPUNodeLinkType link_type)
+ GPUNodeLinkType link_type,
+ eGPUSamplerState sampler_state)
{
/* Find existing texture. */
int num_textures = 0;
GPUMaterialTexture *tex = graph->textures.first;
for (; tex; tex = tex->next) {
- if (tex->ima == ima && tex->colorband == colorband) {
+ if (tex->ima == ima && tex->colorband == colorband && tex->sampler_state == sampler_state) {
break;
}
num_textures++;
@@ -316,6 +319,7 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
tex->ima = ima;
tex->iuser = iuser;
tex->colorband = colorband;
+ tex->sampler_state = sampler_state;
BLI_snprintf(tex->sampler_name, sizeof(tex->sampler_name), "samp%d", num_textures);
if (ELEM(link_type, GPU_NODE_LINK_IMAGE_TILED, GPU_NODE_LINK_IMAGE_TILED_MAPPING)) {
BLI_snprintf(
@@ -389,21 +393,29 @@ GPUNodeLink *GPU_uniform(const float *num)
return link;
}
-GPUNodeLink *GPU_image(GPUMaterial *mat, Image *ima, ImageUser *iuser)
+GPUNodeLink *GPU_image(GPUMaterial *mat,
+ Image *ima,
+ ImageUser *iuser,
+ eGPUSamplerState sampler_state)
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE;
- link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, ima, iuser, NULL, link->link_type, sampler_state);
return link;
}
-GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, Image *ima, ImageUser *iuser)
+GPUNodeLink *GPU_image_tiled(GPUMaterial *mat,
+ Image *ima,
+ ImageUser *iuser,
+ eGPUSamplerState sampler_state)
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_TILED;
- link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, ima, iuser, NULL, link->link_type, sampler_state);
return link;
}
@@ -412,7 +424,8 @@ GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, Image *ima, ImageUser *iu
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING;
- link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, ima, iuser, NULL, link->link_type, GPU_SAMPLER_MAX);
return link;
}
@@ -424,7 +437,8 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_COLORBAND;
- link->texture = gpu_node_graph_add_texture(graph, NULL, NULL, colorband, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, NULL, NULL, colorband, link->link_type, GPU_SAMPLER_MAX);
return link;
}
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 8dfc992ae9f..8c03567b95f 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -331,6 +331,8 @@ GPUShader *GPU_shader_load_from_binary(const char *binary,
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (success) {
+ glUseProgram(program);
+
GPUShader *shader = MEM_callocN(sizeof(*shader), __func__);
shader->interface = GPU_shaderinterface_create(program);
shader->program = program;
@@ -572,6 +574,7 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
return NULL;
}
+ glUseProgram(shader->program);
shader->interface = GPU_shaderinterface_create(shader->program);
return shader;
@@ -726,21 +729,19 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
{
BLI_assert(shader && shader->program);
const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shader->interface, name);
- return uniform ? uniform->location : -2;
+ return uniform ? uniform->location : -1;
}
-int GPU_shader_get_uniform_ensure(GPUShader *shader, const char *name)
+int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin)
{
BLI_assert(shader && shader->program);
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(shader->interface, name);
- return uniform ? uniform->location : -1;
+ return GPU_shaderinterface_uniform_builtin(shader->interface, builtin);
}
-int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin)
+int GPU_shader_get_builtin_block(GPUShader *shader, int builtin)
{
BLI_assert(shader && shader->program);
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_builtin(shader->interface, builtin);
- return uniform ? uniform->location : -1;
+ return GPU_shaderinterface_block_builtin(shader->interface, builtin);
}
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
@@ -750,6 +751,20 @@ int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
return ubo ? ubo->location : -1;
}
+int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name)
+{
+ BLI_assert(shader && shader->program);
+ const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name);
+ return ubo ? ubo->binding : -1;
+}
+
+int GPU_shader_get_texture_binding(GPUShader *shader, const char *name)
+{
+ BLI_assert(shader && shader->program);
+ const GPUShaderInput *tex = GPU_shaderinterface_uniform(shader->interface, name);
+ return tex ? tex->binding : -1;
+}
+
void *GPU_shader_get_interface(GPUShader *shader)
{
return shader->interface;
@@ -837,40 +852,11 @@ void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
glUniform1i(location, value);
}
-void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo)
-{
- int bindpoint = GPU_uniformbuffer_bindpoint(ubo);
-
- if (location == -1) {
- return;
- }
-
- glUniformBlockBinding(shader->program, location, bindpoint);
-}
-
-void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
-{
- int number = GPU_texture_bound_number(tex);
-
- if (number == -1) {
- fprintf(stderr, "Texture is not bound.\n");
- BLI_assert(0);
- return;
- }
-
- if (location == -1) {
- return;
- }
-
- glUniform1i(location, number);
-}
-
void GPU_shader_set_srgb_uniform(const GPUShaderInterface *interface)
{
- const GPUShaderInput *srgb_uniform = GPU_shaderinterface_uniform_builtin(
- interface, GPU_UNIFORM_SRGB_TRANSFORM);
- if (srgb_uniform) {
- glUniform1i(srgb_uniform->location, g_shader_builtin_srgb_transform);
+ int32_t loc = GPU_shaderinterface_uniform_builtin(interface, GPU_UNIFORM_SRGB_TRANSFORM);
+ if (loc != -1) {
+ glUniform1i(loc, g_shader_builtin_srgb_transform);
}
}
diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
index 3218d12bc0d..9d9f98c6bb0 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.c
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -24,6 +24,10 @@
*/
#include "BKE_global.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_math_base.h"
+
#include "MEM_guardedalloc.h"
#include "GPU_shader_interface.h"
@@ -36,7 +40,6 @@
#include <string.h>
#define DEBUG_SHADER_INTERFACE 0
-#define DEBUG_SHADER_UNIFORMS 0
#if DEBUG_SHADER_INTERFACE
# include <stdio.h>
@@ -45,8 +48,6 @@
static const char *BuiltinUniform_name(GPUUniformBuiltin u)
{
static const char *names[] = {
- [GPU_UNIFORM_NONE] = NULL,
-
[GPU_UNIFORM_MODEL] = "ModelMatrix",
[GPU_UNIFORM_VIEW] = "ViewMatrix",
[GPU_UNIFORM_MODELVIEW] = "ModelViewMatrix",
@@ -70,13 +71,25 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u)
[GPU_UNIFORM_RESOURCE_ID] = "resourceId",
[GPU_UNIFORM_SRGB_TRANSFORM] = "srgbTarget",
- [GPU_UNIFORM_CUSTOM] = NULL,
[GPU_NUM_UNIFORMS] = NULL,
};
return names[u];
}
+static const char *BuiltinUniformBlock_name(GPUUniformBlockBuiltin u)
+{
+ static const char *names[] = {
+ [GPU_UNIFORM_BLOCK_VIEW] = "viewBlock",
+ [GPU_UNIFORM_BLOCK_MODEL] = "modelBlock",
+ [GPU_UNIFORM_BLOCK_INFO] = "infoBlock",
+
+ [GPU_NUM_UNIFORM_BLOCKS] = NULL,
+ };
+
+ return names[u];
+}
+
GPU_INLINE bool match(const char *a, const char *b)
{
return strcmp(a, b) == 0;
@@ -91,129 +104,136 @@ GPU_INLINE uint hash_string(const char *str)
return i;
}
-GPU_INLINE void set_input_name(GPUShaderInterface *shaderface,
- GPUShaderInput *input,
- const char *name,
- uint32_t name_len)
+GPU_INLINE uint32_t set_input_name(GPUShaderInterface *shaderface,
+ GPUShaderInput *input,
+ char *name,
+ uint32_t name_len)
{
- input->name_offset = shaderface->name_buffer_offset;
- input->name_hash = hash_string(name);
- shaderface->name_buffer_offset += name_len + 1; /* include NULL terminator */
-}
+ /* remove "[0]" from array name */
+ if (name[name_len - 1] == ']') {
+ name[name_len - 3] = '\0';
+ name_len -= 3;
+ }
-GPU_INLINE void shader_input_to_bucket(GPUShaderInput *input,
- GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS])
-{
- const uint bucket_index = input->name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS;
- input->next = buckets[bucket_index];
- buckets[bucket_index] = input;
+ input->name_offset = (uint32_t)(name - shaderface->name_buffer);
+ input->name_hash = hash_string(name);
+ return name_len + 1; /* include NULL terminator */
}
-GPU_INLINE const GPUShaderInput *buckets_lookup(
- GPUShaderInput *const buckets[GPU_NUM_SHADERINTERFACE_BUCKETS],
- const char *name_buffer,
- const char *name)
+GPU_INLINE const GPUShaderInput *input_lookup(const GPUShaderInterface *shaderface,
+ const GPUShaderInput *const inputs,
+ const uint inputs_len,
+ const char *name)
{
const uint name_hash = hash_string(name);
- const uint bucket_index = name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS;
- const GPUShaderInput *input = buckets[bucket_index];
- if (input == NULL) {
- /* Requested uniform is not found at all. */
- return NULL;
- }
- /* Optimization bit: if there is no hash collision detected when constructing shader interface
- * it means we can only request the single possible uniform. Surely, it's possible we request
- * uniform which causes hash collision, but that will be detected in debug builds. */
- if (input->next == NULL) {
- if (name_hash == input->name_hash) {
-#if TRUST_NO_ONE
- assert(match(name_buffer + input->name_offset, name));
-#endif
- return input;
- }
- return NULL;
- }
- /* Work through possible collisions. */
- const GPUShaderInput *next = input;
- while (next != NULL) {
- input = next;
- next = input->next;
- if (input->name_hash != name_hash) {
- continue;
- }
- if (match(name_buffer + input->name_offset, name)) {
- return input;
+ /* Simple linear search for now. */
+ for (int i = inputs_len - 1; i >= 0; i--) {
+ if (inputs[i].name_hash == name_hash) {
+ if ((i > 0) && UNLIKELY(inputs[i - 1].name_hash == name_hash)) {
+ /* Hash colision resolve. */
+ for (; i >= 0 && inputs[i].name_hash == name_hash; i--) {
+ if (match(name, shaderface->name_buffer + inputs[i].name_offset)) {
+ return inputs + i; /* not found */
+ }
+ }
+ return NULL; /* not found */
+ }
+ else {
+ /* This is a bit dangerous since we could have a hash collision.
+ * where the asked uniform that does not exist has the same hash
+ * as a real uniform. */
+ BLI_assert(match(name, shaderface->name_buffer + inputs[i].name_offset));
+ return inputs + i;
+ }
}
}
return NULL; /* not found */
}
-GPU_INLINE void buckets_free(GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS])
+/* Note that this modify the src array. */
+GPU_INLINE void sort_input_list(GPUShaderInput *dst, GPUShaderInput *src, const uint input_len)
{
- for (uint bucket_index = 0; bucket_index < GPU_NUM_SHADERINTERFACE_BUCKETS; bucket_index++) {
- GPUShaderInput *input = buckets[bucket_index];
- while (input != NULL) {
- GPUShaderInput *input_next = input->next;
- MEM_freeN(input);
- input = input_next;
+ for (uint i = 0; i < input_len; i++) {
+ GPUShaderInput *input_src = &src[0];
+ for (uint j = 1; j < input_len; j++) {
+ if (src[j].name_hash > input_src->name_hash) {
+ input_src = &src[j];
+ }
}
+ dst[i] = *input_src;
+ input_src->name_hash = 0;
}
}
-static bool setup_builtin_uniform(GPUShaderInput *input, const char *name)
+static int block_binding(int32_t program, uint32_t block_index)
{
- /* TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types */
-
- /* detect built-in uniforms (name must match) */
- for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; u++) {
- const char *builtin_name = BuiltinUniform_name(u);
- if (match(name, builtin_name)) {
- input->builtin_type = u;
- return true;
- }
- }
- input->builtin_type = GPU_UNIFORM_CUSTOM;
- return false;
+ /* 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. */
+ glUniformBlockBinding(program, block_index, block_index);
+ return block_index;
}
-static const GPUShaderInput *add_uniform(GPUShaderInterface *shaderface, const char *name)
+static int sampler_binding(int32_t program,
+ uint32_t uniform_index,
+ int32_t uniform_location,
+ int *sampler_len)
{
- GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Unif");
-
- input->location = glGetUniformLocation(shaderface->program, name);
-
- const uint name_len = strlen(name);
- /* Include NULL terminator. */
- shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer,
- shaderface->name_buffer_offset + name_len + 1);
- char *name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset;
- strcpy(name_buffer, name);
-
- set_input_name(shaderface, input, name, name_len);
- setup_builtin_uniform(input, name);
-
- shader_input_to_bucket(input, shaderface->uniform_buckets);
- if (input->builtin_type != GPU_UNIFORM_NONE && input->builtin_type != GPU_UNIFORM_CUSTOM) {
- shaderface->builtin_uniforms[input->builtin_type] = input;
+ /* Identify sampler uniforms and asign sampler units to them. */
+ GLint type;
+ glGetActiveUniformsiv(program, 1, &uniform_index, GL_UNIFORM_TYPE, &type);
+
+ switch (type) {
+ case GL_SAMPLER_1D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_CUBE_MAP_ARRAY_ARB: /* OpenGL 4.0 */
+ case GL_SAMPLER_1D_SHADOW:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_1D_ARRAY:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_1D_ARRAY_SHADOW:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ case GL_SAMPLER_2D_MULTISAMPLE:
+ case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_SAMPLER_CUBE_SHADOW:
+ case GL_SAMPLER_BUFFER:
+ case GL_INT_SAMPLER_1D:
+ case GL_INT_SAMPLER_2D:
+ case GL_INT_SAMPLER_3D:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_1D_ARRAY:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_INT_SAMPLER_BUFFER:
+ case GL_UNSIGNED_INT_SAMPLER_1D:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_BUFFER: {
+ /* 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 = *sampler_len;
+ glUniform1i(uniform_location, binding);
+ (*sampler_len)++;
+ return binding;
+ }
+ default:
+ return -1;
}
-#if DEBUG_SHADER_INTERFACE
- printf("GPUShaderInterface %p, program %d, uniform[] '%s' at location %d\n",
- shaderface,
- shaderface->program,
- name,
- input->location);
-#endif
- return input;
}
GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
{
- GPUShaderInterface *shaderface = MEM_callocN(sizeof(GPUShaderInterface), "GPUShaderInterface");
- shaderface->program = program;
-
-#if DEBUG_SHADER_INTERFACE
- printf("%s {\n", __func__); /* enter function */
- printf("GPUShaderInterface %p, program %d\n", shaderface, program);
+#ifndef NDEBUG
+ GLint curr_program;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &curr_program);
+ BLI_assert(curr_program == program);
#endif
GLint max_attr_name_len = 0, attr_len = 0;
@@ -224,6 +244,11 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len);
glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len);
+ GLint max_uniform_name_len = 0, active_uniform_len = 0, uniform_len = 0;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_name_len);
+ glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_len);
+ uniform_len = active_uniform_len;
+
/* Work around driver bug with Intel HD 4600 on Windows 7/8, where
* GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH does not work. */
if (attr_len > 0 && max_attr_name_len == 0) {
@@ -232,87 +257,190 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
if (ubo_len > 0 && max_ubo_name_len == 0) {
max_ubo_name_len = 256;
}
+ if (uniform_len > 0 && max_uniform_name_len == 0) {
+ max_uniform_name_len = 256;
+ }
+
+ /* GL_ACTIVE_UNIFORMS lied to us! Remove the UBO uniforms from the total before
+ * allocating the uniform array. */
+ GLint max_ubo_uni_len = 0;
+ for (int i = 0; i < ubo_len; i++) {
+ GLint ubo_uni_len;
+ glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &ubo_uni_len);
+ max_ubo_uni_len = max_ii(max_ubo_uni_len, ubo_uni_len);
+ uniform_len -= ubo_uni_len;
+ }
+ /* Bit set to true if uniform comes from a uniform block. */
+ BLI_bitmap *uniforms_from_blocks = BLI_BITMAP_NEW(active_uniform_len, __func__);
+ /* Set uniforms from block for exclusion. */
+ GLint *ubo_uni_ids = MEM_mallocN(sizeof(GLint) * max_ubo_uni_len, __func__);
+ for (int i = 0; i < ubo_len; i++) {
+ GLint ubo_uni_len;
+ glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &ubo_uni_len);
+ glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, ubo_uni_ids);
+ for (int u = 0; u < ubo_uni_len; u++) {
+ BLI_BITMAP_ENABLE(uniforms_from_blocks, ubo_uni_ids[u]);
+ }
+ }
+ MEM_freeN(ubo_uni_ids);
- const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len;
+ uint32_t name_buffer_offset = 0;
+ const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len +
+ uniform_len * max_uniform_name_len;
+
+ int input_tot_len = attr_len + ubo_len + uniform_len;
+ size_t interface_size = sizeof(GPUShaderInterface) + sizeof(GPUShaderInput) * input_tot_len;
+
+ GPUShaderInterface *shaderface = MEM_callocN(interface_size, "GPUShaderInterface");
+ shaderface->attribute_len = attr_len;
+ shaderface->ubo_len = ubo_len;
+ shaderface->uniform_len = uniform_len;
shaderface->name_buffer = MEM_mallocN(name_buffer_len, "name_buffer");
+ GPUShaderInput *inputs = shaderface->inputs;
+
+ /* Temp buffer. */
+ int input_tmp_len = max_iii(attr_len, ubo_len, uniform_len);
+ GPUShaderInput *inputs_tmp = MEM_mallocN(sizeof(GPUShaderInput) * input_tmp_len, "name_buffer");
/* Attributes */
shaderface->enabled_attr_mask = 0;
- for (uint32_t i = 0; i < attr_len; i++) {
- GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Attr");
- GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
- char *name = shaderface->name_buffer + shaderface->name_buffer_offset;
+ for (int i = 0, idx = 0; i < attr_len; i++) {
+ char *name = shaderface->name_buffer + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
GLsizei name_len = 0;
+ GLenum type;
+ GLint size;
- glGetActiveAttrib(
- program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name);
-
- /* remove "[0]" from array name */
- if (name[name_len - 1] == ']') {
- name[name_len - 3] = '\0';
- name_len -= 3;
- }
-
- /* TODO: reject DOUBLE gl_types */
- input->location = glGetAttribLocation(program, name);
+ glGetActiveAttrib(program, i, remaining_buffer, &name_len, &size, &type, name);
+ GLint location = glGetAttribLocation(program, name);
/* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */
- if (input->location == -1) {
- MEM_freeN(input);
+ if (location == -1) {
+ shaderface->attribute_len--;
continue;
}
- if (input->location != -1) {
- shaderface->enabled_attr_mask |= (1 << input->location);
- }
-
- set_input_name(shaderface, input, name, name_len);
-
- shader_input_to_bucket(input, shaderface->attr_buckets);
+ GPUShaderInput *input = &inputs_tmp[idx++];
+ input->location = input->binding = location;
-#if DEBUG_SHADER_INTERFACE
- printf("attr[%u] '%s' at location %d\n", i, name, input->location);
-#endif
+ name_buffer_offset += set_input_name(shaderface, input, name, name_len);
+ shaderface->enabled_attr_mask |= (1 << input->location);
}
+ sort_input_list(inputs, inputs_tmp, shaderface->attribute_len);
+ inputs += shaderface->attribute_len;
+
/* Uniform Blocks */
- for (uint32_t i = 0; i < ubo_len; i++) {
- GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput UBO");
- GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
- char *name = shaderface->name_buffer + shaderface->name_buffer_offset;
+ for (int i = 0, idx = 0; i < ubo_len; i++) {
+ char *name = shaderface->name_buffer + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
GLsizei name_len = 0;
glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name);
- input->location = i;
+ GPUShaderInput *input = &inputs_tmp[idx++];
+ input->binding = input->location = block_binding(program, i);
- set_input_name(shaderface, input, name, name_len);
+ name_buffer_offset += set_input_name(shaderface, input, name, name_len);
+ shaderface->enabled_ubo_mask |= (1 << input->binding);
+ }
+ sort_input_list(inputs, inputs_tmp, shaderface->ubo_len);
+ inputs += shaderface->ubo_len;
- shader_input_to_bucket(input, shaderface->ubo_buckets);
+ /* Uniforms */
+ for (int i = 0, idx = 0, sampler = 0; i < active_uniform_len; i++) {
+ if (BLI_BITMAP_TEST(uniforms_from_blocks, i)) {
+ continue;
+ }
+ char *name = shaderface->name_buffer + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
+ GLsizei name_len = 0;
-#if DEBUG_SHADER_INTERFACE
- printf("ubo '%s' at location %d\n", name, input->location);
-#endif
+ glGetActiveUniformName(program, i, remaining_buffer, &name_len, name);
+
+ GPUShaderInput *input = &inputs_tmp[idx++];
+ input->location = glGetUniformLocation(program, name);
+ input->binding = sampler_binding(program, i, input->location, &sampler);
+
+ name_buffer_offset += set_input_name(shaderface, input, name, name_len);
+ shaderface->enabled_tex_mask |= (input->binding != -1) ? (1lu << input->binding) : 0lu;
}
+ sort_input_list(inputs, inputs_tmp, shaderface->uniform_len);
+
/* Builtin Uniforms */
- for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; u++) {
- const char *builtin_name = BuiltinUniform_name(u);
- if (glGetUniformLocation(program, builtin_name) != -1) {
- add_uniform((GPUShaderInterface *)shaderface, builtin_name);
- }
+ for (GPUUniformBuiltin u = 0; u < GPU_NUM_UNIFORMS; u++) {
+ shaderface->builtins[u] = glGetUniformLocation(program, BuiltinUniform_name(u));
}
+
+ /* Builtin Uniforms Blocks */
+ for (GPUUniformBlockBuiltin u = 0; u < GPU_NUM_UNIFORM_BLOCKS; u++) {
+ const GPUShaderInput *block = GPU_shaderinterface_ubo(shaderface, BuiltinUniformBlock_name(u));
+ shaderface->builtin_blocks[u] = (block != NULL) ? block->binding : -1;
+ }
+
/* Batches ref buffer */
shaderface->batches_len = GPU_SHADERINTERFACE_REF_ALLOC_COUNT;
shaderface->batches = MEM_callocN(shaderface->batches_len * sizeof(GPUBatch *),
"GPUShaderInterface batches");
+ MEM_freeN(uniforms_from_blocks);
+ MEM_freeN(inputs_tmp);
+
+ /* Resize name buffer to save some memory. */
+ if (name_buffer_offset < name_buffer_len) {
+ shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer, name_buffer_offset);
+ }
+
+#if DEBUG_SHADER_INTERFACE
+ char *name_buf = shaderface->name_buffer;
+ printf("--- GPUShaderInterface %p, program %d ---\n", shaderface, program);
+ if (shaderface->attribute_len > 0) {
+ printf("Attributes {\n");
+ for (int i = 0; i < shaderface->attribute_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + i;
+ printf("\t(location = %d) %s;\n", input->location, name_buf + input->name_offset);
+ }
+ printf("};\n");
+ }
+ if (shaderface->ubo_len > 0) {
+ printf("Uniform Buffer Objects {\n");
+ for (int i = 0; i < shaderface->ubo_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len + i;
+ printf("\t(binding = %d) %s;\n", input->binding, name_buf + input->name_offset);
+ }
+ printf("};\n");
+ }
+ if (shaderface->enabled_tex_mask > 0) {
+ printf("Samplers {\n");
+ for (int i = 0; i < shaderface->uniform_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len +
+ shaderface->ubo_len + i;
+ if (input->binding != -1) {
+ printf("\t(location = %d, binding = %d) %s;\n",
+ input->location,
+ input->binding,
+ name_buf + input->name_offset);
+ }
+ }
+ printf("};\n");
+ }
+ if (shaderface->uniform_len > 0) {
+ printf("Uniforms {\n");
+ for (int i = 0; i < shaderface->uniform_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len +
+ shaderface->ubo_len + i;
+ if (input->binding == -1) {
+ printf("\t(location = %d) %s;\n", input->location, name_buf + input->name_offset);
+ }
+ }
+ printf("};\n");
+ }
+ printf("--- GPUShaderInterface end ---\n\n");
+#endif
+
return shaderface;
}
void GPU_shaderinterface_discard(GPUShaderInterface *shaderface)
{
- /* Free memory used by buckets and has entries. */
- buckets_free(shaderface->uniform_buckets);
- buckets_free(shaderface->attr_buckets);
- buckets_free(shaderface->ubo_buckets);
/* Free memory used by name_buffer. */
MEM_freeN(shaderface->name_buffer);
/* Remove this interface from all linked Batches vao cache. */
@@ -326,59 +454,39 @@ void GPU_shaderinterface_discard(GPUShaderInterface *shaderface)
MEM_freeN(shaderface);
}
-const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface,
- const char *name)
+const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface,
+ const char *name)
{
- return buckets_lookup(shaderface->uniform_buckets, shaderface->name_buffer, name);
+ uint ofs = 0;
+ return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->attribute_len, name);
}
-const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *shaderface,
- const char *name)
+const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface,
+ const char *name)
{
- const GPUShaderInput *input = GPU_shaderinterface_uniform(shaderface, name);
- /* If input is not found add it so it's found next time. */
- if (input == NULL) {
- input = add_uniform((GPUShaderInterface *)shaderface, name);
-
- if ((G.debug & G_DEBUG_GPU) && (input->location == -1)) {
- fprintf(stderr, "GPUShaderInterface: Warning: Uniform '%s' not found!\n", name);
- }
- }
-
-#if DEBUG_SHADER_UNIFORMS
- if ((G.debug & G_DEBUG_GPU) && input->builtin_type != GPU_UNIFORM_NONE &&
- input->builtin_type != GPU_UNIFORM_CUSTOM) {
- /* Warn if we find a matching builtin, since these can be looked up much quicker. */
- fprintf(stderr,
- "GPUShaderInterface: Warning: Uniform '%s' is a builtin uniform but not queried as "
- "such!\n",
- name);
- }
-#endif
- return (input->location != -1) ? input : NULL;
+ uint ofs = shaderface->attribute_len;
+ return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->ubo_len, name);
}
-const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface,
- GPUUniformBuiltin builtin)
+const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface,
+ const char *name)
{
-#if TRUST_NO_ONE
- assert(builtin != GPU_UNIFORM_NONE);
- assert(builtin != GPU_UNIFORM_CUSTOM);
- assert(builtin != GPU_NUM_UNIFORMS);
-#endif
- return shaderface->builtin_uniforms[builtin];
+ uint ofs = shaderface->attribute_len + shaderface->ubo_len;
+ return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->uniform_len, name);
}
-const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface,
- const char *name)
+int32_t GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface,
+ GPUUniformBuiltin builtin)
{
- return buckets_lookup(shaderface->ubo_buckets, shaderface->name_buffer, name);
+ BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORMS);
+ return shaderface->builtins[builtin];
}
-const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface,
- const char *name)
+int32_t GPU_shaderinterface_block_builtin(const GPUShaderInterface *shaderface,
+ GPUUniformBlockBuiltin builtin)
{
- return buckets_lookup(shaderface->attr_buckets, shaderface->name_buffer, name);
+ BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORM_BLOCKS);
+ return shaderface->builtin_blocks[builtin];
}
void GPU_shaderinterface_add_batch_ref(GPUShaderInterface *shaderface, GPUBatch *batch)
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index fd01ddf8597..ca0d633aa9e 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -50,7 +50,9 @@ static struct GPUTextureGlobal {
GPUTexture *invalid_tex_1D;
GPUTexture *invalid_tex_2D;
GPUTexture *invalid_tex_3D;
-} GG = {NULL, NULL, NULL};
+ /** Sampler objects used to replace internal texture parameters. */
+ GLuint samplers[GPU_SAMPLER_MAX];
+} GG = {NULL};
/* Maximum number of FBOs a texture can be attached to. */
#define GPU_TEX_MAX_FBO_ATTACHED 12
@@ -72,7 +74,7 @@ typedef enum eGPUTextureFormatFlag {
struct GPUTexture {
int w, h, d; /* width/height/depth */
int orig_w, orig_h; /* width/height (of source data), optional. */
- int number; /* number for multitexture binding */
+ int number; /* Texture unit to which this texture is bound. */
int refcount; /* reference count */
GLenum target; /* GL_TEXTURE_* */
GLenum target_base; /* same as target, (but no multisample)
@@ -81,6 +83,7 @@ struct GPUTexture {
eGPUTextureFormat format;
eGPUTextureFormatFlag format_flag;
+ eGPUSamplerState sampler_state; /* Internal Sampler state. */
int mipmaps; /* number of mipmaps */
int components; /* number of color/alpha channels */
@@ -94,6 +97,7 @@ struct GPUTexture {
};
static uint gpu_get_bytesize(eGPUTextureFormat data_type);
+static void gpu_texture_framebuffer_ensure(GPUTexture *tex);
/* ------ Memory Management ------- */
/* Records every texture allocation / free
@@ -826,12 +830,12 @@ GPUTexture *GPU_texture_create_nD(int w,
tex->h = h;
tex->d = d;
tex->samples = samples;
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->mipmaps = 0;
tex->format_flag = 0;
+ tex->number = -1;
if (n == 2) {
if (d == 0) {
@@ -975,26 +979,13 @@ GPUTexture *GPU_texture_create_nD(int w,
if (GPU_texture_stencil(tex) || /* Does not support filtering */
GPU_texture_integer(tex) || /* Does not support filtering */
GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER;
}
else {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
-
- if (GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- }
-
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- if (n > 1) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- if (n > 2) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT;
}
+ /* Avoid issue with incomplete textures. */
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(tex->target, 0);
@@ -1013,12 +1004,12 @@ GPUTexture *GPU_texture_cube_create(int w,
tex->h = w;
tex->d = d;
tex->samples = 0;
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->mipmaps = 0;
tex->format_flag = GPU_FORMAT_CUBE;
+ tex->number = -1;
if (d == 0) {
tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP;
@@ -1116,22 +1107,13 @@ GPUTexture *GPU_texture_cube_create(int w,
if (GPU_texture_stencil(tex) || /* Does not support filtering */
GPU_texture_integer(tex) || /* Does not support filtering */
GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER;
}
else {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
-
- if (GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT;
}
-
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ /* Avoid issue with incomplete textures. */
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(tex->target, 0);
@@ -1142,13 +1124,13 @@ GPUTexture *GPU_texture_cube_create(int w,
GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat tex_format, const GLuint buffer)
{
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->format_flag = 0;
tex->target_base = tex->target = GL_TEXTURE_BUFFER;
tex->mipmaps = 0;
+ tex->number = -1;
GLenum internalformat = gpu_format_to_gl_internalformat(tex_format);
@@ -1195,11 +1177,15 @@ GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode)
{
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
tex->bindcode = bindcode;
- tex->number = -1;
tex->refcount = 1;
tex->target = textarget;
tex->target_base = textarget;
tex->samples = 0;
+ tex->sampler_state = GPU_SAMPLER_REPEAT | GPU_SAMPLER_ANISO;
+ if (GPU_get_mipmap()) {
+ tex->sampler_state |= (GPU_SAMPLER_MIPMAP | GPU_SAMPLER_FILTER);
+ }
+ tex->number = -1;
if (!glIsTexture(tex->bindcode)) {
GPU_print_error_debug("Blender Texture Not Loaded");
@@ -1570,25 +1556,117 @@ void *GPU_texture_read(GPUTexture *tex, eGPUDataFormat gpu_data_format, int mipl
void GPU_texture_clear(GPUTexture *tex, eGPUDataFormat gpu_data_format, const void *color)
{
- if (GLEW_ARB_clear_texture) {
- GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag);
+ BLI_assert(color != NULL); /* Do not accept NULL as parameter. */
+ gpu_validate_data_format(tex->format, gpu_data_format);
+
+ if (false && GLEW_ARB_clear_texture) {
GLenum data_type = gpu_get_gl_datatype(gpu_data_format);
+ GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag);
glClearTexImage(tex->bindcode, 0, data_format, data_type, color);
+
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) {
+ /* TODO(clem) implement in fallback. */
+ BLI_assert(0);
+ }
+ else if (GPU_texture_depth(tex)) {
+ switch (gpu_data_format) {
+ case GPU_DATA_FLOAT:
+ case GPU_DATA_UNSIGNED_INT:
+ break;
+ default:
+ /* TODO(clem) implement in fallback. */
+ BLI_assert(0);
+ break;
+ }
+ }
+ else {
+ switch (gpu_data_format) {
+ case GPU_DATA_FLOAT:
+ case GPU_DATA_UNSIGNED_INT:
+ case GPU_DATA_UNSIGNED_BYTE:
+ break;
+ default:
+ /* TODO(clem) implement in fallback. */
+ BLI_assert(0);
+ break;
+ }
+ }
}
else {
- size_t buffer_len = gpu_texture_memory_footprint_compute(tex);
- unsigned char *pixels = MEM_mallocN(buffer_len, __func__);
- if (color) {
- const size_t bytesize = (size_t)gpu_get_bytesize(tex->format);
- for (size_t byte = 0; byte < buffer_len; byte += bytesize) {
- memcpy(&pixels[byte], color, bytesize);
+ /* Fallback for older GL. */
+ GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
+
+ gpu_texture_framebuffer_ensure(tex);
+ /* This means that this function can only be used in one context for each texture. */
+ BLI_assert(tex->copy_fb_ctx == GPU_context_active_get());
+
+ glBindFramebuffer(GL_FRAMEBUFFER, tex->copy_fb);
+ glViewport(0, 0, tex->w, tex->h);
+
+ /* Watch: Write mask could prevent the clear.
+ * glClearTexImage does not change the state so we don't do it here either. */
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) {
+ /* TODO(clem) implement. */
+ BLI_assert(0);
+ }
+ else if (GPU_texture_depth(tex)) {
+ float depth;
+ switch (gpu_data_format) {
+ case GPU_DATA_FLOAT: {
+ depth = *(float *)color;
+ break;
+ }
+ case GPU_DATA_UNSIGNED_INT: {
+ depth = *(uint *)color / (float)UINT_MAX;
+ break;
+ }
+ default:
+ BLI_assert(!"Unhandled data format");
+ depth = 0.0f;
+ break;
}
+ glClearDepth(depth);
+ glClear(GL_DEPTH_BUFFER_BIT);
}
else {
- memset(pixels, 0, buffer_len);
+ float r, g, b, a;
+ switch (gpu_data_format) {
+ case GPU_DATA_FLOAT: {
+ float *f_color = (float *)color;
+ r = f_color[0];
+ g = (tex->components > 1) ? f_color[1] : 0.0f;
+ b = (tex->components > 2) ? f_color[2] : 0.0f;
+ a = (tex->components > 3) ? f_color[3] : 0.0f;
+ break;
+ }
+ case GPU_DATA_UNSIGNED_INT: {
+ uint *u_color = (uint *)color;
+ r = u_color[0] / (float)UINT_MAX;
+ g = (tex->components > 1) ? u_color[1] / (float)UINT_MAX : 0.0f;
+ b = (tex->components > 2) ? u_color[2] / (float)UINT_MAX : 0.0f;
+ a = (tex->components > 3) ? u_color[3] / (float)UINT_MAX : 0.0f;
+ break;
+ }
+ case GPU_DATA_UNSIGNED_BYTE: {
+ uchar *ub_color = (uchar *)color;
+ r = ub_color[0] / 255.0f;
+ g = (tex->components > 1) ? ub_color[1] / 255.0f : 0.0f;
+ b = (tex->components > 2) ? ub_color[2] / 255.0f : 0.0f;
+ a = (tex->components > 3) ? ub_color[3] / 255.0f : 0.0f;
+ break;
+ }
+ default:
+ BLI_assert(!"Unhandled data format");
+ r = g = b = a = 0.0f;
+ break;
+ }
+ glClearColor(r, g, b, a);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ if (prev_fb) {
+ GPU_framebuffer_bind(prev_fb);
}
- GPU_texture_update(tex, gpu_data_format, pixels);
- MEM_freeN(pixels);
}
}
@@ -1634,16 +1712,17 @@ void GPU_invalid_tex_free(void)
}
}
-void GPU_texture_bind(GPUTexture *tex, int number)
+/* set_number is to save the the texture unit for setting texture parameters. */
+void GPU_texture_bind_ex(GPUTexture *tex, eGPUSamplerState state, int unit, const bool set_number)
{
- BLI_assert(number >= 0);
+ BLI_assert(unit >= 0);
- if (number >= GPU_max_textures()) {
+ if (unit >= GPU_max_textures()) {
fprintf(stderr, "Not enough texture slots.\n");
return;
}
- if ((G.debug & G_DEBUG)) {
+ if (G.debug & G_DEBUG) {
for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; i++) {
if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) {
fprintf(stderr,
@@ -1655,16 +1734,27 @@ void GPU_texture_bind(GPUTexture *tex, int number)
}
}
- glActiveTexture(GL_TEXTURE0 + number);
+ if (set_number) {
+ tex->number = unit;
+ }
+
+ glActiveTexture(GL_TEXTURE0 + unit);
+
+ state = (state < GPU_SAMPLER_MAX) ? state : tex->sampler_state;
if (tex->bindcode != 0) {
glBindTexture(tex->target, tex->bindcode);
+ glBindSampler(unit, GG.samplers[state]);
}
else {
GPU_invalid_tex_bind(tex->target_base);
+ glBindSampler(unit, 0);
}
+}
- tex->number = number;
+void GPU_texture_bind(GPUTexture *tex, int unit)
+{
+ GPU_texture_bind_ex(tex, GPU_SAMPLER_MAX, unit, true);
}
void GPU_texture_unbind(GPUTexture *tex)
@@ -1675,13 +1765,34 @@ void GPU_texture_unbind(GPUTexture *tex)
glActiveTexture(GL_TEXTURE0 + tex->number);
glBindTexture(tex->target, 0);
-
+ glBindSampler(tex->number, 0);
tex->number = -1;
}
-int GPU_texture_bound_number(GPUTexture *tex)
+void GPU_texture_unbind_all(void)
{
- return tex->number;
+ if (GLEW_ARB_multi_bind) {
+ glBindTextures(0, GPU_max_textures(), NULL);
+ glBindSamplers(0, GPU_max_textures(), NULL);
+ return;
+ }
+
+ for (int i = 0; i < GPU_max_textures(); i++) {
+ glActiveTexture(GL_TEXTURE0 + i);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
+ glBindTexture(GL_TEXTURE_1D, 0);
+ glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
+ glBindTexture(GL_TEXTURE_3D, 0);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+ glBindTexture(GL_TEXTURE_BUFFER, 0);
+ if (GPU_arb_texture_cube_map_array_is_supported()) {
+ glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY_ARB, 0);
+ }
+ glBindSampler(i, 0);
+ }
+
+ glActiveTexture(GL_TEXTURE0);
}
#define WARN_NOT_BOUND(_tex) \
@@ -1705,8 +1816,8 @@ void GPU_texture_generate_mipmap(GPUTexture *tex)
if (GPU_texture_depth(tex)) {
/* Some drivers have bugs when using glGenerateMipmap with depth textures (see T56789).
- * In this case we just create a complete texture with mipmaps manually without down-sampling.
- * You must initialize the texture levels using other methods like
+ * In this case we just create a complete texture with mipmaps manually without
+ * down-sampling. You must initialize the texture levels using other methods like
* GPU_framebuffer_recursive_downsample(). */
eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex->format);
for (int i = 1; i < levels; i++) {
@@ -1812,69 +1923,35 @@ void GPU_texture_copy(GPUTexture *dst, GPUTexture *src)
void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
{
- WARN_NOT_BOUND(tex);
-
/* Could become an assertion ? (fclem) */
if (!GPU_texture_depth(tex)) {
return;
}
-
- GLenum mode = (use_compare) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, mode);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_compare, GPU_SAMPLER_COMPARE);
}
void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter)
{
- WARN_NOT_BOUND(tex);
-
/* Stencil and integer format does not support filtering. */
BLI_assert(!use_filter || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
}
void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter)
{
- WARN_NOT_BOUND(tex);
-
/* Stencil and integer format does not support filtering. */
- BLI_assert((!use_filter && !use_mipmap) ||
+ BLI_assert(!(use_filter || use_mipmap) ||
!(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
- GLenum mipmap = ((use_filter) ? (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR :
- (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST);
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_mipmap, GPU_SAMPLER_MIPMAP);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
}
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp)
{
- WARN_NOT_BOUND(tex);
-
- GLenum repeat = (use_repeat) ? GL_REPEAT : (use_clamp) ? GL_CLAMP_TO_EDGE : GL_CLAMP_TO_BORDER;
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat);
- if (tex->target_base != GL_TEXTURE_1D) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat);
- }
- if (tex->target_base == GL_TEXTURE_3D) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat);
- }
-
- if (repeat == GL_CLAMP_TO_BORDER) {
- const float black[] = {0.0f, 0.0f, 0.0f, 0.0f};
- glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, black);
- }
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_repeat, GPU_SAMPLER_REPEAT);
+ SET_FLAG_FROM_TEST(tex->sampler_state, !use_clamp, GPU_SAMPLER_CLAMP_BORDER);
}
void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels)
@@ -1888,34 +1965,6 @@ void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, (channels >= 4) ? GL_ALPHA : GL_ONE);
}
-static GLenum gpu_get_gl_filterfunction(eGPUFilterFunction filter)
-{
- switch (filter) {
- case GPU_NEAREST:
- return GL_NEAREST;
- case GPU_LINEAR:
- return GL_LINEAR;
- default:
- BLI_assert(!"Unhandled filter mode");
- return GL_NEAREST;
- }
-}
-
-void GPU_texture_filters(GPUTexture *tex,
- eGPUFilterFunction min_filter,
- eGPUFilterFunction mag_filter)
-{
- WARN_NOT_BOUND(tex);
-
- /* Stencil and integer format does not support filtering. */
- BLI_assert(!(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- BLI_assert(mag_filter == GPU_NEAREST || mag_filter == GPU_LINEAR);
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, gpu_get_gl_filterfunction(min_filter));
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter));
-}
-
void GPU_texture_free(GPUTexture *tex)
{
tex->refcount--;
@@ -2076,3 +2125,55 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size)
size[2] = max_ii(1, tex->d / div);
}
}
+
+/* -------------------------------------------------------------------- */
+/** \name GPU Sampler Objects
+ *
+ * Simple wrapper around opengl sampler objects.
+ * Override texture sampler state for one sampler unit only.
+ * \{ */
+
+void GPU_samplers_init(void)
+{
+ glGenSamplers(GPU_SAMPLER_MAX, GG.samplers);
+ for (int i = 0; i < GPU_SAMPLER_MAX; i++) {
+ eGPUSamplerState state = i;
+ GLenum clamp_type = (state & GPU_SAMPLER_CLAMP_BORDER) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE;
+ GLenum wrap_s = (state & GPU_SAMPLER_REPEAT_S) ? GL_REPEAT : clamp_type;
+ GLenum wrap_t = (state & GPU_SAMPLER_REPEAT_T) ? GL_REPEAT : clamp_type;
+ GLenum wrap_r = (state & GPU_SAMPLER_REPEAT_R) ? GL_REPEAT : clamp_type;
+ GLenum mag_filter = (state & GPU_SAMPLER_FILTER) ? GL_LINEAR : GL_NEAREST;
+ GLenum min_filter = (state & GPU_SAMPLER_FILTER) ?
+ ((state & GPU_SAMPLER_MIPMAP) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) :
+ ((state & GPU_SAMPLER_MIPMAP) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST);
+ GLenum compare_mode = (state & GPU_SAMPLER_COMPARE) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
+ float aniso_filter = ((state & GPU_SAMPLER_MIPMAP) && (state & GPU_SAMPLER_ANISO)) ?
+ GPU_get_anisotropic() :
+ 1.0f;
+
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_S, wrap_s);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_T, wrap_t);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_R, wrap_r);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_MIN_FILTER, min_filter);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_MAG_FILTER, mag_filter);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_COMPARE_MODE, compare_mode);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ if (GLEW_EXT_texture_filter_anisotropic) {
+ glSamplerParameterf(GG.samplers[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso_filter);
+ }
+
+ /** Other states are left to default:
+ * - GL_TEXTURE_BORDER_COLOR is {0, 0, 0, 0}.
+ * - GL_TEXTURE_MIN_LOD is -1000.
+ * - GL_TEXTURE_MAX_LOD is 1000.
+ * - GL_TEXTURE_LOD_BIAS is 0.0f.
+ **/
+ }
+}
+
+void GPU_samplers_free(void)
+{
+ glDeleteSamplers(GPU_SAMPLER_MAX, GG.samplers);
+}
+
+/** \} */
diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c
index e6a9cb8f2f2..b84a7e0f554 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.c
+++ b/source/blender/gpu/intern/gpu_vertex_format.c
@@ -23,8 +23,6 @@
* GPU vertex format
*/
-#include "GPU_shader_interface.h"
-
#include "GPU_vertex_format.h"
#include "gpu_vertex_format_private.h"
#include <stddef.h>
@@ -34,6 +32,9 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "GPU_shader.h"
+#include "gpu_shader_private.h"
+
#define PACK_DEBUG 0
#if PACK_DEBUG
@@ -391,38 +392,37 @@ void VertexFormat_pack(GPUVertFormat *format)
format->packed = true;
}
-static uint calc_input_component_size(const GPUShaderInput *input)
+static uint calc_component_size(const GLenum gl_type)
{
- int size = input->size;
- switch (input->gl_type) {
+ switch (gl_type) {
case GL_FLOAT_VEC2:
case GL_INT_VEC2:
case GL_UNSIGNED_INT_VEC2:
- return size * 2;
+ return 2;
case GL_FLOAT_VEC3:
case GL_INT_VEC3:
case GL_UNSIGNED_INT_VEC3:
- return size * 3;
+ return 3;
case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2:
case GL_INT_VEC4:
case GL_UNSIGNED_INT_VEC4:
- return size * 4;
+ return 4;
case GL_FLOAT_MAT3:
- return size * 9;
+ return 9;
case GL_FLOAT_MAT4:
- return size * 16;
+ return 16;
case GL_FLOAT_MAT2x3:
case GL_FLOAT_MAT3x2:
- return size * 6;
+ return 6;
case GL_FLOAT_MAT2x4:
case GL_FLOAT_MAT4x2:
- return size * 8;
+ return 8;
case GL_FLOAT_MAT3x4:
case GL_FLOAT_MAT4x3:
- return size * 12;
+ return 12;
default:
- return size;
+ return 1;
}
}
@@ -466,42 +466,39 @@ static void get_fetch_mode_and_comp_type(int gl_type,
}
}
-void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterface *shaderface)
+void GPU_vertformat_from_shader(GPUVertFormat *format, const GPUShader *shader)
{
- const char *name_buffer = shaderface->name_buffer;
-
- for (int i = 0; i < GPU_NUM_SHADERINTERFACE_BUCKETS; i++) {
- const GPUShaderInput *input = shaderface->attr_buckets[i];
- if (input == NULL) {
- continue;
- }
+ GPU_vertformat_clear(format);
+ GPUVertAttr *attr = &format->attrs[0];
- const GPUShaderInput *next = input;
- while (next != NULL) {
- input = next;
- next = input->next;
+ GLint attr_len;
+ glGetProgramiv(shader->program, GL_ACTIVE_ATTRIBUTES, &attr_len);
- /* OpenGL attributes such as `gl_VertexID` have a location of -1. */
- if (input->location < 0) {
- continue;
- }
-
- format->name_len++; /* multiname support */
- format->attr_len++;
-
- GPUVertCompType comp_type;
- GPUVertFetchMode fetch_mode;
- get_fetch_mode_and_comp_type(input->gl_type, &comp_type, &fetch_mode);
+ for (int i = 0; i < attr_len; i++) {
+ char name[256];
+ GLenum gl_type;
+ GLint size;
+ glGetActiveAttrib(shader->program, i, sizeof(name), NULL, &size, &gl_type, name);
- GPUVertAttr *attr = &format->attrs[input->location];
-
- attr->names[attr->name_len++] = copy_attr_name(format, name_buffer + input->name_offset);
- attr->offset = 0; /* offsets & stride are calculated later (during pack) */
- attr->comp_len = calc_input_component_size(input);
- attr->sz = attr->comp_len * 4;
- attr->fetch_mode = fetch_mode;
- attr->comp_type = comp_type;
- attr->gl_comp_type = convert_comp_type_to_gl(comp_type);
+ /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */
+ if (glGetAttribLocation(shader->program, name) == -1) {
+ continue;
}
+
+ format->name_len++; /* multiname support */
+ format->attr_len++;
+
+ GPUVertCompType comp_type;
+ GPUVertFetchMode fetch_mode;
+ get_fetch_mode_and_comp_type(gl_type, &comp_type, &fetch_mode);
+
+ attr->names[attr->name_len++] = copy_attr_name(format, name);
+ attr->offset = 0; /* offsets & stride are calculated later (during pack) */
+ attr->comp_len = calc_component_size(gl_type) * size;
+ attr->sz = attr->comp_len * 4;
+ attr->fetch_mode = fetch_mode;
+ attr->comp_type = comp_type;
+ attr->gl_comp_type = convert_comp_type_to_gl(comp_type);
+ attr += 1;
}
}
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index f30270b9eed..753da8544ea 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -382,12 +382,10 @@ GPUTexture *GPU_viewport_texture_pool_query(
}
tex = GPU_texture_create_2d(width, height, format, NULL, NULL);
- GPU_texture_bind(tex, 0);
/* Doing filtering for depth does not make sense when not doing shadow mapping,
* and enabling texture filtering on integer texture make them unreadable. */
bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex);
GPU_texture_filter_mode(tex, do_filter);
- GPU_texture_unbind(tex);
ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture");
tmp_tex->texture = tex;
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl
index 62f76d46088..4cb00c15b78 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl
@@ -1,8 +1,16 @@
-void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result)
+void node_output_material(
+ Closure surface, Closure volume, vec3 displacement, float alpha_threshold, out Closure result)
{
#ifdef VOLUMETRICS
result = volume;
#else
result = surface;
+# if defined(USE_ALPHA_HASH)
+ /* Alpha clip emulation. */
+ if (alpha_threshold >= 0.0) {
+ float alpha = saturate(1.0 - avg(result.transmittance));
+ result.transmittance = vec3(step(alpha, alpha_threshold));
+ }
+# endif
#endif
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
index 9bd36f8a757..20a65f23c05 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
@@ -15,16 +15,11 @@ void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec)
#endif
}
-void node_tex_environment_equirectangular(vec3 co, float clamp_size, sampler2D ima, out vec3 uv)
+void node_tex_environment_equirectangular(vec3 co, out vec3 uv)
{
vec3 nco = normalize(co);
uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5;
uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5;
-
- /* Fix pole bleeding */
- float half_height = clamp_size / float(textureSize(ima, 0).y);
- uv.y = clamp(uv.y, half_height, 1.0 - half_height);
- uv.z = 0.0;
}
void node_tex_environment_mirror_ball(vec3 co, out vec3 uv)
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
index c39bec8ac64..df949f7358b 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
@@ -54,19 +54,6 @@ void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alp
alpha = color.a;
}
-void node_tex_image_linear_no_mip(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- color = safe_color(textureLod(ima, co.xy, 0.0));
- alpha = color.a;
-}
-
-void node_tex_image_nearest(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- ivec2 pix = ivec2(fract(co.xy) * textureSize(ima, 0).xy);
- color = safe_color(texelFetch(ima, pix, 0));
- alpha = color.a;
-}
-
/** \param f: Signed distance to texel center. */
void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3)
{
@@ -79,8 +66,7 @@ void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2
w2 = 1.0 - w0 - w1 - w3;
}
-void node_tex_image_cubic_ex(
- vec3 co, sampler2D ima, float do_extend, out vec4 color, out float alpha)
+void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha)
{
vec2 tex_size = vec2(textureSize(ima, 0).xy);
@@ -101,9 +87,6 @@ void node_tex_image_cubic_ex(
final_co.xy = tc - 1.0 + f0;
final_co.zw = tc + 1.0 + f1;
- if (do_extend == 1.0) {
- final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5);
- }
final_co /= tex_size.xyxy;
color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y;
@@ -136,22 +119,6 @@ void node_tex_image_cubic_ex(
alpha = color.a;
}
-void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- node_tex_image_cubic_ex(co, ima, 0.0, color, alpha);
-}
-
-void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- node_tex_image_cubic_ex(co, ima, 1.0, color, alpha);
-}
-
-void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- /* use cubic for now */
- node_tex_image_cubic_ex(co, ima, 0.0, color, alpha);
-}
-
void tex_box_sample_linear(
vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
{
@@ -175,32 +142,6 @@ void tex_box_sample_linear(
color3 = texture(ima, uv);
}
-void tex_box_sample_nearest(
- vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
-{
- /* X projection */
- vec2 uv = texco.yz;
- if (N.x < 0.0) {
- uv.x = 1.0 - uv.x;
- }
- ivec2 pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy);
- color1 = texelFetch(ima, pix, 0);
- /* Y projection */
- uv = texco.xz;
- if (N.y > 0.0) {
- uv.x = 1.0 - uv.x;
- }
- pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy);
- color2 = texelFetch(ima, pix, 0);
- /* Z projection */
- uv = texco.yx;
- if (N.z > 0.0) {
- uv.x = 1.0 - uv.x;
- }
- pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy);
- color3 = texelFetch(ima, pix, 0);
-}
-
void tex_box_sample_cubic(
vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
{
@@ -210,36 +151,23 @@ void tex_box_sample_cubic(
if (N.x < 0.0) {
uv.x = 1.0 - uv.x;
}
- node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color1, alpha);
+ node_tex_image_cubic(uv.xyy, ima, color1, alpha);
/* Y projection */
uv = texco.xz;
if (N.y > 0.0) {
uv.x = 1.0 - uv.x;
}
- node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha);
+ node_tex_image_cubic(uv.xyy, ima, color2, alpha);
/* Z projection */
uv = texco.yx;
if (N.z > 0.0) {
uv.x = 1.0 - uv.x;
}
- node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color3, alpha);
+ node_tex_image_cubic(uv.xyy, ima, color3, alpha);
}
-void tex_box_sample_smart(
- vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
-{
- tex_box_sample_cubic(texco, N, ima, color1, color2, color3);
-}
-
-void node_tex_image_box(vec3 texco,
- vec3 N,
- vec4 color1,
- vec4 color2,
- vec4 color3,
- sampler2D ima,
- float blend,
- out vec4 color,
- out float alpha)
+void tex_box_blend(
+ vec3 N, vec4 color1, vec4 color2, vec4 color3, float blend, out vec4 color, out float alpha)
{
/* project from direction vector to barycentric coordinates in triangles */
N = abs(N);
@@ -284,70 +212,6 @@ void node_tex_image_box(vec3 texco,
alpha = color.a;
}
-void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- vec2 tex_size = vec2(textureSize(ima, 0).xy);
- vec2 minco = min(co.xy, 1.0 - co.xy);
- minco = clamp(minco * tex_size + 0.5, 0.0, 1.0);
- float fac = minco.x * minco.y;
-
- color = mix(vec4(0.0), icolor, fac);
- alpha = color.a;
-}
-
-void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- vec4 minco = vec4(co.xy, 1.0 - co.xy);
- color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor;
- alpha = color.a;
-}
-
-void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- vec2 tex_size = vec2(textureSize(ima, 0).xy);
-
- co.xy *= tex_size;
- /* texel center */
- vec2 tc = floor(co.xy - 0.5) + 0.5;
- vec2 w0, w1, w2, w3;
- cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3);
-
- /* TODO Optimize this part. I'm sure there is a smarter way to do that.
- * Could do that when sampling? */
-#define CLIP_CUBIC_SAMPLE(samp, size) \
- (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size))))
- ivec2 itex_size = textureSize(ima, 0).xy;
- float fac;
- fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, -1.0), itex_size) * w1.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, -1.0), itex_size) * w2.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, -1.0), itex_size) * w3.x * w0.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 0.0), itex_size) * w1.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 0.0), itex_size) * w2.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 0.0), itex_size) * w3.x * w1.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 1.0), itex_size) * w1.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 1.0), itex_size) * w2.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 1.0), itex_size) * w3.x * w2.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 2.0), itex_size) * w1.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 2.0), itex_size) * w2.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 2.0), itex_size) * w3.x * w3.y;
-#undef CLIP_CUBIC_SAMPLE
-
- color = mix(vec4(0.0), icolor, fac);
- alpha = color.a;
-}
-
-void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- tex_clip_cubic(co, ima, icolor, color, alpha);
-}
-
void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
{
color = vec4(0.0);
@@ -389,20 +253,6 @@ void node_tex_tile_linear(
alpha = color.a;
}
-void node_tex_tile_nearest(
- vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha)
-{
- if (node_tex_tile_lookup(co, ima, map)) {
- ivec3 pix = ivec3(fract(co.xy) * textureSize(ima, 0).xy, co.z);
- color = safe_color(texelFetch(ima, pix, 0));
- }
- else {
- color = vec4(1.0, 0.0, 1.0, 1.0);
- }
-
- alpha = color.a;
-}
-
void node_tex_tile_cubic(
vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha)
{
@@ -437,9 +287,3 @@ void node_tex_tile_cubic(
alpha = color.a;
}
-
-void node_tex_tile_smart(
- vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha)
-{
- node_tex_tile_cubic(co, ima, map, color, alpha);
-}
diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc
index 40a057f9a20..62f6a52f7cf 100644
--- a/source/blender/io/alembic/intern/abc_customdata.cc
+++ b/source/blender/io/alembic/intern/abc_customdata.cc
@@ -144,7 +144,7 @@ const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, Custom
* - (optional due to its behavior) tag as UV using Alembic::AbcGeom::SetIsUV
*/
static void write_uv(const OCompoundProperty &prop,
- const CDStreamConfig &config,
+ CDStreamConfig &config,
void *data,
const char *name)
{
@@ -157,13 +157,18 @@ static void write_uv(const OCompoundProperty &prop,
return;
}
- OV2fGeomParam param(prop, name, true, kFacevaryingScope, 1);
+ std::string uv_map_name(name);
+ OV2fGeomParam param = config.abc_uv_maps[uv_map_name];
+ if (!param.valid()) {
+ param = OV2fGeomParam(prop, name, true, kFacevaryingScope, 1);
+ }
OV2fGeomParam::Sample sample(V2fArraySample(&uvs.front(), uvs.size()),
UInt32ArraySample(&indices.front(), indices.size()),
kFacevaryingScope);
-
param.set(sample);
+
+ config.abc_uv_maps[uv_map_name] = param;
}
/* Convention to write Vertex Colors:
@@ -217,7 +222,7 @@ static void write_mcol(const OCompoundProperty &prop,
}
void write_custom_data(const OCompoundProperty &prop,
- const CDStreamConfig &config,
+ CDStreamConfig &config,
CustomData *data,
int data_type)
{
diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h
index 04572c736af..96b57b08681 100644
--- a/source/blender/io/alembic/intern/abc_customdata.h
+++ b/source/blender/io/alembic/intern/abc_customdata.h
@@ -27,6 +27,8 @@
#include <Alembic/Abc/All.h>
#include <Alembic/AbcGeom/All.h>
+#include <map>
+
struct CustomData;
struct MLoop;
struct MLoopUV;
@@ -70,6 +72,12 @@ struct CDStreamConfig {
const char **modifier_error_message;
+ /* Alembic needs Blender to keep references to C++ objects (the destructors
+ * finalize the writing to ABC). This map stores OV2fGeomParam objects for the
+ * 2nd and subsequent UV maps; the primary UV map is kept alive by the Alembic
+ * mesh sample itself. */
+ std::map<std::string, Alembic::AbcGeom::OV2fGeomParam> abc_uv_maps;
+
CDStreamConfig()
: mloop(NULL),
totloop(0),
@@ -95,7 +103,7 @@ struct CDStreamConfig {
const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data);
void write_custom_data(const OCompoundProperty &prop,
- const CDStreamConfig &config,
+ CDStreamConfig &config,
CustomData *data,
int data_type);
diff --git a/source/blender/io/alembic/intern/abc_writer_archive.cc b/source/blender/io/alembic/intern/abc_writer_archive.cc
index 5aae1f05f4b..e7dee536cb9 100644
--- a/source/blender/io/alembic/intern/abc_writer_archive.cc
+++ b/source/blender/io/alembic/intern/abc_writer_archive.cc
@@ -52,7 +52,7 @@ static OArchive create_archive(std::ostream *ostream,
abc_metadata.set(Alembic::Abc::kApplicationNameKey, "Blender");
abc_metadata.set(Alembic::Abc::kUserDescriptionKey, scene_name);
- abc_metadata.set("blender_version", versionstr);
+ abc_metadata.set("blender_version", std::string("v") + BKE_blender_version_string());
abc_metadata.set("FramesPerTimeUnit", std::to_string(scene_fps));
time_t raw_time;
diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc
index 987a3cacb3b..6ca9e82a26c 100644
--- a/source/blender/io/alembic/intern/alembic_capi.cc
+++ b/source/blender/io/alembic/intern/alembic_capi.cc
@@ -875,8 +875,7 @@ bool ABC_import(bContext *C,
bool validate_meshes,
bool as_background_job)
{
- /* Using new here since MEM_* funcs do not call ctor to properly initialize
- * data. */
+ /* Using new here since MEM_* functions do not call constructor to properly initialize data. */
ImportJobData *job = new ImportJobData();
job->bmain = CTX_data_main(C);
job->scene = CTX_data_scene(C);
diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp
index 2511d3c287d..edac84e2aaa 100644
--- a/source/blender/io/collada/AnimationImporter.cpp
+++ b/source/blender/io/collada/AnimationImporter.cpp
@@ -57,7 +57,7 @@ template<class T> static const char *bc_get_joint_name(T *node)
FCurve *AnimationImporter::create_fcurve(int array_index, const char *rna_path)
{
- FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve");
+ FCurve *fcu = BKE_fcurve_create();
fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
fcu->array_index = array_index;
@@ -100,7 +100,7 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
case 16: /* matrix */
{
for (i = 0; i < dim; i++) {
- FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve");
+ FCurve *fcu = BKE_fcurve_create();
fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
fcu->array_index = 0;
@@ -274,7 +274,7 @@ AnimationImporter::~AnimationImporter()
/* free unused FCurves */
for (std::vector<FCurve *>::iterator it = unused_curves.begin(); it != unused_curves.end();
it++) {
- free_fcurve(*it);
+ BKE_fcurve_free(*it);
}
if (unused_curves.size()) {
@@ -442,7 +442,7 @@ virtual void AnimationImporter::change_eul_to_quat(Object *ob, bAction *act)
}
action_groups_remove_channel(act, eulcu[i]);
- free_fcurve(eulcu[i]);
+ BKE_fcurve_free(eulcu[i]);
}
chan->rotmode = ROT_MODE_QUAT;
diff --git a/source/blender/io/collada/BCAnimationCurve.cpp b/source/blender/io/collada/BCAnimationCurve.cpp
index 98eb12f738e..61dded368b5 100644
--- a/source/blender/io/collada/BCAnimationCurve.cpp
+++ b/source/blender/io/collada/BCAnimationCurve.cpp
@@ -89,12 +89,12 @@ void BCAnimationCurve::init_pointer_rna(Object *ob)
void BCAnimationCurve::delete_fcurve(FCurve *fcu)
{
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
}
FCurve *BCAnimationCurve::create_fcurve(int array_index, const char *rna_path)
{
- FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve");
+ FCurve *fcu = BKE_fcurve_create();
fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
fcu->array_index = array_index;
diff --git a/source/blender/io/collada/BCAnimationSampler.cpp b/source/blender/io/collada/BCAnimationSampler.cpp
index fc23a58ccbc..4aea74cd82f 100644
--- a/source/blender/io/collada/BCAnimationSampler.cpp
+++ b/source/blender/io/collada/BCAnimationSampler.cpp
@@ -271,7 +271,7 @@ void BCAnimationSampler::find_depending_animated(std::set<Object *> &animated_ob
std::set<Object *>::iterator it;
for (it = candidates.begin(); it != candidates.end(); ++it) {
Object *cob = *it;
- ListBase *conlist = get_active_constraints(cob);
+ ListBase *conlist = ED_object_constraint_list_from_context(cob);
if (is_animated_by_constraint(cob, conlist, animated_objects)) {
animated_objects.insert(cob);
candidates.erase(cob);
diff --git a/source/blender/io/collada/DocumentExporter.cpp b/source/blender/io/collada/DocumentExporter.cpp
index b890d4cf018..0578bf45f04 100644
--- a/source/blender/io/collada/DocumentExporter.cpp
+++ b/source/blender/io/collada/DocumentExporter.cpp
@@ -243,20 +243,13 @@ int DocumentExporter::exportCurrentScene()
#ifdef WITH_BUILDINFO
BLI_snprintf(version_buf,
sizeof(version_buf),
- "Blender %d.%02d.%d commit date:%s, commit time:%s, hash:%s",
- BLENDER_VERSION / 100,
- BLENDER_VERSION % 100,
- BLENDER_SUBVERSION,
+ "Blender %s commit date:%s, commit time:%s, hash:%s",
+ BKE_blender_version_string(),
build_commit_date,
build_commit_time,
build_hash);
#else
- BLI_snprintf(version_buf,
- sizeof(version_buf),
- "Blender %d.%02d.%d",
- BLENDER_VERSION / 100,
- BLENDER_VERSION % 100,
- BLENDER_SUBVERSION);
+ BLI_snprintf(version_buf, sizeof(version_buf), "Blender %s", BKE_blender_version_string());
#endif
asset.getContributor().mAuthoringTool = version_buf;
asset.add();
diff --git a/source/blender/io/collada/ErrorHandler.h b/source/blender/io/collada/ErrorHandler.h
index 9789e93cee9..0c082a3b9dd 100644
--- a/source/blender/io/collada/ErrorHandler.h
+++ b/source/blender/io/collada/ErrorHandler.h
@@ -46,7 +46,7 @@ class ErrorHandler : public COLLADASaxFWL::IErrorHandler {
}
private:
- /** Disable default copy ctor. */
+ /** Disable default copy constructor. */
ErrorHandler(const ErrorHandler &pre);
/** Disable default assignment operator. */
const ErrorHandler &operator=(const ErrorHandler &pre);
diff --git a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc b/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc
index e382fa6bb1d..ab83ea2c3c4 100644
--- a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc
+++ b/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc
@@ -53,7 +53,7 @@ bool HierarchyContext::operator<(const HierarchyContext &other) const
if (object != other.object) {
return object < other.object;
}
- if (duplicator != NULL && duplicator == other.duplicator) {
+ if (duplicator != nullptr && duplicator == other.duplicator) {
// Only resort to string comparisons when both objects are created by the same duplicator.
return export_name < other.export_name;
}
diff --git a/source/blender/io/usd/intern/usd_capi.cc b/source/blender/io/usd/intern/usd_capi.cc
index f8e0a03abfa..cf962446d04 100644
--- a/source/blender/io/usd/intern/usd_capi.cc
+++ b/source/blender/io/usd/intern/usd_capi.cc
@@ -91,7 +91,8 @@ static void export_startjob(void *customdata, short *stop, short *do_update, flo
usd_stage->SetMetadata(pxr::UsdGeomTokens->upAxis, pxr::VtValue(pxr::UsdGeomTokens->z));
usd_stage->SetMetadata(pxr::UsdGeomTokens->metersPerUnit,
pxr::VtValue(scene->unit.scale_length));
- usd_stage->GetRootLayer()->SetDocumentation(std::string("Blender ") + versionstr);
+ usd_stage->GetRootLayer()->SetDocumentation(std::string("Blender v") +
+ BKE_blender_version_string());
// Set up the stage for animated data.
if (data->params.export_animation) {
@@ -185,7 +186,7 @@ bool USD_export(bContext *C,
/* setup job */
WM_jobs_customdata_set(wm_job, job, MEM_freeN);
WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME);
- WM_jobs_callbacks(wm_job, USD::export_startjob, NULL, NULL, USD::export_endjob);
+ WM_jobs_callbacks(wm_job, USD::export_startjob, nullptr, nullptr, USD::export_endjob);
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc
index 909869d2af1..841501bcf42 100644
--- a/source/blender/io/usd/intern/usd_writer_mesh.cc
+++ b/source/blender/io/usd/intern/usd_writer_mesh.cc
@@ -79,7 +79,7 @@ void USDGenericMeshWriter::do_write(HierarchyContext &context)
bool needsfree = false;
Mesh *mesh = get_export_mesh(object_eval, needsfree);
- if (mesh == NULL) {
+ if (mesh == nullptr) {
return;
}
@@ -100,7 +100,7 @@ void USDGenericMeshWriter::do_write(HierarchyContext &context)
void USDGenericMeshWriter::free_export_mesh(Mesh *mesh)
{
- BKE_id_free(NULL, mesh);
+ BKE_id_free(nullptr, mesh);
}
struct USDMeshData {
diff --git a/source/blender/io/usd/intern/usd_writer_transform.cc b/source/blender/io/usd/intern/usd_writer_transform.cc
index 038f2b17b1a..0694d873002 100644
--- a/source/blender/io/usd/intern/usd_writer_transform.cc
+++ b/source/blender/io/usd/intern/usd_writer_transform.cc
@@ -50,7 +50,7 @@ void USDTransformWriter::do_write(HierarchyContext &context)
bool USDTransformWriter::check_is_animated(const HierarchyContext &context) const
{
- if (context.duplicator != NULL) {
+ if (context.duplicator != nullptr) {
/* This object is being duplicated, so could be emitted by a particle system and thus
* influenced by forces. TODO(Sybren): Make this more strict. Probably better to get from the
* depsgraph whether this object instance has a time source. */
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 39f22fb9555..4f2bbc4ee73 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -327,7 +327,7 @@ typedef struct Library {
/* Temp data needed by read/write code. */
int temp_index;
- /** See BLENDER_VERSION, BLENDER_SUBVERSION, needed for do_versions. */
+ /** See BLENDER_FILE_VERSION, BLENDER_FILE_SUBVERSION, needed for do_versions. */
short versionfile, subversionfile;
} Library;
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index c143c2a442a..be7c894b4e4 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -331,9 +331,15 @@ typedef enum eBrushClothForceFalloffType {
BRUSH_CLOTH_FORCE_FALLOFF_PLANE = 1,
} eBrushClothForceFalloffType;
+typedef enum eBrushPoseDeformType {
+ BRUSH_POSE_DEFORM_ROTATE_TWIST = 0,
+ BRUSH_POSE_DEFORM_SCALE_TRASLATE = 1,
+} eBrushPoseDeformType;
+
typedef enum eBrushPoseOriginType {
BRUSH_POSE_ORIGIN_TOPOLOGY = 0,
BRUSH_POSE_ORIGIN_FACE_SETS = 1,
+ BRUSH_POSE_ORIGIN_FACE_SETS_FK = 2,
} eBrushPoseOriginType;
/* Gpencilsettings.Vertex_mode */
@@ -478,7 +484,7 @@ typedef struct Brush {
char gpencil_sculpt_tool;
/** Active grease pencil weight tool. */
char gpencil_weight_tool;
- char _pad1[6];
+ char _pad1[2];
float autosmooth_factor;
@@ -510,6 +516,7 @@ typedef struct Brush {
float elastic_deform_volume_preservation;
/* pose */
+ int pose_deform_type;
float pose_offset;
int pose_smooth_iterations;
int pose_ik_segments;
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 6a081a7f5a7..b2902407a15 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -496,11 +496,11 @@ typedef enum eBezTriple_KeyframeType {
#define BEZT_ISSEL_ALL(bezt) \
(((bezt)->f2 & SELECT) && ((bezt)->f1 & SELECT) && ((bezt)->f3 & SELECT))
#define BEZT_ISSEL_ALL_HIDDENHANDLES(v3d, bezt) \
- ((((v3d) != NULL) && ((v3d)->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) ? \
+ ((((v3d) != NULL) && ((v3d)->overlay.handle_display == CURVE_HANDLE_NONE)) ? \
(bezt)->f2 & SELECT : \
BEZT_ISSEL_ALL(bezt))
#define BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt) \
- ((((v3d) != NULL) && ((v3d)->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) ? \
+ ((((v3d) != NULL) && ((v3d)->overlay.handle_display == CURVE_HANDLE_NONE)) ? \
(bezt)->f2 & SELECT : \
BEZT_ISSEL_ANY(bezt))
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index e99d7fd5609..ef3b2015758 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -76,7 +76,8 @@ typedef struct CustomData {
* MUST be >= CD_NUMTYPES, but we cant use a define here.
* Correct size is ensured in CustomData_update_typemap assert().
*/
- int typemap[47];
+ int typemap[48];
+ char _pad[4];
/** Number of layers, size of layers array. */
int totlayer, maxlayer;
/** In editmode, total size of all data layers. */
@@ -153,7 +154,9 @@ typedef enum CustomDataType {
CD_HAIRCURVE = 45,
CD_HAIRMAPPING = 46,
- CD_NUMTYPES = 47,
+ CD_PROP_COLOR = 47,
+
+ CD_NUMTYPES = 48,
} CustomDataType;
/* Bits for CustomDataMask */
@@ -202,6 +205,7 @@ typedef enum CustomDataType {
#define CD_MASK_TESSLOOPNORMAL (1LL << CD_TESSLOOPNORMAL)
#define CD_MASK_CUSTOMLOOPNORMAL (1LL << CD_CUSTOMLOOPNORMAL)
#define CD_MASK_SCULPT_FACE_SETS (1LL << CD_SCULPT_FACE_SETS)
+#define CD_MASK_PROP_COLOR (1LL << CD_PROP_COLOR)
/** Data types that may be defined for all mesh elements types. */
#define CD_MASK_GENERIC_DATA (CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR)
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index dc1a2b5ff1d..acc020ec710 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -33,6 +33,7 @@ extern "C" {
#endif
struct AnimData;
+struct BVHCache;
struct Ipo;
struct Key;
struct LinkNode;
@@ -99,8 +100,8 @@ typedef struct Mesh_Runtime {
struct MLoopTri_Store looptris;
- /** 'BVHCache', for 'BKE_bvhutil.c' */
- struct LinkNode *bvh_cache;
+ /** `BVHCache` defined in 'BKE_bvhutil.c' */
+ struct BVHCache *bvh_cache;
/** Non-manifold boundary data for Shrinkwrap Target Project. */
struct ShrinkwrapBoundaryData *shrinkwrap_data;
@@ -112,7 +113,20 @@ typedef struct Mesh_Runtime {
* In the future we may leave the mesh-data empty
* since its not needed if we can use edit-mesh data. */
char is_original;
- char _pad[6];
+
+ /** #eMeshWrapperType and others. */
+ char wrapper_type;
+ /**
+ * A type mask from wrapper_type,
+ * in case there are differences in finalizing logic between types.
+ */
+ char wrapper_type_finalize;
+
+ char _pad[4];
+
+ /** Needed in case we need to lazily initialize the mesh. */
+ CustomData_MeshMasks cd_mask_extra;
+
} Mesh_Runtime;
typedef struct Mesh {
@@ -228,6 +242,15 @@ typedef struct TFace {
/* **************** MESH ********************* */
+/** #Mesh_Runtime.wrapper_type */
+typedef enum eMeshWrapperType {
+ /** Use mesh data (#Mesh.mvert,#Mesh.medge, #Mesh.mloop, #Mesh.mpoly). */
+ ME_WRAPPER_TYPE_MDATA = 0,
+ /** Use edit-mesh data (#Mesh.#edit_mesh, #Mesh_Runtime.edit_data). */
+ ME_WRAPPER_TYPE_BMESH = 1,
+ /* ME_WRAPPER_TYPE_SUBD = 2, */ /* TODO */
+} eMeshWrapperType;
+
/* texflag */
enum {
ME_AUTOSPACE = 1,
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index f48024cd55a..04deecde43e 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -344,6 +344,10 @@ typedef struct MLoopCol {
unsigned char r, g, b, a;
} MLoopCol;
+typedef struct MPropCol {
+ float col[4];
+} MPropCol;
+
/** Multi-Resolution loop data. */
typedef struct MDisps {
/* Strange bug in SDNA: if disps pointer comes first, it fails to see totdisp */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 609d3782997..a2b96ac2772 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -1418,7 +1418,7 @@ typedef struct WeightVGEditModifierData {
/* WeightVGEdit flags. */
enum {
- /* (1 << 0) is free for future use! */
+ MOD_WVG_EDIT_WEIGHTS_NORMALIZE = (1 << 0),
MOD_WVG_INVERT_FALLOFF = (1 << 1),
MOD_WVG_EDIT_INVERT_VGROUP_MASK = (1 << 2),
/** Add vertices with higher weight than threshold to vgroup. */
@@ -1506,6 +1506,9 @@ enum {
/* WeightVGMix->flag */
enum {
MOD_WVG_MIX_INVERT_VGROUP_MASK = (1 << 0),
+ MOD_WVG_MIX_WEIGHTS_NORMALIZE = (1 << 1),
+ MOD_WVG_MIX_INVERT_VGROUP_A = (1 << 2),
+ MOD_WVG_MIX_INVERT_VGROUP_B = (1 << 3),
};
typedef struct WeightVGProximityModifierData {
@@ -1568,6 +1571,7 @@ enum {
MOD_WVG_PROXIMITY_GEOM_FACES = (1 << 2),
MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK = (1 << 3),
MOD_WVG_PROXIMITY_INVERT_FALLOFF = (1 << 4),
+ MOD_WVG_PROXIMITY_WEIGHTS_NORMALIZE = (1 << 3),
};
/* Defines common to all WeightVG modifiers. */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 8c34a7cb0a1..c50e48982b3 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -908,8 +908,6 @@ typedef struct ImagePaintSettings {
/** Mode used for texture painting. */
int mode;
- /** Wm handle. */
- void *paintcursor;
/** Workaround until we support true layer masks. */
struct Image *stencil;
/** Clone layer for image mode for projective texture painting. */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 8f4f066efbb..31a8d967ccf 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -833,9 +833,10 @@ typedef enum eFileSel_Params_RenameFlag {
FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE = 1 << 3,
} eFileSel_Params_RenameFlag;
-/* files in filesel list: file types
- * Note we could use mere values (instead of bitflags) for file types themselves,
- * but since we do not lack of bytes currently...
+/**
+ * Files in the file selector list: file types
+ * Note we could use mere values (instead of bit-flags) for file types themselves,
+ * but since we do not lack of bytes currently.
*/
typedef enum eFileSel_File_Types {
FILE_TYPE_BLENDER = (1 << 2),
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 019e4c9ea9e..63e7a90547e 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -1189,7 +1189,7 @@ typedef enum eColorPicker_Types {
} eColorPicker_Types;
/**
- * Timecode display styles
+ * Time-code display styles.
* #UserDef.timecode_style
*/
typedef enum eTimecodeStyles {
diff --git a/source/blender/makesdna/DNA_view3d_defaults.h b/source/blender/makesdna/DNA_view3d_defaults.h
index 20b491c47f2..10eadf368ef 100644
--- a/source/blender/makesdna/DNA_view3d_defaults.h
+++ b/source/blender/makesdna/DNA_view3d_defaults.h
@@ -64,8 +64,8 @@
.edit_flag = V3D_OVERLAY_EDIT_FACES | V3D_OVERLAY_EDIT_SEAMS | \
V3D_OVERLAY_EDIT_SHARP | V3D_OVERLAY_EDIT_FREESTYLE_EDGE | \
V3D_OVERLAY_EDIT_FREESTYLE_FACE | V3D_OVERLAY_EDIT_EDGES | \
- V3D_OVERLAY_EDIT_CREASES | V3D_OVERLAY_EDIT_BWEIGHTS | \
- V3D_OVERLAY_EDIT_CU_HANDLES, \
+ V3D_OVERLAY_EDIT_CREASES | V3D_OVERLAY_EDIT_BWEIGHTS, \
+ .handle_display = CURVE_HANDLE_SELECTED, \
\
.gpencil_paper_opacity = 0.5f, \
.gpencil_grid_opacity = 0.9f, \
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 6d8d16c4313..ef174f5858f 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -228,9 +228,20 @@ typedef struct View3DOverlay {
/** Factor for mixing vertex paint with original color */
float gpencil_vertex_paint_opacity;
- char _pad4[4];
+ /** Handles display type for curves. */
+ int handle_display;
} View3DOverlay;
+/* View3DOverlay->handle_display */
+typedef enum eHandleDisplay {
+ /* Display only selected points. */
+ CURVE_HANDLE_SELECTED = 0,
+ /* Display all handles. */
+ CURVE_HANDLE_ALL = 1,
+ /* No display handles. */
+ CURVE_HANDLE_NONE = 2,
+} eHandleDisplay;
+
typedef struct View3D_Runtime {
/** Nkey panel stores stuff here. */
void *properties_storage;
@@ -522,7 +533,9 @@ enum {
V3D_OVERLAY_EDIT_FACE_AREA = (1 << 18),
V3D_OVERLAY_EDIT_INDICES = (1 << 19),
- V3D_OVERLAY_EDIT_CU_HANDLES = (1 << 20),
+ /* Deprecated. */
+ /* V3D_OVERLAY_EDIT_CU_HANDLES = (1 << 20), */
+
V3D_OVERLAY_EDIT_CU_NORMALS = (1 << 21),
};
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index d2e27bdbcad..65c43ebc151 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -71,6 +71,7 @@ extern StructRNA RNA_BackgroundImage;
extern StructRNA RNA_BevelModifier;
extern StructRNA RNA_BezierSplinePoint;
extern StructRNA RNA_BlendData;
+extern StructRNA RNA_BlendDataLibraries;
extern StructRNA RNA_BlendTexture;
extern StructRNA RNA_BlenderRNA;
extern StructRNA RNA_BoidRule;
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 7a7ab1085dd..1bcf7f434f2 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -50,6 +50,7 @@ void RNA_free(BlenderRNA *brna);
void RNA_define_verify_sdna(bool verify);
void RNA_define_animate_sdna(bool animate);
void RNA_define_fallback_property_update(int noteflag, const char *updatefunc);
+void RNA_define_lib_overridable(const bool make_overridable);
void RNA_init(void);
void RNA_exit(void);
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 86a088f38ed..2960cea7f53 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -637,7 +637,7 @@ static char *rna_def_property_get_func(
if (!manualfunc) {
if (!dp->dnastructname || !dp->dnaname) {
CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
@@ -654,7 +654,7 @@ static char *rna_def_property_get_func(
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -667,7 +667,7 @@ static char *rna_def_property_get_func(
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -679,7 +679,7 @@ static char *rna_def_property_get_func(
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -1020,7 +1020,7 @@ static char *rna_def_property_set_func(
if (!dp->dnastructname || !dp->dnaname) {
if (prop->flag & PROP_EDITABLE) {
CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
return NULL;
}
@@ -1263,7 +1263,7 @@ static char *rna_def_property_length_func(
if (!manualfunc) {
if (!dp->dnastructname || !dp->dnaname) {
CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -1289,7 +1289,7 @@ static char *rna_def_property_length_func(
if (prop->type == PROP_COLLECTION &&
(!(dp->dnalengthname || dp->dnalengthfixed) || !dp->dnaname)) {
CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -1338,7 +1338,7 @@ static char *rna_def_property_begin_func(
if (!manualfunc) {
if (!dp->dnastructname || !dp->dnaname) {
CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -1823,6 +1823,10 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
case PROP_ENUM: {
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
+ if (!eprop->get && !eprop->set) {
+ rna_set_raw_property(dp, prop);
+ }
+
eprop->get = (void *)rna_def_property_get_func(f, srna, prop, dp, (const char *)eprop->get);
eprop->set = (void *)rna_def_property_set_func(f, srna, prop, dp, (const char *)eprop->set);
break;
@@ -1844,7 +1848,7 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
if (!pprop->type) {
CLOG_ERROR(
&LOG, "%s.%s, pointer must have a struct type.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
break;
}
@@ -1892,21 +1896,21 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
"%s.%s, collection must have a begin function.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
if (!cprop->next) {
CLOG_ERROR(&LOG,
"%s.%s, collection must have a next function.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
if (!cprop->get) {
CLOG_ERROR(&LOG,
"%s.%s, collection must have a get function.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
if (!cprop->item_type) {
@@ -1914,7 +1918,7 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
"%s.%s, collection must have a struct type.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
break;
}
@@ -3652,7 +3656,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
errnest,
prop->identifier,
eprop->defaultvalue & ~totflag);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
else {
@@ -3662,7 +3666,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
srna->identifier,
errnest,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
}
@@ -3672,7 +3676,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
srna->identifier,
errnest,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
break;
}
@@ -4214,7 +4218,7 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
if (srna->reg && !srna->refine) {
CLOG_ERROR(
&LOG, "%s has a register function, must also have refine function.", srna->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
func = srna->functions.first;
@@ -4705,7 +4709,8 @@ static const char *cpp_classes =
" DynamicArray() : data(NULL), length(0) {}\n"
" DynamicArray(int new_length) : data(NULL), length(new_length) { data = (T "
"*)malloc(sizeof(T) * new_length); }\n"
- " DynamicArray(const DynamicArray<T>& other) { copy_from(other); }\n"
+ " DynamicArray(const DynamicArray<T>& other) : data(NULL), length(0) { copy_from(other); "
+ "}\n"
" const DynamicArray<T>& operator = (const DynamicArray<T>& other) { copy_from(other); "
"return *this; }\n"
"\n"
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 85892758a88..2197764794b 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -2182,7 +2182,7 @@ bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
}
for (index = 0; index < len; index++) {
- if (rna_get_fcurve(ptr, prop, index, NULL, NULL, &driven, &special)) {
+ if (BKE_fcurve_find_by_rna(ptr, prop, index, NULL, NULL, &driven, &special)) {
return true;
}
}
@@ -4386,8 +4386,8 @@ static int rna_raw_access(ReportList *reports,
/* check type */
itemtype = RNA_property_type(itemprop);
- if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
- BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
+ if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM)) {
+ BKE_report(reports, RPT_ERROR, "Only boolean, int float and enum properties supported");
return 0;
}
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index facbf8d59cc..e67366fc7ef 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -147,7 +147,7 @@ static FCurve *rna_Action_fcurve_find(bAction *act,
}
/* Returns NULL if not found. */
- return list_find_fcurve(&act->curves, data_path, index);
+ return BKE_fcurve_find(&act->curves, data_path, index);
}
static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerRNA *fcu_ptr)
@@ -164,7 +164,7 @@ static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerR
}
action_groups_remove_channel(act, fcu);
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
RNA_POINTER_INVALIDATE(fcu_ptr);
}
else {
@@ -174,7 +174,7 @@ static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerR
}
BLI_remlink(&act->curves, fcu);
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
RNA_POINTER_INVALIDATE(fcu_ptr);
}
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 7ea44bce6db..823446a9d3b 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -648,7 +648,7 @@ static FCurve *rna_Driver_from_existing(AnimData *adt, bContext *C, FCurve *src_
}
else {
/* just make a copy of the existing one and add to self */
- FCurve *new_fcu = copy_fcurve(src_driver);
+ FCurve *new_fcu = BKE_fcurve_copy(src_driver);
/* XXX: if we impose any ordering on these someday, this will be problematic */
BLI_addtail(&adt->drivers, new_fcu);
@@ -664,7 +664,7 @@ static FCurve *rna_Driver_new(
return NULL;
}
- if (list_find_fcurve(&adt->drivers, rna_path, array_index)) {
+ if (BKE_fcurve_find(&adt->drivers, rna_path, array_index)) {
BKE_reportf(reports, RPT_ERROR, "Driver '%s[%d]' already exists", rna_path, array_index);
return NULL;
}
@@ -683,7 +683,7 @@ static void rna_Driver_remove(AnimData *adt, Main *bmain, ReportList *reports, F
BKE_report(reports, RPT_ERROR, "Driver not found in this animation data");
return;
}
- free_fcurve(fcu);
+ BKE_fcurve_free(fcu);
DEG_relations_tag_update(bmain);
}
@@ -698,7 +698,7 @@ static FCurve *rna_Driver_find(AnimData *adt,
}
/* Returns NULL if not found. */
- return list_find_fcurve(&adt->drivers, data_path, index);
+ return BKE_fcurve_find(&adt->drivers, data_path, index);
}
bool rna_AnimaData_override_apply(Main *UNUSED(bmain),
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index fe35af8c2e0..8454d5c125f 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -176,6 +176,20 @@ static void rna_Armature_redraw_data(Main *UNUSED(bmain), Scene *UNUSED(scene),
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
}
+/* Unselect bones when hidden */
+static void rna_Bone_hide_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bArmature *arm = (bArmature *)ptr->owner_id;
+ Bone *bone = (Bone *)ptr->data;
+
+ if (bone->flag & BONE_HIDDEN_P) {
+ bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+
+ WM_main_add_notifier(NC_OBJECT | ND_POSE, arm);
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+}
+
/* called whenever a bone is renamed */
static void rna_Bone_update_renamed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
@@ -1143,7 +1157,8 @@ static void rna_def_bone(BlenderRNA *brna)
prop,
"Hide",
"Bone is not visible when it is not in Edit Mode (i.e. in Object or Pose Modes)");
- RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1);
+ RNA_def_property_update(prop, 0, "rna_Bone_hide_update");
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_SELECTED);
@@ -1312,7 +1327,7 @@ static void rna_def_edit_bone(BlenderRNA *brna)
prop,
"Editbone Matrix",
"Matrix combining loc/rot of the bone (head position, direction and roll), "
- "in armature space (WARNING: does not include/support bone's length/size)");
+ "in armature space (does not include/support bone's length/size)");
RNA_def_property_float_funcs(prop, "rna_EditBone_matrix_get", "rna_EditBone_matrix_set", NULL);
RNA_api_armature_edit_bone(srna);
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index d3b607fcb76..209e5a1ff8b 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1960,6 +1960,12 @@ static void rna_def_brush(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem brush_pose_deform_type_items[] = {
+ {BRUSH_POSE_DEFORM_ROTATE_TWIST, "ROTATE_TWIST", 0, "Rotate/Twist", ""},
+ {BRUSH_POSE_DEFORM_SCALE_TRASLATE, "SCALE_TRANSLATE", 0, "Scale/Translate", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
static const EnumPropertyItem brush_pose_origin_type_items[] = {
{BRUSH_POSE_ORIGIN_TOPOLOGY,
"TOPOLOGY",
@@ -1972,6 +1978,11 @@ static void rna_def_brush(BlenderRNA *brna)
0,
"Face Sets",
"Creates a pose segment per face sets, starting from the active face set"},
+ {BRUSH_POSE_ORIGIN_FACE_SETS_FK,
+ "FACE_SETS_FK",
+ 0,
+ "Face Sets FK",
+ "Simulates an FK deformation using the Face Set under the cursor as control"},
{0, NULL, 0, NULL, NULL},
};
@@ -2095,6 +2106,11 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "pose_deform_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, brush_pose_deform_type_items);
+ RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "pose_origin_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_pose_origin_type_items);
RNA_def_property_ui_text(prop,
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 47a09233769..79ee9619e36 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -193,6 +193,8 @@ static void rna_def_camera_background_image(BlenderRNA *brna)
RNA_def_struct_ui_text(
srna, "Background Image", "Image and settings for display in the 3D View background");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "source");
RNA_def_property_enum_items(prop, bgpic_source_items);
@@ -301,6 +303,8 @@ static void rna_def_camera_background_image(BlenderRNA *brna)
RNA_def_property_enum_items(prop, bgpic_camera_frame_items);
RNA_def_property_ui_text(prop, "Frame Method", "How the image fits in the camera frame");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_camera_background_images(BlenderRNA *brna, PropertyRNA *cprop)
@@ -356,6 +360,8 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna)
RNA_def_struct_nested(brna, srna, "Camera");
RNA_def_struct_ui_text(srna, "Stereo", "Stereoscopy settings for a Camera data-block");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "convergence_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, convergence_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
@@ -409,6 +415,8 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Pole Merge End Angle", "Angle at which interocular distance is 0");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_camera_dof_settings_data(BlenderRNA *brna)
@@ -421,6 +429,8 @@ static void rna_def_camera_dof_settings_data(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_CameraDOFSettings_path");
RNA_def_struct_ui_text(srna, "Depth of Field", "Depth of Field settings");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_DOF_ENABLED);
RNA_def_property_ui_text(prop, "Depth of Field", "Use Depth of Field");
@@ -469,6 +479,8 @@ static void rna_def_camera_dof_settings_data(BlenderRNA *brna)
RNA_def_property_range(prop, 0.01f, FLT_MAX);
RNA_def_property_ui_range(prop, 1.0f, 2.0f, 0.1, 3);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update");
+
+ RNA_define_lib_overridable(false);
}
void RNA_def_camera(BlenderRNA *brna)
@@ -505,6 +517,8 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Camera", "Camera data-block for storing camera settings");
RNA_def_struct_ui_icon(srna, ICON_CAMERA_DATA);
+ RNA_define_lib_overridable(true);
+
/* Enums */
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_type_items);
@@ -736,6 +750,8 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Background Images", "List of background images");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ RNA_define_lib_overridable(false);
+
rna_def_animdata_common(srna);
rna_def_camera_background_image(brna);
diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c
index fe64ead3f89..fbc2b871026 100644
--- a/source/blender/makesrna/intern/rna_collection.c
+++ b/source/blender/makesrna/intern/rna_collection.c
@@ -394,6 +394,8 @@ void RNA_def_collections(BlenderRNA *brna)
* removed if no objects are in the collection and not in a scene. */
RNA_def_struct_clear_flag(srna, STRUCT_ID_REFCOUNT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "instance_offset", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_ui_text(
prop, "Instance Offset", "Offset from the origin to use when instancing");
@@ -402,7 +404,6 @@ void RNA_def_collections(BlenderRNA *brna)
prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_override_funcs(prop, NULL, NULL, "rna_Collection_objects_override_apply");
RNA_def_property_ui_text(prop, "Objects", "Objects that are directly in this collection");
RNA_def_property_collection_funcs(prop,
@@ -421,6 +422,7 @@ void RNA_def_collections(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "All Objects", "Objects that are in this collection and its child collections");
RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
+ RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_collection_funcs(prop,
"rna_Collection_all_objects_begin",
"rna_iterator_listbase_next",
@@ -433,7 +435,6 @@ void RNA_def_collections(BlenderRNA *brna)
prop = RNA_def_property(srna, "children", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Collection");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_override_funcs(prop, NULL, NULL, "rna_Collection_children_override_apply");
RNA_def_property_ui_text(
prop, "Children", "Collections that are immediate children of this collection");
@@ -452,7 +453,6 @@ void RNA_def_collections(BlenderRNA *brna)
prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_SELECT);
RNA_def_property_boolean_funcs(prop, NULL, "rna_Collection_hide_select_set");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1);
RNA_def_property_ui_text(prop, "Disable Selection", "Disable selection in viewport");
@@ -461,7 +461,6 @@ void RNA_def_collections(BlenderRNA *brna)
prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_VIEWPORT);
RNA_def_property_boolean_funcs(prop, NULL, "rna_Collection_hide_viewport_set");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1);
RNA_def_property_ui_text(prop, "Disable in Viewports", "Globally disable in viewports");
@@ -470,11 +469,12 @@ void RNA_def_collections(BlenderRNA *brna)
prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_RENDER);
RNA_def_property_boolean_funcs(prop, NULL, "rna_Collection_hide_render_set");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1);
RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
+
+ RNA_define_lib_overridable(false);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 9f627f9d407..12265a8e1f7 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -389,7 +389,7 @@ static void rna_Constraint_name_set(PointerRNA *ptr, const char *value)
/* make sure name is unique */
if (ptr->owner_id) {
Object *ob = (Object *)ptr->owner_id;
- ListBase *list = get_constraint_lb(ob, con, NULL);
+ ListBase *list = ED_object_constraint_list_from_constraint(ob, con, NULL);
/* if we have the list, check for unique name, otherwise give up */
if (list) {
@@ -404,7 +404,7 @@ static void rna_Constraint_name_set(PointerRNA *ptr, const char *value)
static char *rna_Constraint_do_compute_path(Object *ob, bConstraint *con)
{
bPoseChannel *pchan;
- ListBase *lb = get_constraint_lb(ob, con, &pchan);
+ ListBase *lb = ED_object_constraint_list_from_constraint(ob, con, &pchan);
if (lb == NULL) {
printf("%s: internal error, constraint '%s' not found in object '%s'\n",
@@ -824,6 +824,8 @@ static void rna_def_constraint_headtail_common(StructRNA *srna)
{
PropertyRNA *prop;
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
@@ -835,23 +837,28 @@ static void rna_def_constraint_headtail_common(StructRNA *srna)
"Follow B-Bone",
"Follow shape of B-Bone segments when calculating Head/Tail position");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_target_common(StructRNA *srna)
{
PropertyRNA *prop;
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_ui_text(prop, "Target", "Target object");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
prop = RNA_def_property(srna, "subtarget", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "subtarget");
RNA_def_property_ui_text(prop, "Sub-Target", "Armature bone, mesh or lattice vertex group, ...");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constrainttarget(BlenderRNA *brna)
@@ -864,11 +871,12 @@ static void rna_def_constrainttarget(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_ConstraintTarget_path");
RNA_def_struct_sdna(srna, "bConstraintTarget");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_ui_text(prop, "Target", "Target object");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(
prop, NC_OBJECT | ND_CONSTRAINT, "rna_ConstraintTarget_dependency_update");
@@ -879,6 +887,8 @@ static void rna_def_constrainttarget(BlenderRNA *brna)
prop, NC_OBJECT | ND_CONSTRAINT, "rna_ConstraintTarget_dependency_update");
/* space, flag and type still to do */
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constrainttarget_bone(BlenderRNA *brna)
@@ -892,13 +902,14 @@ static void rna_def_constrainttarget_bone(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_ConstraintTarget_path");
RNA_def_struct_sdna(srna, "bConstraintTarget");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_ui_text(prop, "Target", "Target armature");
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ConstraintTargetBone_target_set", NULL, "rna_Armature_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(
prop, NC_OBJECT | ND_CONSTRAINT, "rna_ConstraintTarget_dependency_update");
@@ -913,6 +924,8 @@ static void rna_def_constrainttarget_bone(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Blend Weight", "Blending weight of this bone");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_ConstraintTarget_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_childof(BlenderRNA *brna)
@@ -928,6 +941,8 @@ static void rna_def_constraint_childof(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_location_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CHILDOF_LOCX);
RNA_def_property_ui_text(prop, "Location X", "Use X Location of Parent");
@@ -985,6 +1000,8 @@ static void rna_def_constraint_childof(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Inverse Matrix", "Transformation matrix to apply before");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_python(BlenderRNA *brna)
@@ -996,6 +1013,8 @@ static void rna_def_constraint_python(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Python Constraint", "Use Python script for constraint evaluation");
RNA_def_struct_sdna_from(srna, "bPythonConstraint", "data");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "targets", NULL);
RNA_def_property_struct_type(prop, "ConstraintTarget");
@@ -1021,6 +1040,8 @@ static void rna_def_constraint_python(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", PYCON_SCRIPTERROR);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Script Error", "The linked Python script has thrown an error");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_armature_deform_targets(BlenderRNA *brna, PropertyRNA *cprop)
@@ -1065,11 +1086,12 @@ static void rna_def_constraint_armature_deform(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bArmatureConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_ARMATURE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "targets", NULL);
RNA_def_property_struct_type(prop, "ConstraintTargetBone");
RNA_def_property_ui_text(prop, "Targets", "Target Bones");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
rna_def_constraint_armature_deform_targets(brna, prop);
prop = RNA_def_property(srna, "use_deform_preserve_volume", PROP_BOOLEAN, PROP_NONE);
@@ -1095,6 +1117,8 @@ static void rna_def_constraint_armature_deform(BlenderRNA *brna)
"Use the current bone location for envelopes and choosing B-Bone "
"segments instead of rest position");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_kinematic(BlenderRNA *brna)
@@ -1121,6 +1145,8 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 10000);
RNA_def_property_ui_text(prop, "Iterations", "Maximum number of solving iterations");
@@ -1130,7 +1156,6 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "poletar");
RNA_def_property_ui_text(prop, "Pole Target", "Object for pole rotation");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
prop = RNA_def_property(srna, "pole_subtarget", PROP_STRING, PROP_NONE);
@@ -1240,6 +1265,8 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0, 100.f);
RNA_def_property_ui_text(prop, "Distance", "Radius of limiting sphere");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_track_to(BlenderRNA *brna)
@@ -1266,6 +1293,8 @@ static void rna_def_constraint_track_to(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_CON_TRACKTO);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "reserved1");
RNA_def_property_enum_items(prop, track_axis_items);
@@ -1283,6 +1312,8 @@ static void rna_def_constraint_track_to(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Target Z", "Target's Z axis, not World Z axis, will constraint the Up direction");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_locate_like(BlenderRNA *brna)
@@ -1300,6 +1331,8 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_X);
RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X location");
@@ -1334,6 +1367,8 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_OFFSET);
RNA_def_property_ui_text(prop, "Offset", "Add original location into copied location");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_rotate_like(BlenderRNA *brna)
@@ -1370,6 +1405,8 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ROTLIKE_X);
RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X rotation");
@@ -1420,6 +1457,8 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Offset", "DEPRECATED: Add original rotation into copied rotation");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_size_like(BlenderRNA *brna)
@@ -1434,6 +1473,8 @@ static void rna_def_constraint_size_like(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_X);
RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X scale");
@@ -1476,6 +1517,8 @@ static void rna_def_constraint_size_like(BlenderRNA *brna)
"Additive",
"Use addition instead of multiplication to combine scale (2.7 compatibility)");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_same_volume(BlenderRNA *brna)
@@ -1518,6 +1561,8 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bSameVolumeConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_SAMEVOL);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "free_axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "free_axis");
RNA_def_property_enum_items(prop, axis_items);
@@ -1535,6 +1580,8 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna)
RNA_def_property_range(prop, 0.001f, 100.0f);
RNA_def_property_ui_text(prop, "Volume", "Volume of the bone at rest");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_transform_like(BlenderRNA *brna)
@@ -1575,12 +1622,16 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mix_mode");
RNA_def_property_enum_items(prop, mix_mode_items);
RNA_def_property_ui_text(
prop, "Mix Mode", "Specify how the copied and existing transformations are combined");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_minmax(BlenderRNA *brna)
@@ -1606,6 +1657,8 @@ static void rna_def_constraint_minmax(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "floor_location", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "minmaxflag");
RNA_def_property_enum_items(prop, minmax_items);
@@ -1622,6 +1675,8 @@ static void rna_def_constraint_minmax(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -100.0f, 100.0f, 1, -1);
RNA_def_property_ui_text(prop, "Offset", "Offset of floor from object origin");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_action(BlenderRNA *brna)
@@ -1673,6 +1728,8 @@ static void rna_def_constraint_action(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mix_mode");
RNA_def_property_enum_items(prop, mix_mode_items);
@@ -1697,7 +1754,6 @@ static void rna_def_constraint_action(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Action_id_poll");
RNA_def_property_ui_text(prop, "Action", "The constraining action");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
prop = RNA_def_property(srna, "use_bone_object_action", PROP_BOOLEAN, PROP_NONE);
@@ -1733,6 +1789,8 @@ static void rna_def_constraint_action(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Minimum", "Minimum value for target channel range");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_ActionConstraint_minmax_range");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_locked_track(BlenderRNA *brna)
@@ -1760,6 +1818,8 @@ static void rna_def_constraint_locked_track(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "trackflag");
RNA_def_property_enum_items(prop, track_axis_items);
@@ -1771,6 +1831,8 @@ static void rna_def_constraint_locked_track(BlenderRNA *brna)
RNA_def_property_enum_items(prop, lock_items);
RNA_def_property_ui_text(prop, "Locked Axis", "Axis that points upward");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_follow_path(BlenderRNA *brna)
@@ -1800,12 +1862,13 @@ static void rna_def_constraint_follow_path(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bFollowPathConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_FOLLOWPATH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Curve_object_poll");
RNA_def_property_ui_text(prop, "Target", "Target Curve object");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_TIME);
@@ -1852,6 +1915,8 @@ static void rna_def_constraint_follow_path(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "followflag", FOLLOWPATH_RADIUS);
RNA_def_property_ui_text(prop, "Curve Radius", "Object is scaled by the curve radius");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_stretch_to(BlenderRNA *brna)
@@ -1888,6 +1953,8 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "volume", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "volmode");
RNA_def_property_enum_items(prop, volume_items);
@@ -1941,6 +2008,8 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Volume Variation Smoothness", "Strength of volume stretching clamping");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_clamp_to(BlenderRNA *brna)
@@ -1964,12 +2033,13 @@ static void rna_def_constraint_clamp_to(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bClampToConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_CLAMPTO);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Curve_object_poll");
RNA_def_property_ui_text(prop, "Target", "Target Object (Curves only)");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
prop = RNA_def_property(srna, "main_axis", PROP_ENUM, PROP_NONE);
@@ -1983,6 +2053,8 @@ static void rna_def_constraint_clamp_to(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Cyclic", "Treat curve as cyclic curve (no clamping to curve bounding box)");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_transform(BlenderRNA *brna)
@@ -2033,6 +2105,8 @@ static void rna_def_constraint_transform(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "map_from", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "from");
RNA_def_property_enum_items(prop, transform_items);
@@ -2323,6 +2397,8 @@ static void rna_def_constraint_transform(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Scale Mix Mode", "Specify how to combine the new scale with original");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_location_limit(BlenderRNA *brna)
@@ -2336,6 +2412,8 @@ static void rna_def_constraint_location_limit(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bLocLimitConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_LOCLIMIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_min_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMIT_XMIN);
RNA_def_property_ui_text(prop, "Minimum X", "Use the minimum X value");
@@ -2407,6 +2485,8 @@ static void rna_def_constraint_location_limit(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "For Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_rotation_limit(BlenderRNA *brna)
@@ -2420,6 +2500,8 @@ static void rna_def_constraint_rotation_limit(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bRotLimitConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_ROTLIMIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_limit_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMIT_XROT);
RNA_def_property_ui_text(prop, "Limit X", "Use the minimum X value");
@@ -2476,6 +2558,8 @@ static void rna_def_constraint_rotation_limit(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "For Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_size_limit(BlenderRNA *brna)
@@ -2489,6 +2573,8 @@ static void rna_def_constraint_size_limit(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bSizeLimitConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_SIZELIMIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_min_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMIT_XMIN);
RNA_def_property_ui_text(prop, "Minimum X", "Use the minimum X value");
@@ -2560,6 +2646,8 @@ static void rna_def_constraint_size_limit(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "For Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_distance_limit(BlenderRNA *brna)
@@ -2578,6 +2666,8 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "dist");
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 10, 3);
@@ -2596,6 +2686,8 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "For Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_shrinkwrap(BlenderRNA *brna)
@@ -2649,12 +2741,13 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bShrinkwrapConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_SHRINKWRAP);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "target"); /* TODO, mesh type */
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
RNA_def_property_ui_text(prop, "Target", "Target Mesh object");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
prop = RNA_def_property(srna, "shrinkwrap_type", PROP_ENUM, PROP_NONE);
@@ -2734,6 +2827,8 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna)
RNA_def_property_enum_items(prop, track_axis_items);
RNA_def_property_ui_text(prop, "Track Axis", "Axis that is aligned to the normal");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_damped_track(BlenderRNA *brna)
@@ -2752,11 +2847,15 @@ static void rna_def_constraint_damped_track(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "trackflag");
RNA_def_property_enum_items(prop, track_axis_items);
RNA_def_property_ui_text(prop, "Track Axis", "Axis that points to the target object");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_spline_ik(BlenderRNA *brna)
@@ -2804,13 +2903,14 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bSplineIKConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_SPLINEIK);
+ RNA_define_lib_overridable(true);
+
/* target chain */
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Curve_object_poll");
RNA_def_property_ui_text(prop, "Target", "Curve that controls this relationship");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
prop = RNA_def_property(srna, "chain_count", PROP_INT, PROP_NONE);
@@ -2922,6 +3022,8 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Volume Variation Smoothness", "Strength of volume stretching clamping");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_pivot(BlenderRNA *brna)
@@ -2973,13 +3075,14 @@ static void rna_def_constraint_pivot(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_CON_PIVOT);
+ RNA_define_lib_overridable(true);
+
/* target-defined pivot */
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_ui_text(
prop, "Target", "Target Object, defining the position of the pivot when defined");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
prop = RNA_def_property(srna, "subtarget", PROP_STRING, PROP_NONE);
@@ -3011,6 +3114,8 @@ static void rna_def_constraint_pivot(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Enabled Rotation Range", "Rotation range on which pivoting should occur");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_follow_track(BlenderRNA *brna)
@@ -3031,12 +3136,13 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bFollowTrackConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_FOLLOWTRACK);
+ RNA_define_lib_overridable(true);
+
/* movie clip */
prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "clip");
RNA_def_property_ui_text(prop, "Movie Clip", "Movie Clip to get tracking data from");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
/* track */
@@ -3070,7 +3176,6 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Camera", "Camera to which motion is parented (if empty active scene camera is used)");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
RNA_def_property_pointer_funcs(prop,
NULL,
@@ -3086,7 +3191,6 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna)
"Depth Object",
"Object used to define depth in camera space by projecting onto surface of this object");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
RNA_def_property_pointer_funcs(prop,
NULL,
@@ -3106,6 +3210,8 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", FOLLOWTRACK_USE_UNDISTORTION);
RNA_def_property_ui_text(prop, "Undistort", "Parent to undistorted position of 2D track");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_camera_solver(BlenderRNA *brna)
@@ -3119,12 +3225,13 @@ static void rna_def_constraint_camera_solver(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bCameraSolverConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_CAMERASOLVER);
+ RNA_define_lib_overridable(true);
+
/* movie clip */
prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "clip");
RNA_def_property_ui_text(prop, "Movie Clip", "Movie Clip to get tracking data from");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
/* use default clip */
@@ -3132,6 +3239,8 @@ static void rna_def_constraint_camera_solver(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", CAMERASOLVER_ACTIVECLIP);
RNA_def_property_ui_text(prop, "Active Clip", "Use active clip defined in scene");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_object_solver(BlenderRNA *brna)
@@ -3145,12 +3254,13 @@ static void rna_def_constraint_object_solver(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bObjectSolverConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_OBJECTSOLVER);
+ RNA_define_lib_overridable(true);
+
/* movie clip */
prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "clip");
RNA_def_property_ui_text(prop, "Movie Clip", "Movie Clip to get tracking data from");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
/* use default clip */
@@ -3177,13 +3287,14 @@ static void rna_def_constraint_object_solver(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Camera", "Camera to which motion is parented (if empty active scene camera is used)");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
RNA_def_property_pointer_funcs(prop,
NULL,
"rna_Constraint_objectSolver_camera_set",
NULL,
"rna_Constraint_cameraObject_poll");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_transform_cache(BlenderRNA *brna)
@@ -3197,12 +3308,13 @@ static void rna_def_constraint_transform_cache(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bTransformCacheConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_TRANSFORM_CACHE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "cache_file", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "cache_file");
RNA_def_property_struct_type(prop, "CacheFile");
RNA_def_property_ui_text(prop, "Cache File", "");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Constraint_dependency_update");
prop = RNA_def_property(srna, "object_path", PROP_STRING, PROP_NONE);
@@ -3211,6 +3323,8 @@ static void rna_def_constraint_transform_cache(BlenderRNA *brna)
"Object Path",
"Path to the object in the Alembic archive used to lookup the transform matrix");
RNA_def_property_update(prop, 0, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
/* base struct for constraints */
@@ -3241,6 +3355,8 @@ void RNA_def_constraint(BlenderRNA *brna)
RNA_def_property_enum_items(prop, rna_enum_constraint_type_items);
RNA_def_property_ui_text(prop, "Type", "");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "owner_space", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "ownspace");
RNA_def_property_enum_items(prop, owner_space_pchan_items);
@@ -3258,7 +3374,6 @@ void RNA_def_constraint(BlenderRNA *brna)
/* flags */
prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_OFF);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Disable", "Enable/Disable Constraint");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1);
@@ -3267,7 +3382,6 @@ void RNA_def_constraint(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
RNA_def_property_boolean_sdna(prop, NULL, "ui_expand_flag", 0);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
- RNA_def_property_ui_text(prop, "Expanded", "Constraint's panel is expanded in UI");
RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1);
/* XXX this is really an internal flag,
@@ -3315,6 +3429,8 @@ void RNA_def_constraint(BlenderRNA *brna)
"Rot error",
"Amount of residual error in radians for constraints that work on orientation");
+ RNA_define_lib_overridable(false);
+
/* pointers */
rna_def_constrainttarget(brna);
rna_def_constrainttarget_bone(brna);
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 7a439a11a54..d6bedc61424 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -61,7 +61,18 @@ static CLG_LogRef LOG = {"rna.define"};
/* Global used during defining */
-BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1};
+BlenderDefRNA DefRNA = {
+ .sdna = NULL,
+ .structs = {NULL, NULL},
+ .allocs = {NULL, NULL},
+ .laststruct = NULL,
+ .error = 0,
+ .silent = false,
+ .preprocess = false,
+ .verify = true,
+ .animate = true,
+ .make_overridable = false,
+};
#ifndef RNA_RUNTIME
static struct {
@@ -691,13 +702,13 @@ BlenderRNA *RNA_create(void)
BLI_listbase_clear(&DefRNA.structs);
brna->structs_map = BLI_ghash_str_new_ex(__func__, 2048);
- DefRNA.error = 0;
- DefRNA.preprocess = 1;
+ DefRNA.error = false;
+ DefRNA.preprocess = true;
DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, &error_message);
if (DefRNA.sdna == NULL) {
CLOG_ERROR(&LOG, "Failed to decode SDNA: %s.", error_message);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
/* We need both alias and static (on-disk) DNA names. */
@@ -737,7 +748,7 @@ void RNA_define_free(BlenderRNA *UNUSED(brna))
DefRNA.sdna = NULL;
}
- DefRNA.error = 0;
+ DefRNA.error = false;
}
void RNA_define_verify_sdna(bool verify)
@@ -745,6 +756,15 @@ void RNA_define_verify_sdna(bool verify)
DefRNA.verify = verify;
}
+/**
+ * Properties defined when this is enabled are lib-overridable by default (except for Pointer
+ * ones).
+ */
+void RNA_define_lib_overridable(const bool make_overridable)
+{
+ DefRNA.make_overridable = make_overridable;
+}
+
#ifndef RNA_RUNTIME
void RNA_define_animate_sdna(bool animate)
{
@@ -910,7 +930,7 @@ StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRN
if (rna_validate_identifier(identifier, error, false) == 0) {
CLOG_ERROR(&LOG, "struct identifier \"%s\" error - %s", identifier, error);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
@@ -1040,7 +1060,7 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *
srnafrom = BLI_ghash_lookup(brna->structs_map, from);
if (!srnafrom) {
CLOG_ERROR(&LOG, "struct %s not found to define %s.", from, identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
@@ -1065,7 +1085,7 @@ void RNA_def_struct_sdna(StructRNA *srna, const char *structname)
if (DNA_struct_find_nr_wrapper(DefRNA.sdna, structname) == -1) {
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "%s not found.", structname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
return;
}
@@ -1093,7 +1113,7 @@ void RNA_def_struct_sdna_from(StructRNA *srna, const char *structname, const cha
if (DNA_struct_find_nr_wrapper(DefRNA.sdna, structname) == -1) {
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "%s not found.", structname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
return;
}
@@ -1106,7 +1126,7 @@ void RNA_def_struct_name_property(struct StructRNA *srna, struct PropertyRNA *pr
{
if (prop->type != PROP_STRING) {
CLOG_ERROR(&LOG, "\"%s.%s\", must be a string property.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
else {
srna->nameproperty = prop;
@@ -1121,7 +1141,7 @@ void RNA_def_struct_nested(BlenderRNA *brna, StructRNA *srna, const char *struct
srnafrom = BLI_ghash_lookup(brna->structs_map, structname);
if (!srnafrom) {
CLOG_ERROR(&LOG, "struct %s not found for %s.", structname, srna->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
srna->nested = srnafrom;
@@ -1271,7 +1291,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
if (rna_validate_identifier(identifier, error, true) == 0) {
CLOG_ERROR(
&LOG, "property identifier \"%s.%s\" - %s", CONTAINER_RNA_ID(cont), identifier, error);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
dcont = rna_find_container_def(cont);
@@ -1279,7 +1299,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
/* XXX - toto, detect supertype collisions */
if (rna_findlink(&dcont->properties, identifier)) {
CLOG_ERROR(&LOG, "duplicate identifier \"%s.%s\"", CONTAINER_RNA_ID(cont), identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
dprop = MEM_callocN(sizeof(PropertyDefRNA), "PropertyDefRNA");
@@ -1294,7 +1314,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
CONTAINER_RNA_ID(cont),
identifier,
error);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
#endif
}
@@ -1309,7 +1329,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
"subtype does not apply to 'PROP_BOOLEAN' \"%s.%s\"",
CONTAINER_RNA_ID(cont),
identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
break;
@@ -1322,7 +1342,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
"subtype does not apply to 'PROP_INT' \"%s.%s\"",
CONTAINER_RNA_ID(cont),
identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
#endif
@@ -1371,7 +1391,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
break;
default:
CLOG_ERROR(&LOG, "\"%s.%s\", invalid property type.", CONTAINER_RNA_ID(cont), identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
@@ -1404,6 +1424,12 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
}
}
+#ifndef RNA_RUNTIME
+ if (DefRNA.make_overridable) {
+ prop->flag_override |= PROPOVERRIDE_OVERRIDABLE_LIBRARY;
+ }
+#endif
+
if (type == PROP_STRING) {
/* used so generated 'get/length/set' functions skip a NULL check
* in some cases we want it */
@@ -1413,42 +1439,42 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
if (DefRNA.preprocess) {
switch (type) {
case PROP_BOOLEAN:
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_boolean_sdna(prop, NULL, identifier, 0);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
case PROP_INT: {
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_int_sdna(prop, NULL, identifier);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
}
case PROP_FLOAT: {
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_float_sdna(prop, NULL, identifier);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
}
case PROP_STRING: {
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_string_sdna(prop, NULL, identifier);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
}
case PROP_ENUM:
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_enum_sdna(prop, NULL, identifier);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
case PROP_POINTER:
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_pointer_sdna(prop, NULL, identifier);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
case PROP_COLLECTION:
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_collection_sdna(prop, NULL, identifier, NULL);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
}
}
@@ -1543,7 +1569,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length)
"\"%s.%s\", array length must be zero of greater.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -1553,7 +1579,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length)
srna->identifier,
prop->identifier,
RNA_MAX_ARRAY_LENGTH);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -1563,7 +1589,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length)
srna->identifier,
prop->identifier,
prop->arraydimension);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -1580,7 +1606,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length)
"\"%s.%s\", only boolean/int/float can be array.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1606,7 +1632,7 @@ void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int le
srna->identifier,
prop->identifier,
RNA_MAX_ARRAY_DIMENSION);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -1620,7 +1646,7 @@ void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int le
"\"%s.%s\", only boolean/int/float can be array.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
@@ -1680,22 +1706,22 @@ void RNA_def_property_ui_range(
#ifndef NDEBUG
if (min > max) {
CLOG_ERROR(&LOG, "\"%s.%s\", min > max.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
if (step < 0 || step > 100) {
CLOG_ERROR(&LOG, "\"%s.%s\", step outside range.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
if (step == 0) {
CLOG_ERROR(&LOG, "\"%s.%s\", step is zero.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
if (precision < -1 || precision > UI_PRECISION_FLOAT_MAX) {
CLOG_ERROR(&LOG, "\"%s.%s\", precision outside range.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
#endif
@@ -1718,7 +1744,7 @@ void RNA_def_property_ui_range(
default:
CLOG_ERROR(
&LOG, "\"%s.%s\", invalid type for ui range.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1730,7 +1756,7 @@ void RNA_def_property_range(PropertyRNA *prop, double min, double max)
#ifdef DEBUG
if (min > max) {
CLOG_ERROR(&LOG, "\"%s.%s\", min > max.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
#endif
@@ -1753,7 +1779,7 @@ void RNA_def_property_range(PropertyRNA *prop, double min, double max)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", invalid type for range.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1781,7 +1807,7 @@ void RNA_def_property_struct_type(PropertyRNA *prop, const char *type)
default:
CLOG_ERROR(
&LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1814,7 +1840,7 @@ void RNA_def_property_struct_runtime(PropertyRNA *prop, StructRNA *type)
default:
CLOG_ERROR(
&LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1831,7 +1857,7 @@ void RNA_def_property_enum_native_type(PropertyRNA *prop, const char *native_enu
default:
CLOG_ERROR(
&LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1856,7 +1882,7 @@ void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item
"\"%s.%s\", enum identifiers must not contain spaces.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
else if (item[i].value == eprop->defaultvalue) {
@@ -1879,7 +1905,7 @@ void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item
default:
CLOG_ERROR(
&LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1896,7 +1922,7 @@ void RNA_def_property_string_maxlength(PropertyRNA *prop, int maxlength)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1920,7 +1946,7 @@ void RNA_def_property_boolean_default(PropertyRNA *prop, bool value)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1937,7 +1963,7 @@ void RNA_def_property_boolean_array_default(PropertyRNA *prop, const bool *array
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1959,7 +1985,7 @@ void RNA_def_property_int_default(PropertyRNA *prop, int value)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1981,7 +2007,7 @@ void RNA_def_property_int_array_default(PropertyRNA *prop, const int *array)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -2003,7 +2029,7 @@ void RNA_def_property_float_default(PropertyRNA *prop, float value)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -2025,7 +2051,7 @@ void RNA_def_property_float_array_default(PropertyRNA *prop, const float *array)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -2043,7 +2069,7 @@ void RNA_def_property_string_default(PropertyRNA *prop, const char *value)
"\"%s.%s\", NULL string passed (dont call in this case).",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
@@ -2052,7 +2078,7 @@ void RNA_def_property_string_default(PropertyRNA *prop, const char *value)
"\"%s.%s\", empty string passed (dont call in this case).",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
// BLI_assert(0);
break;
}
@@ -2066,7 +2092,7 @@ void RNA_def_property_string_default(PropertyRNA *prop, const char *value)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -2096,7 +2122,7 @@ void RNA_def_property_enum_default(PropertyRNA *prop, int value)
srna->identifier,
prop->identifier,
eprop->defaultvalue & ~totflag);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
else {
@@ -2113,7 +2139,7 @@ void RNA_def_property_enum_default(PropertyRNA *prop, int value)
else {
CLOG_ERROR(
&LOG, "\"%s.%s\", default is not in items.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
}
@@ -2122,7 +2148,7 @@ void RNA_def_property_enum_default(PropertyRNA *prop, int value)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not enum.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -2175,7 +2201,7 @@ static PropertyDefRNA *rna_def_property_sdna(PropertyRNA *prop,
structname,
propname,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -2219,13 +2245,13 @@ void RNA_def_property_boolean_sdna(PropertyRNA *prop,
if (prop->type != PROP_BOOLEAN) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
if ((dp = rna_def_property_sdna(prop, structname, propname))) {
- if (DefRNA.silent == 0) {
+ if (!DefRNA.silent) {
/* error check to ensure floats are not wrapped as ints/bools */
if (dp->dnatype && *dp->dnatype && IS_DNATYPE_BOOLEAN_COMPAT(dp->dnatype) == 0) {
CLOG_ERROR(&LOG,
@@ -2234,7 +2260,7 @@ void RNA_def_property_boolean_sdna(PropertyRNA *prop,
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
}
@@ -2323,14 +2349,14 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const
if (prop->type != PROP_INT) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
if ((dp = rna_def_property_sdna(prop, structname, propname))) {
/* error check to ensure floats are not wrapped as ints/bools */
- if (DefRNA.silent == 0) {
+ if (!DefRNA.silent) {
if (dp->dnatype && *dp->dnatype && IS_DNATYPE_INT_COMPAT(dp->dnatype) == 0) {
CLOG_ERROR(&LOG,
"%s.%s is a '%s' but wrapped as type '%s'.",
@@ -2338,7 +2364,7 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
}
@@ -2470,13 +2496,13 @@ void RNA_def_property_float_sdna(PropertyRNA *prop, const char *structname, cons
if (prop->type != PROP_FLOAT) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
if ((dp = rna_def_property_sdna(prop, structname, propname))) {
/* silent is for internal use */
- if (DefRNA.silent == 0) {
+ if (!DefRNA.silent) {
if (dp->dnatype && *dp->dnatype && IS_DNATYPE_FLOAT_COMPAT(dp->dnatype) == 0) {
/* Colors are an exception. these get translated. */
if (prop->subtype != PROP_COLOR_GAMMA) {
@@ -2486,7 +2512,7 @@ void RNA_def_property_float_sdna(PropertyRNA *prop, const char *structname, cons
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
}
@@ -2578,7 +2604,7 @@ void RNA_def_property_enum_sdna(PropertyRNA *prop, const char *structname, const
if (prop->type != PROP_ENUM) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not enum.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -2589,7 +2615,7 @@ void RNA_def_property_enum_sdna(PropertyRNA *prop, const char *structname, const
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "\"%s.%s\", array not supported for enum type.", structname, propname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
@@ -2672,7 +2698,7 @@ void RNA_def_property_string_sdna(PropertyRNA *prop, const char *structname, con
if (prop->type != PROP_STRING) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -2716,7 +2742,7 @@ void RNA_def_property_pointer_sdna(PropertyRNA *prop, const char *structname, co
if (prop->type != PROP_POINTER) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not pointer.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -2727,7 +2753,7 @@ void RNA_def_property_pointer_sdna(PropertyRNA *prop, const char *structname, co
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "\"%s.%s\", array not supported for pointer type.", structname, propname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
}
@@ -2749,7 +2775,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop,
if (prop->type != PROP_COLLECTION) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not collection.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -2760,7 +2786,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop,
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "\"%s.%s\", array of collections not supported.", structname, propname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
@@ -2806,7 +2832,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop,
else {
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "\"%s.%s\" not found.", structname, lengthpropname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
}
@@ -2904,7 +2930,7 @@ void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getleng
if (!(prop->flag & PROP_DYNAMIC)) {
CLOG_ERROR(&LOG, "property is a not dynamic array.");
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -2946,7 +2972,7 @@ void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const ch
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3036,7 +3062,7 @@ void RNA_def_property_int_funcs(PropertyRNA *prop,
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3134,7 +3160,7 @@ void RNA_def_property_float_funcs(PropertyRNA *prop,
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3222,7 +3248,7 @@ void RNA_def_property_enum_funcs(PropertyRNA *prop,
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not enum.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3289,7 +3315,7 @@ void RNA_def_property_string_funcs(PropertyRNA *prop,
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3351,7 +3377,7 @@ void RNA_def_property_pointer_funcs(
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not pointer.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3405,7 +3431,7 @@ void RNA_def_property_collection_funcs(PropertyRNA *prop,
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not collection.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -4170,7 +4196,7 @@ static FunctionRNA *rna_def_function(StructRNA *srna, const char *identifier)
if (rna_validate_identifier(identifier, error, false) == 0) {
CLOG_ERROR(&LOG, "function identifier \"%s\" - %s", identifier, error);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 9fceafd8374..e49186f4cb1 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -579,7 +579,7 @@ static void rna_FCurve_group_set(PointerRNA *ptr,
/* calculate time extents of F-Curve */
static void rna_FCurve_range(FCurve *fcu, float range[2])
{
- calc_fcurve_range(fcu, range, range + 1, false, false);
+ BKE_fcurve_calc_range(fcu, range, range + 1, false, false);
}
static bool rna_FCurve_is_empty_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c
index 93c7c1f3480..94ba09b2bb8 100644
--- a/source/blender/makesrna/intern/rna_fluid.c
+++ b/source/blender/makesrna/intern/rna_fluid.c
@@ -227,8 +227,11 @@ static void rna_Fluid_flip_parts_update(Main *bmain, Scene *scene, PointerRNA *p
mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid);
bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_FLIP);
- /* Only create a particle system in liquid domain mode. */
+ /* Only create a particle system in liquid domain mode.
+ * Remove any remaining data from a liquid sim when switching to gas. */
if (mmd->domain->type != FLUID_DOMAIN_TYPE_LIQUID) {
+ rna_Fluid_parts_delete(ptr, PART_FLUID_FLIP);
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FLIP;
rna_Fluid_domain_reset(bmain, scene, ptr);
return;
}
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 5f1ff0d8745..a52811a9a9a 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -121,7 +121,7 @@ static const EnumPropertyItem rna_enum_layer_blend_modes_items[] = {
{eGplBlendMode_Divide, "DIVIDE", 0, "Divide", ""},
{0, NULL, 0, NULL, NULL}};
-static EnumPropertyItem rna_enum_gpencil_caps_modes_items[] = {
+static const EnumPropertyItem rna_enum_gpencil_caps_modes_items[] = {
{GP_STROKE_CAP_ROUND, "ROUND", 0, "Rounded", ""},
{GP_STROKE_CAP_FLAT, "FLAT", 0, "Flat", ""},
{0, NULL, 0, NULL, NULL},
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index cb59eee6afa..44f118a8744 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -118,7 +118,14 @@ typedef struct BlenderDefRNA {
ListBase structs;
ListBase allocs;
struct StructRNA *laststruct;
- int error, silent, preprocess, verify, animate;
+ bool error;
+ bool silent;
+ bool preprocess;
+ bool verify;
+ bool animate;
+ /** Whether RNA properties defined should be overridable or not by default. */
+ bool make_overridable;
+
/* Keep last. */
#ifndef RNA_RUNTIME
struct {
diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c
index c19dafb3bc6..2caf315e09e 100644
--- a/source/blender/makesrna/intern/rna_light.c
+++ b/source/blender/makesrna/intern/rna_light.c
@@ -186,25 +186,45 @@ static void rna_def_light(BlenderRNA *brna)
rna_def_animdata_common(srna);
}
-static void rna_def_light_energy(StructRNA *srna, bool distant)
+static void rna_def_light_energy(StructRNA *srna, const short light_type)
{
PropertyRNA *prop;
- if (distant) {
- /* Distant light strength has no unit defined, it's proportional to
- * Watt/m^2 and is not sensitive to scene unit scale. */
- prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Strength", "Amount of light emitted");
- RNA_def_property_update(prop, 0, "rna_Light_draw_update");
- }
- else {
- /* Lights with a location have power in Watt, which is sensitive to
- * scene unit scale. */
- prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER);
- RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5);
- RNA_def_property_ui_text(prop, "Power", "Amount of light emitted");
- RNA_def_property_update(prop, 0, "rna_Light_draw_update");
+ switch (light_type) {
+ case LA_SUN: {
+ /* Distant light strength has no unit defined,
+ * it's proportional to 'watt/m^2' and is not sensitive to scene unit scale. */
+ prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
+ RNA_def_property_ui_text(
+ prop, "Strength", "Sunlight strength in watts per meter squared (W/m^2)");
+ RNA_def_property_update(prop, 0, "rna_Light_draw_update");
+ break;
+ }
+ case LA_SPOT: {
+ /* Lights with a location have power in Watts,
+ * which is sensitive to scene unit scale. */
+ prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER);
+ RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5);
+ RNA_def_property_ui_text(prop,
+ "Power",
+ "The energy this light would emit over its entire area "
+ "if it wasn't limited by the spot angle");
+ RNA_def_property_update(prop, 0, "rna_Light_draw_update");
+ break;
+ }
+ default: {
+ /* Lights with a location have power in Watts,
+ * which is sensitive to scene unit scale. */
+ prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER);
+ RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5);
+ RNA_def_property_ui_text(
+ prop,
+ "Power",
+ "Light energy emitted over the entire area of the light in all directions");
+ RNA_def_property_update(prop, 0, "rna_Light_draw_update");
+ break;
+ }
}
}
@@ -395,7 +415,7 @@ static void rna_def_point_light(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Point Light", "Omnidirectional point Light");
RNA_def_struct_ui_icon(srna, ICON_LIGHT_POINT);
- rna_def_light_energy(srna, false);
+ rna_def_light_energy(srna, LA_LOCAL);
rna_def_light_falloff(srna);
rna_def_light_shadow(srna, false);
}
@@ -418,7 +438,7 @@ static void rna_def_area_light(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Area Light", "Directional area Light");
RNA_def_struct_ui_icon(srna, ICON_LIGHT_AREA);
- rna_def_light_energy(srna, false);
+ rna_def_light_energy(srna, LA_AREA);
rna_def_light_shadow(srna, false);
rna_def_light_falloff(srna);
@@ -457,7 +477,7 @@ static void rna_def_spot_light(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Spot Light", "Directional cone Light");
RNA_def_struct_ui_icon(srna, ICON_LIGHT_SPOT);
- rna_def_light_energy(srna, false);
+ rna_def_light_energy(srna, LA_SPOT);
rna_def_light_falloff(srna);
rna_def_light_shadow(srna, false);
@@ -503,7 +523,7 @@ static void rna_def_sun_light(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Angle", "Angular diameter of the Sun as seen from the Earth");
RNA_def_property_update(prop, 0, "rna_Light_update");
- rna_def_light_energy(srna, true);
+ rna_def_light_energy(srna, LA_SUN);
rna_def_light_shadow(srna, true);
}
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 2e97f97375d..e9b8595ce3c 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1682,6 +1682,8 @@ static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const c
PropertyRNA *prop;
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "uv_smooth", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "uv_smooth");
RNA_def_property_enum_items(prop, prop_uv_smooth_items);
@@ -1702,6 +1704,8 @@ static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const c
RNA_def_property_ui_text(prop, "Subdivision Type", "Select type of subdivision algorithm");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
return prop;
}
@@ -1717,6 +1721,8 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna)
rna_def_property_subdivision_common(srna, "subdivType");
+ RNA_define_lib_overridable(true);
+
/* see CCGSUBSURF_LEVEL_MAX for max limit */
prop = RNA_def_property(srna, "levels", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "levels");
@@ -1743,6 +1749,8 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Use Creases", "Use mesh edge crease information to sharpen edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_generic_map_info(StructRNA *srna)
@@ -1769,10 +1777,11 @@ static void rna_def_modifier_generic_map_info(StructRNA *srna)
PropertyRNA *prop;
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Texture", "");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "texture_coords", PROP_ENUM, PROP_NONE);
@@ -1792,13 +1801,14 @@ static void rna_def_modifier_generic_map_info(StructRNA *srna)
RNA_def_property_ui_text(
prop, "Texture Coordinate Object", "Object to set the texture coordinates");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "texture_coords_bone", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "map_bone");
RNA_def_property_ui_text(prop, "Texture Coordinate Bone", "Bone to set the texture coordinates");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_warp(BlenderRNA *brna)
@@ -1811,11 +1821,12 @@ static void rna_def_modifier_warp(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WarpModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_WARP);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object_from", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "object_from");
RNA_def_property_ui_text(prop, "Object From", "Object to transform from");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "bone_from", PROP_STRING, PROP_NONE);
@@ -1827,7 +1838,6 @@ static void rna_def_modifier_warp(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "object_to");
RNA_def_property_ui_text(prop, "Object To", "Object to transform to");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "bone_to", PROP_STRING, PROP_NONE);
@@ -1872,6 +1882,8 @@ static void rna_def_modifier_warp(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
rna_def_modifier_generic_map_info(srna);
}
@@ -1885,6 +1897,8 @@ static void rna_def_modifier_multires(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MultiresModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MULTIRES);
+ RNA_define_lib_overridable(true);
+
prop = rna_def_property_subdivision_common(srna, "simple");
RNA_def_property_enum_funcs(prop, NULL, "rna_MultiresModifier_type_set", NULL);
@@ -1936,6 +1950,8 @@ static void rna_def_modifier_multires(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Use Creases", "Use mesh edge crease information to sharpen edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_lattice(BlenderRNA *brna)
@@ -1948,12 +1964,13 @@ static void rna_def_modifier_lattice(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "LatticeModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_LATTICE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Lattice object to deform with");
RNA_def_property_pointer_funcs(
prop, NULL, "rna_LatticeModifier_object_set", NULL, "rna_Lattice_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
@@ -1975,6 +1992,8 @@ static void rna_def_modifier_lattice(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0, 1, 10, 2);
RNA_def_property_ui_text(prop, "Strength", "Strength of modifier effect");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_curve(BlenderRNA *brna)
@@ -1997,12 +2016,13 @@ static void rna_def_modifier_curve(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "CurveModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_CURVE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Curve object to deform with");
RNA_def_property_pointer_funcs(
prop, NULL, "rna_CurveModifier_object_set", NULL, "rna_Curve_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_CurveModifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
@@ -2024,6 +2044,8 @@ static void rna_def_modifier_curve(BlenderRNA *brna)
RNA_def_property_enum_items(prop, prop_deform_axis_items);
RNA_def_property_ui_text(prop, "Deform Axis", "The axis that the curve deforms along");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_build(BlenderRNA *brna)
@@ -2036,6 +2058,8 @@ static void rna_def_modifier_build(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "BuildModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_BUILD);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "start");
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
@@ -2062,6 +2086,8 @@ static void rna_def_modifier_build(BlenderRNA *brna)
RNA_def_property_range(prop, 1, MAXFRAMEF);
RNA_def_property_ui_text(prop, "Seed", "Seed for random if used");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_mirror(BlenderRNA *brna)
@@ -2074,6 +2100,8 @@ static void rna_def_modifier_mirror(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MirrorModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MIRROR);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_axis", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MIR_AXIS_X);
RNA_def_property_array(prop, 3);
@@ -2172,8 +2200,9 @@ static void rna_def_modifier_mirror(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "mirror_ob");
RNA_def_property_ui_text(prop, "Mirror Object", "Object to use as mirror");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_decimate(BlenderRNA *brna)
@@ -2199,6 +2228,8 @@ static void rna_def_modifier_decimate(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "DecimateModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_DECIM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "decimate_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, modifier_decim_mode_items);
@@ -2287,6 +2318,8 @@ static void rna_def_modifier_decimate(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(
prop, "Face Count", "The current number of faces in the decimated mesh");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_wave(BlenderRNA *brna)
@@ -2299,6 +2332,8 @@ static void rna_def_modifier_wave(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WaveModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_WAVE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WAVE_X);
RNA_def_property_ui_text(prop, "X", "X axis motion");
@@ -2382,7 +2417,6 @@ static void rna_def_modifier_wave(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "objectcenter");
RNA_def_property_ui_text(prop, "Start Position Object", "Object which defines the wave center");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
@@ -2426,6 +2460,8 @@ static void rna_def_modifier_wave(BlenderRNA *brna)
"the more narrow the wave");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
rna_def_modifier_generic_map_info(srna);
}
@@ -2439,12 +2475,13 @@ static void rna_def_modifier_armature(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ArmatureModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_ARMATURE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Armature object to deform with");
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ArmatureModifier_object_set", NULL, "rna_Armature_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "use_bone_envelopes", PROP_BOOLEAN, PROP_NONE);
@@ -2486,6 +2523,8 @@ static void rna_def_modifier_armature(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "deformflag", ARM_DEF_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_hook(BlenderRNA *brna)
@@ -2501,6 +2540,8 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "HookModifierData");
RNA_def_struct_ui_icon(srna, ICON_HOOK);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "force");
RNA_def_property_range(prop, 0, 1);
@@ -2543,7 +2584,6 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Object", "Parent Object for hook, also recalculates and clears offset");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_override_funcs(prop, NULL, NULL, "rna_HookModifier_object_override_apply");
RNA_def_property_pointer_funcs(prop, NULL, "rna_HookModifier_object_set", NULL, NULL);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
@@ -2595,6 +2635,8 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_HOOK_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_softbody(BlenderRNA *brna)
@@ -2645,12 +2687,13 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "BooleanModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_BOOLEAN);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Mesh object to use for Boolean operation");
RNA_def_property_pointer_funcs(
prop, NULL, "rna_BooleanModifier_object_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE);
@@ -2687,6 +2730,8 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
RNA_def_property_ui_text(prop, "Debug", "Debugging options, only when started with '-d'");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_array(BlenderRNA *brna)
@@ -2714,6 +2759,8 @@ static void rna_def_modifier_array(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ArrayModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_ARRAY);
+ RNA_define_lib_overridable(true);
+
/* Length parameters */
prop = RNA_def_property(srna, "fit_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_fit_type_items);
@@ -2739,7 +2786,6 @@ static void rna_def_modifier_array(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ArrayModifier_curve_ob_set", NULL, "rna_Curve_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_ArrayModifier_dependency_update");
/* Offset parameters */
@@ -2804,7 +2850,6 @@ static void rna_def_modifier_array(BlenderRNA *brna)
"Use the location and rotation of another object to determine the distance and "
"rotational change between arrayed items");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
/* Caps */
@@ -2813,15 +2858,13 @@ static void rna_def_modifier_array(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ArrayModifier_start_cap_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "end_cap", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "End Cap", "Mesh object to use as an end cap");
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ArrayModifier_end_cap_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "offset_u", PROP_FLOAT, PROP_FACTOR);
@@ -2837,6 +2880,8 @@ static void rna_def_modifier_array(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -1, 1, 2, 4);
RNA_def_property_ui_text(prop, "V Offset", "Amount to offset array UVs on the V axis");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_edgesplit(BlenderRNA *brna)
@@ -2850,6 +2895,8 @@ static void rna_def_modifier_edgesplit(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "EdgeSplitModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_EDGESPLIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "split_angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 2);
@@ -2865,6 +2912,8 @@ static void rna_def_modifier_edgesplit(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_EDGESPLIT_FROMFLAG);
RNA_def_property_ui_text(prop, "Use Sharp Edges", "Split edges that are marked as sharp");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_displace(BlenderRNA *brna)
@@ -2918,6 +2967,8 @@ static void rna_def_modifier_displace(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "DisplaceModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_DISPLACE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
RNA_def_property_ui_text(
@@ -2955,6 +3006,8 @@ static void rna_def_modifier_displace(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
rna_def_modifier_generic_map_info(srna);
}
@@ -2969,6 +3022,8 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "UVProjectModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_UVPROJECT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "uvlayer_name");
RNA_def_property_ui_text(prop, "UV Map", "UV map name");
@@ -3035,9 +3090,10 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, "rna_UVProjector_object_get", "rna_UVProjector_object_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Object", "Object to use as projector transform");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_smooth(BlenderRNA *brna)
@@ -3050,6 +3106,8 @@ static void rna_def_modifier_smooth(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SmoothModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SMOOTH_X);
RNA_def_property_ui_text(prop, "X", "Smooth object along X axis");
@@ -3091,6 +3149,8 @@ static void rna_def_modifier_smooth(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SMOOTH_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_correctivesmooth(BlenderRNA *brna)
@@ -3132,6 +3192,8 @@ static void rna_def_modifier_correctivesmooth(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "CorrectiveSmoothModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "lambda");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
@@ -3195,6 +3257,8 @@ static void rna_def_modifier_correctivesmooth(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Pin Boundaries", "Excludes boundary vertices from being smoothed");
RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna)
@@ -3207,6 +3271,8 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "LaplacianSmoothModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_X);
RNA_def_property_ui_text(prop, "X", "Smooth object along X axis");
@@ -3265,6 +3331,8 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_cast(BlenderRNA *brna)
@@ -3284,6 +3352,8 @@ static void rna_def_modifier_cast(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "CastModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_CAST);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "cast_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, prop_cast_type_items);
@@ -3297,7 +3367,6 @@ static void rna_def_modifier_cast(BlenderRNA *brna)
"Control object: if available, its location determines the center of the effect");
RNA_def_property_pointer_funcs(prop, NULL, "rna_CastModifier_object_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE);
@@ -3360,6 +3429,8 @@ static void rna_def_modifier_cast(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name");
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_CastModifier_defgrp_name_set");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_meshdeform(BlenderRNA *brna)
@@ -3380,12 +3451,13 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MeshDeformModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Mesh object to deform with");
RNA_def_property_pointer_funcs(
prop, NULL, "rna_MeshDeformModifier_object_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "is_bound", PROP_BOOLEAN, PROP_NONE);
@@ -3424,6 +3496,8 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Mode", "Method of binding vertices are bound to cage mesh");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
# endif
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_particlesystem(BlenderRNA *brna)
@@ -3436,10 +3510,14 @@ static void rna_def_modifier_particlesystem(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ParticleSystemModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_PARTICLES);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "psys");
RNA_def_property_ui_text(prop, "Particle System", "Particle System that this modifier controls");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_particleinstance(BlenderRNA *brna)
@@ -3466,12 +3544,13 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ParticleInstanceModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_PARTICLES);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
RNA_def_property_ui_text(prop, "Object", "Object that has the particle system");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "particle_system_index", PROP_INT, PROP_NONE);
@@ -3593,6 +3672,8 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Value Layer Name", "Custom data layer name for the randomized value");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_explode(BlenderRNA *brna)
@@ -3606,6 +3687,8 @@ static void rna_def_modifier_explode(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ExplodeModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_EXPLODE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop,
"rna_ExplodeModifier_vgroup_get",
@@ -3653,6 +3736,8 @@ static void rna_def_modifier_explode(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", eExplodeFlag_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_cloth(BlenderRNA *brna)
@@ -3665,6 +3750,8 @@ static void rna_def_modifier_cloth(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ClothModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_CLOTH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "sim_parms");
@@ -3698,6 +3785,8 @@ static void rna_def_modifier_cloth(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "hair_grid_res");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Hair Grid Resolution", "");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_fluid(BlenderRNA *brna)
@@ -3718,6 +3807,8 @@ static void rna_def_modifier_fluid(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "FluidModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_FLUIDSIM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "domain_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "domain");
RNA_def_property_ui_text(prop, "Domain Settings", "");
@@ -3736,6 +3827,8 @@ static void rna_def_modifier_fluid(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Type", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, 0, "rna_fluid_set_type");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_dynamic_paint(BlenderRNA *brna)
@@ -3748,6 +3841,8 @@ static void rna_def_modifier_dynamic_paint(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "DynamicPaintModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_DYNAMICPAINT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "canvas_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "canvas");
RNA_def_property_ui_text(prop, "Canvas Settings", "");
@@ -3761,6 +3856,8 @@ static void rna_def_modifier_dynamic_paint(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, rna_enum_prop_dynamicpaint_type_items);
RNA_def_property_ui_text(prop, "Type", "");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_collision(BlenderRNA *brna)
@@ -3775,11 +3872,15 @@ static void rna_def_modifier_collision(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "CollisionModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_PHYSICS);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "CollisionSettings");
RNA_def_property_pointer_funcs(prop, "rna_CollisionModifier_settings_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Settings", "");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_bevel(BlenderRNA *brna)
@@ -3870,6 +3971,8 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "BevelModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_BEVEL);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "width", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "value");
RNA_def_property_range(prop, 0, FLT_MAX);
@@ -4008,6 +4111,8 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Vertex Mesh Method", "The method to use to create the mesh at intersections");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
@@ -4062,6 +4167,8 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ShrinkwrapModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SHRINKWRAP);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "wrap_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "shrinkType");
RNA_def_property_enum_items(prop, shrink_type_items);
@@ -4091,7 +4198,6 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ShrinkwrapModifier_target_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "auxiliary_target", PROP_POINTER, PROP_NONE);
@@ -4100,7 +4206,6 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ShrinkwrapModifier_auxTarget_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
@@ -4172,6 +4277,8 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "shrinkOpts", MOD_SHRINKWRAP_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_mask(BlenderRNA *brna)
@@ -4190,6 +4297,8 @@ static void rna_def_modifier_mask(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MaskModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MASK);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, modifier_mask_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
@@ -4201,7 +4310,6 @@ static void rna_def_modifier_mask(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_MaskModifier_ob_arm_set", NULL, "rna_Armature_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
@@ -4221,6 +4329,8 @@ static void rna_def_modifier_mask(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
RNA_def_property_ui_text(prop, "Threshold", "Weights over this threshold remain");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_simpledeform(BlenderRNA *brna)
@@ -4260,6 +4370,8 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SimpleDeformModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SIMPLEDEFORM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "deform_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, simple_deform_mode_items);
@@ -4280,7 +4392,6 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
prop = RNA_def_property(srna, "origin", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Origin", "Offset the origin and orientation of the deformation");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
@@ -4324,6 +4435,8 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SIMPLEDEFORM_FLAG_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_surface(BlenderRNA *brna)
@@ -4400,6 +4513,8 @@ static void rna_def_modifier_solidify(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SolidifyModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SOLIDIFY);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "solidify_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, mode_items);
@@ -4570,6 +4685,8 @@ static void rna_def_modifier_solidify(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -1.0, 1.0, 0.1, 3);
RNA_def_property_ui_text(prop, "Bevel Convex", "Edge bevel weight to be added to outside edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_screw(BlenderRNA *brna)
@@ -4582,11 +4699,12 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ScrewModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SCREW);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob_axis");
RNA_def_property_ui_text(prop, "Object", "Object to define the screw axis");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "steps", PROP_INT, PROP_UNSIGNED);
@@ -4680,6 +4798,8 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
prop, "Object Angle", "Use the angle between the objects rather than the fixed angle");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
# endif
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_uvwarp(BlenderRNA *brna)
@@ -4692,6 +4812,8 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "UVWarpModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_UVPROJECT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "axis_u", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "axis_u");
RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
@@ -4728,7 +4850,6 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "object_src");
RNA_def_property_ui_text(prop, "Object From", "Object defining offset");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "bone_from", PROP_STRING, PROP_NONE);
@@ -4740,7 +4861,6 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "object_dst");
RNA_def_property_ui_text(prop, "Object To", "Object defining offset");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "bone_to", PROP_STRING, PROP_NONE);
@@ -4764,10 +4884,13 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "UV Layer", "UV Layer name");
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_UVWarpModifier_uvlayer_name_set");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna),
StructRNA *srna,
+ const char *mask_flags,
const char *mask_vgroup_setter,
const char *mask_uvlayer_setter)
{
@@ -4797,6 +4920,8 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna),
PropertyRNA *prop;
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mask_constant", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1);
@@ -4810,10 +4935,14 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna),
RNA_def_property_string_funcs(prop, NULL, NULL, mask_vgroup_setter);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, mask_flags, MOD_WVG_EDIT_INVERT_VGROUP_MASK);
+ RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "mask_texture", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Masking Tex", "Masking texture");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "mask_tex_use_channel", PROP_ENUM, PROP_NONE);
@@ -4842,7 +4971,6 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna),
"Which object to take texture "
"coordinates from");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "mask_tex_map_bone", PROP_STRING, PROP_NONE);
@@ -4850,6 +4978,8 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna),
RNA_def_property_ui_text(
prop, "Texture Coordinate Bone", "Which bone to take texture coordinates from");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_weightvgedit(BlenderRNA *brna)
@@ -4879,6 +5009,8 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WeightVGEditModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name");
@@ -4896,6 +5028,14 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert Falloff", "Invert the resulting falloff weight");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "normalize", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_WEIGHTS_NORMALIZE);
+ RNA_def_property_ui_text(
+ prop,
+ "Normalize Weights",
+ "Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "map_curve", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "cmap_curve");
RNA_def_property_ui_text(prop, "Mapping Curve", "Custom mapping curve");
@@ -4946,16 +5086,14 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna)
"to be removed from the vgroup");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
/* Common masking properties. */
rna_def_modifier_weightvg_mask(brna,
srna,
+ "edit_flags",
"rna_WeightVGEditModifier_mask_defgrp_name_set",
"rna_WeightVGEditModifier_mask_tex_uvlayer_name_set");
-
- prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_INVERT_VGROUP_MASK);
- RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_weightvgmix(BlenderRNA *brna)
@@ -5000,6 +5138,8 @@ static void rna_def_modifier_weightvgmix(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WeightVGMixModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group_a", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "defgrp_name_a");
RNA_def_property_ui_text(prop, "Vertex Group A", "First vertex group name");
@@ -5012,6 +5152,16 @@ static void rna_def_modifier_weightvgmix(BlenderRNA *brna)
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightVGMixModifier_defgrp_name_b_set");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "invert_vertex_group_a", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WVG_MIX_INVERT_VGROUP_A);
+ RNA_def_property_ui_text(prop, "Invert Weights A", "Invert the influence of vertex group A");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex_group_b", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WVG_MIX_INVERT_VGROUP_B);
+ RNA_def_property_ui_text(prop, "Invert Weights B", "Invert the influence of vertex group B");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "default_weight_a", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0, 1.0f);
RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1);
@@ -5043,16 +5193,22 @@ static void rna_def_modifier_weightvgmix(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vertex Set", "Which vertices should be affected");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "normalize", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WVG_MIX_WEIGHTS_NORMALIZE);
+ RNA_def_property_ui_text(
+ prop,
+ "Normalize Weights",
+ "Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
+
/* Common masking properties. */
rna_def_modifier_weightvg_mask(brna,
srna,
+ "flag",
"rna_WeightVGMixModifier_mask_defgrp_name_set",
"rna_WeightVGMixModifier_mask_tex_uvlayer_name_set");
-
- prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WVG_MIX_INVERT_VGROUP_MASK);
- RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
@@ -5106,6 +5262,8 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WeightVGProximityModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name");
@@ -5133,7 +5291,6 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "proximity_ob_target");
RNA_def_property_ui_text(prop, "Target Object", "Object to calculate vertices distances from");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "min_dist", PROP_FLOAT, PROP_DISTANCE);
@@ -5159,17 +5316,23 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert Falloff", "Invert the resulting falloff weight");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "normalize", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(
+ prop, NULL, "proximity_flags", MOD_WVG_PROXIMITY_WEIGHTS_NORMALIZE);
+ RNA_def_property_ui_text(
+ prop,
+ "Normalize Weights",
+ "Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
+
/* Common masking properties. */
rna_def_modifier_weightvg_mask(brna,
srna,
+ "proximity_flags",
"rna_WeightVGProximityModifier_mask_defgrp_name_set",
"rna_WeightVGProximityModifier_mask_tex_uvlayer_name_set");
-
- prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(
- prop, NULL, "proximity_flags", MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK);
- RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_remesh(BlenderRNA *brna)
@@ -5205,6 +5368,8 @@ static void rna_def_modifier_remesh(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "RemeshModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_REMESH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
@@ -5273,6 +5438,8 @@ static void rna_def_modifier_remesh(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Smooth Shading", "Output faces with smooth shading rather than flat shaded");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_ocean(BlenderRNA *brna)
@@ -5330,6 +5497,8 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "OceanModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_OCEAN);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "geometry_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "geometry_mode");
RNA_def_property_enum_items(prop, geometry_items);
@@ -5523,6 +5692,8 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Cache Path", "Path to a folder to store external baked images");
/*RNA_def_property_update(prop, 0, "rna_Modifier_update"); */
/* XXX how to update? */
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_skin(BlenderRNA *brna)
@@ -5535,6 +5706,8 @@ static void rna_def_modifier_skin(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SkinModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SKIN);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "branch_smoothing", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_ui_text(prop, "Branch Smoothing", "Smooth complex geometry around branches");
RNA_def_property_ui_range(prop, 0, 1, 1, -1);
@@ -5560,6 +5733,8 @@ static void rna_def_modifier_skin(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "symmetry_axes", MOD_SKIN_SYMM_Z);
RNA_def_property_ui_text(prop, "Z", "Avoid making unsymmetrical quads across the Z axis");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_triangulate(BlenderRNA *brna)
@@ -5572,6 +5747,8 @@ static void rna_def_modifier_triangulate(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "TriangulateModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_TRIANGULATE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "quad_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "quad_method");
RNA_def_property_enum_items(prop, rna_enum_modifier_triangulate_quad_method_items);
@@ -5602,6 +5779,8 @@ static void rna_def_modifier_triangulate(BlenderRNA *brna)
"Try to preserve custom normals (WARNING: depending on chosen triangulation method, "
"shading may not be fully preserved, 'Fixed' method usually gives the best result here)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_meshcache(BlenderRNA *brna)
@@ -5668,6 +5847,8 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MeshCacheModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "cache_format", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, prop_format_type_items);
@@ -5762,6 +5943,8 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Evaluation Factor", "Evaluation time in seconds");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_meshseqcache(BlenderRNA *brna)
@@ -5774,12 +5957,13 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MeshSeqCacheModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "cache_file", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "cache_file");
RNA_def_property_struct_type(prop, "CacheFile");
RNA_def_property_ui_text(prop, "Cache File", "");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "object_path", PROP_STRING, PROP_NONE);
@@ -5804,6 +5988,8 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Read Data", "Data to read from the cache");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_laplaciandeform(BlenderRNA *brna)
@@ -5816,6 +6002,8 @@ static void rna_def_modifier_laplaciandeform(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "LaplacianDeformModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "anchor_grp_name");
RNA_def_property_ui_text(
@@ -5839,6 +6027,8 @@ static void rna_def_modifier_laplaciandeform(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
@@ -5852,6 +6042,8 @@ static void rna_def_modifier_weld(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WeldModifierData");
RNA_def_struct_ui_icon(srna, ICON_AUTOMERGE_OFF);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "merge_threshold", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "merge_dist");
RNA_def_property_range(prop, 0, FLT_MAX);
@@ -5879,6 +6071,8 @@ static void rna_def_modifier_weld(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WELD_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_wireframe(BlenderRNA *brna)
@@ -5891,6 +6085,8 @@ static void rna_def_modifier_wireframe(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WireframeModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_WIREFRAME);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "thickness", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "offset");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
@@ -5962,6 +6158,8 @@ static void rna_def_modifier_wireframe(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WIREFRAME_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_datatransfer(BlenderRNA *brna)
@@ -6019,11 +6217,12 @@ static void rna_def_modifier_datatransfer(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "DataTransferModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_DATA_TRANSFER);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob_source");
RNA_def_property_ui_text(prop, "Source Object", "Object to transfer data from");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_pointer_funcs(
prop, NULL, "rna_DataTransferModifier_ob_source_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
@@ -6319,6 +6518,8 @@ static void rna_def_modifier_datatransfer(BlenderRNA *brna)
srna, "invert_vertex_group", false, "Invert", "Invert vertex group influence");
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_INVERT_VGROUP);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_normaledit(BlenderRNA *brna)
@@ -6358,6 +6559,8 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "NormalEditModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_NORMALEDIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_mode_items);
RNA_def_property_ui_text(prop, "Mode", "How to affect (generate) normals");
@@ -6429,7 +6632,6 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Target", "Target object used to affect normals");
RNA_def_property_pointer_funcs(prop, NULL, "rna_NormalEditModifier_target_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "use_direction_parallel", PROP_BOOLEAN, PROP_NONE);
@@ -6440,6 +6642,8 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna)
"Use same direction for all normals, from origin to target's center "
"(Directional mode only)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_surfacedeform(BlenderRNA *brna)
@@ -6452,12 +6656,13 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SurfaceDeformModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Target", "Mesh object to deform with");
RNA_def_property_pointer_funcs(
prop, NULL, "rna_SurfaceDeformModifier_target_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE);
@@ -6488,6 +6693,8 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -100, 100, 10, 2);
RNA_def_property_ui_text(prop, "Strength", "Strength of modifier deformations");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_weightednormal(BlenderRNA *brna)
@@ -6519,6 +6726,8 @@ static void rna_def_modifier_weightednormal(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WeightedNormalModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_NORMALEDIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "weight", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 1, 100);
RNA_def_property_ui_range(prop, 1, 100, 1, -1);
@@ -6565,6 +6774,8 @@ static void rna_def_modifier_weightednormal(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WEIGHTEDNORMAL_FACE_INFLUENCE);
RNA_def_property_ui_text(prop, "Face Influence", "Use influence of face for weighting");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_simulation_access(BlenderRNA *brna)
@@ -6577,6 +6788,8 @@ static void rna_def_modifier_simulation_access(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SimulationModifierData");
RNA_def_struct_ui_icon(srna, ICON_PHYSICS); /* TODO: Use correct icon. */
+ RNA_define_lib_overridable(true);
+
# ifdef WITH_NEW_SIMULATION_TYPE
prop = RNA_def_property(srna, "simulation", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Simulation", "Simulation to access");
@@ -6588,6 +6801,8 @@ static void rna_def_modifier_simulation_access(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Data Path", "Identifier of the simulation component that should be accessed");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
void RNA_def_modifier(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 230d62d2a23..b0dda1237b0 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -382,7 +382,7 @@ static FCurve *rna_NlaStrip_fcurve_find(NlaStrip *strip,
}
/* Returns NULL if not found. */
- return list_find_fcurve(&strip->fcurves, data_path, index);
+ return BKE_fcurve_find(&strip->fcurves, data_path, index);
}
static NlaStrip *rna_NlaStrip_new(ID *id,
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index a27d77df32a..79a9e0be051 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1471,7 +1471,7 @@ static void rna_Object_constraints_remove(Object *object,
RNA_POINTER_INVALIDATE(con_ptr);
ED_object_constraint_update(bmain, object);
- ED_object_constraint_set_active(object, NULL);
+ ED_object_constraint_active_set(object, NULL);
WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, object);
}
@@ -1480,7 +1480,7 @@ static void rna_Object_constraints_clear(Object *object, Main *bmain)
BKE_constraints_free(&object->constraints);
ED_object_constraint_update(bmain, object);
- ED_object_constraint_set_active(object, NULL);
+ ED_object_constraint_active_set(object, NULL);
WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, object);
}
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 2c9bdd31141..3b80714bcc5 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -41,6 +41,8 @@
#include "DEG_depsgraph.h"
+#include "ED_outliner.h"
+
#include "rna_internal.h" /* own include */
static const EnumPropertyItem space_items[] = {
@@ -114,6 +116,7 @@ static void rna_Object_select_set(
Scene *scene = CTX_data_scene(C);
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
+ ED_outliner_select_sync_from_object_tag(C);
}
static bool rna_Object_select_get(Object *ob, bContext *C, ViewLayer *view_layer)
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 6c21e4ad01b..6af031eb7b0 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -131,7 +131,7 @@ static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE);
GPU_shader_bind(shader);
- int img_loc = GPU_shader_get_uniform_ensure(shader, "image");
+ int img_loc = GPU_shader_get_uniform(shader, "image");
GPU_shader_uniform_int(shader, img_loc, 0);
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index e3d779ce7fb..7e9753b090a 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2198,12 +2198,12 @@ static void rna_Scene_update_active_object_data(bContext *C, PointerRNA *UNUSED(
}
}
-static void rna_SceneCamera_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_SceneCamera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->owner_id;
Object *camera = scene->camera;
- BKE_sequence_invalidate_scene_strips(bmain, scene);
+ BKE_sequencer_cache_cleanup(scene);
if (camera && (camera->type == OB_CAMERA)) {
DEG_id_tag_update(&camera->id, ID_RECALC_GEOMETRY);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index e770b669ca2..1d03b16d5bb 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -160,7 +160,7 @@ static void rna_Scene_ray_cast(Scene *scene,
normalize_v3(direction);
Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true);
- SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, 0);
+ SnapObjectContext *sctx = ED_transform_snap_object_context_create(scene, 0);
bool ret = ED_transform_snap_object_project_ray_ex(sctx,
depsgraph,
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index fd8ddfff14f..39ea054456f 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -874,13 +874,6 @@ static void rna_Sequence_reopen_files_update(Main *bmain, Scene *UNUSED(scene),
}
}
-static void rna_Sequence_mute_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- Scene *scene = (Scene *)ptr->owner_id;
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
-}
-
static void rna_Sequence_filepath_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->owner_id;
@@ -1690,7 +1683,7 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_CHECKBOX_HLT, -1);
RNA_def_property_ui_text(
prop, "Mute", "Disable strip so that it cannot be viewed in the output");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_mute_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_LOCK);
@@ -2023,7 +2016,7 @@ static void rna_def_editor(BlenderRNA *brna)
RNA_def_property_ui_text(
prop,
"Prefetch Frames",
- "Render frames ahead of playhead in the background for faster playback");
+ "Render frames ahead of current frame in the background for faster playback");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
prop = RNA_def_property(srna, "recycle_max_cost", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index c719aa99fd8..df0d514fabf 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -483,6 +483,13 @@ const EnumPropertyItem rna_enum_file_sort_items[] = {
{0, NULL, 0, NULL, NULL},
};
+static const EnumPropertyItem rna_enum_curve_display_handle_items[] = {
+ {CURVE_HANDLE_NONE, "NONE", 0, "None", ""},
+ {CURVE_HANDLE_SELECTED, "SELECTED", 0, "Selected", ""},
+ {CURVE_HANDLE_ALL, "ALL", 0, "All", ""},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
# include "DNA_anim_types.h"
@@ -3817,9 +3824,11 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
prop, "Indices", "Display the index numbers of selected vertices, edges, and faces");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- prop = RNA_def_property(srna, "show_curve_handles", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_CU_HANDLES);
- RNA_def_property_ui_text(prop, "Draw Handles", "Display Bezier handles in editmode");
+ prop = RNA_def_property(srna, "display_handle", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "overlay.handle_display");
+ RNA_def_property_enum_items(prop, rna_enum_curve_display_handle_items);
+ RNA_def_property_ui_text(
+ prop, "Display Handles", "Limit the display of curve handles in edit mode");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_curve_normals", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 5db525a9f6f..e47b2b51acf 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -485,6 +485,21 @@ static void rna_uiTemplateAnyID(uiLayout *layout,
uiTemplateAnyID(layout, ptr, propname, proptypename, name);
}
+static void rna_uiTemplateCacheFile(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ uiTemplateCacheFile(layout, C, ptr, propname);
+}
+
static void rna_uiTemplatePathBuilder(uiLayout *layout,
PointerRNA *ptr,
const char *propname,
@@ -1568,7 +1583,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_float_array(
func, "color", 4, node_socket_color_default, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
- func = RNA_def_function(srna, "template_cache_file", "uiTemplateCacheFile");
+ func = RNA_def_function(srna, "template_cache_file", "rna_uiTemplateCacheFile");
RNA_def_function_ui_description(
func, "Item(s). User interface for selecting cache files and their source paths");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index aa138517209..49a0121dadb 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -360,7 +360,7 @@ static void rna_userdef_load_ui_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
static void rna_userdef_anisotropic_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- GPU_set_anisotropic(bmain, U.anisotropic_filter);
+ GPU_set_anisotropic(U.anisotropic_filter);
rna_userdef_update(bmain, scene, ptr);
}
@@ -4716,7 +4716,7 @@ static void rna_def_userdef_view(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_text_antialiasing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "text_render", USER_TEXT_DISABLE_AA);
- RNA_def_property_ui_text(prop, "Text Anti-aliasing", "Draw user interface text anti-aliased");
+ RNA_def_property_ui_text(prop, "Text Anti-Aliasing", "Draw user interface text anti-aliased");
RNA_def_property_update(prop, 0, "rna_userdef_text_update");
prop = RNA_def_property(srna, "text_hinting", PROP_ENUM, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c
index 826d4039c55..742d3da27ac 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo.c
@@ -401,12 +401,14 @@ RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_use_draw_offset_scale, flag, WM_GIZMO_DRAW_OF
RNA_GIZMO_GENERIC_FLAG_NEG_RW_DEF(flag_use_draw_scale, flag, WM_GIZMO_DRAW_OFFSET_SCALE);
RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_hide, flag, WM_GIZMO_HIDDEN);
RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_hide_select, flag, WM_GIZMO_HIDDEN_SELECT);
+RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_hide_keymap, flag, WM_GIZMO_HIDDEN_KEYMAP);
RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_use_grab_cursor, flag, WM_GIZMO_MOVE_CURSOR);
RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_use_select_background, flag, WM_GIZMO_SELECT_BACKGROUND);
RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_use_operator_tool_properties,
flag,
WM_GIZMO_OPERATOR_TOOL_INIT);
RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_use_event_handle_all, flag, WM_GIZMO_EVENT_HANDLE_ALL);
+RNA_GIZMO_GENERIC_FLAG_NEG_RW_DEF(flag_use_tooltip, flag, WM_GIZMO_NO_TOOLTIP);
/* wmGizmo.state */
RNA_GIZMO_FLAG_RO_DEF(state_is_highlight, state, WM_GIZMO_STATE_HIGHLIGHT);
@@ -1202,6 +1204,12 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
prop, "rna_Gizmo_flag_hide_select_get", "rna_Gizmo_flag_hide_select_set");
RNA_def_property_ui_text(prop, "Hide Select", "");
RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
+ /* WM_GIZMO_HIDDEN_KEYMAP */
+ prop = RNA_def_property(srna, "hide_keymap", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(
+ prop, "rna_Gizmo_flag_hide_keymap_get", "rna_Gizmo_flag_hide_keymap_set");
+ RNA_def_property_ui_text(prop, "Hide Keymap", "Ignore the key-map for this gizmo");
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_MOVE_CURSOR */
prop = RNA_def_property(srna, "use_grab_cursor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
@@ -1271,6 +1279,13 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
"do not pass events through to be handled by other keymaps");
RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
+ /* WM_GIZMO_NO_TOOLTIP (negated) */
+ prop = RNA_def_property(srna, "use_tooltip", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(
+ prop, "rna_Gizmo_flag_use_tooltip_get", "rna_Gizmo_flag_use_tooltip_set");
+ RNA_def_property_ui_text(prop, "Use Tooltip", "Use tool-tips when hovering over this gizmo");
+ /* No update needed. */
+
/* wmGizmo.state (readonly) */
/* WM_GIZMO_STATE_HIGHLIGHT */
prop = RNA_def_property(srna, "is_highlight", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c
index 32e348ea72f..5f110189dd6 100644
--- a/source/blender/makesrna/intern/rna_workspace.c
+++ b/source/blender/makesrna/intern/rna_workspace.c
@@ -59,7 +59,7 @@ static void rna_window_update_all(Main *UNUSED(bmain),
void rna_workspace_screens_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
WorkSpace *workspace = (WorkSpace *)ptr->owner_id;
- rna_iterator_listbase_begin(iter, BKE_workspace_layouts_get(workspace), NULL);
+ rna_iterator_listbase_begin(iter, &workspace->layouts, NULL);
}
static PointerRNA rna_workspace_screens_item_get(CollectionPropertyIterator *iter)
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index e4b043279ce..84651f79e8a 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -173,6 +173,11 @@ static void deformVertsEM(ModifierData *md,
ArmatureModifierData *amd = (ArmatureModifierData *)md;
Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */
armature_deform_verts(amd->object,
@@ -252,25 +257,17 @@ static void deformMatrices(ModifierData *md,
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row, *col;
+ uiLayout *col;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
uiItemR(layout, &ptr, "object", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropDecorate(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
col = uiLayoutColumn(layout, true);
uiItemR(col, &ptr, "use_deform_preserve_volume", 0, NULL, ICON_NONE);
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index b05a9021bff..68e12a8bbef 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -841,7 +841,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index b2f73dd082b..76b8985975e 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -277,15 +277,12 @@ static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row, *col;
+ uiLayout *col;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -325,12 +322,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(col, &ptr, "angle_limit", 0, NULL, ICON_NONE);
}
else if (limit_method == MOD_BEVEL_VGROUP) {
- row = uiLayoutRow(col, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropDecorate(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(col, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
}
modifier_panel_end(layout, &ptr);
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 249711fb132..c2412b295ff 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -363,7 +363,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index cb72e574dad..93f97c7c5b8 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -290,7 +290,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index a6137ae2990..6ce3cc52ef2 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -513,10 +513,15 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
}
- if (mesh_src) {
+ if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
BLI_assert(mesh_src->totvert == numVerts);
}
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
if (cmd->type == MOD_CAST_TYPE_CUBOID) {
cuboid_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
}
@@ -531,16 +536,13 @@ static void deformVertsEM(ModifierData *md,
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row;
+ uiLayout *row;
uiLayout *layout = panel->layout;
int toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
PointerRNA cast_object_ptr = RNA_pointer_get(&ptr, "object");
uiLayoutSetPropSep(layout, true);
@@ -557,12 +559,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, &ptr, "size", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "use_radius_as_size", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
uiItemR(layout, &ptr, "object", 0, NULL, ICON_NONE);
if (!RNA_pointer_is_null(&cast_object_ptr)) {
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index fcb6915709a..c7551b1be00 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -270,7 +270,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
- modifier_panel_buttons(C, panel);
uiItemL(layout, IFACE_("Settings are inside the Physics tab"), ICON_NONE);
diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c
index 892fa8a0e12..3d9f59fba24 100644
--- a/source/blender/modifiers/intern/MOD_correctivesmooth.c
+++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c
@@ -767,6 +767,11 @@ static void deformVertsEM(ModifierData *md,
Mesh *mesh_src = MOD_deform_mesh_eval_get(
ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
correctivesmooth_modifier_do(
md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)numVerts, editData);
@@ -777,15 +782,11 @@ static void deformVertsEM(ModifierData *md,
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -794,12 +795,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, &ptr, "scale", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "smooth_type", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropDecorate(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
uiItemR(layout, &ptr, "use_only_smooth", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "use_pin_boundary", 0, NULL, ICON_NONE);
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 72e794bd2e8..491827720f0 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -153,6 +153,11 @@ static void deformVertsEM(ModifierData *md,
{
Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
deformVerts(md, ctx, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
@@ -162,28 +167,18 @@ static void deformVertsEM(ModifierData *md,
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
uiItemR(layout, &ptr, "object", 0, IFACE_("Curve Object"), ICON_NONE);
uiItemR(layout, &ptr, "deform_axis", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
-
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index 4f2fc8ceebb..e9436147649 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -251,12 +251,9 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
-
row = uiLayoutRow(layout, true);
uiItemR(row, &ptr, "object", 0, IFACE_("Source"), ICON_NONE);
sub = uiLayoutRow(row, true);
@@ -266,12 +263,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, &ptr, "mix_mode", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "mix_factor", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutColumn(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropDecorate(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
uiItemO(layout, "Generate Data Layers", ICON_NONE, "OBJECT_OT_datalayout_transfer");
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index ab60182ff5e..5b494baea1a 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -84,7 +84,7 @@ static DecimateModifierData *getOriginalModifierData(const DecimateModifierData
const ModifierEvalContext *ctx)
{
Object *ob_orig = DEG_get_original_object(ctx->object);
- return (DecimateModifierData *)BKE_modifiers_findny_name(ob_orig, dmd->modifier.name);
+ return (DecimateModifierData *)BKE_modifiers_findby_name(ob_orig, dmd->modifier.name);
}
static void updateFaceCount(const ModifierEvalContext *ctx,
@@ -234,14 +234,12 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
int decimate_type = RNA_enum_get(&ptr, "decimate_type");
char count_info[32];
snprintf(count_info, 32, IFACE_("Face Count: %d"), RNA_int_get(&ptr, "face_count"));
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiItemR(layout, &ptr, "decimate_type", 0, NULL, ICON_NONE);
@@ -259,13 +257,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, &ptr, "use_collapse_triangulate", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutColumn(row, true);
- uiLayoutSetPropDecorate(sub, false);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
}
else if (decimate_type == MOD_DECIM_MODE_UNSUBDIV) {
uiItemR(layout, &ptr, "iterations", 0, NULL, ICON_NONE);
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 42cdb87e289..d562559d66d 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -418,6 +418,11 @@ static void deformVertsEM(ModifierData *md,
Mesh *mesh_src = MOD_deform_mesh_eval_get(
ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
@@ -427,17 +432,15 @@ static void deformVertsEM(ModifierData *md,
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row, *col;
+ uiLayout *col;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
PointerRNA texture_ptr = RNA_pointer_get(&ptr, "texture");
bool has_texture = !RNA_pointer_is_null(&texture_ptr);
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
int texture_coords = RNA_enum_get(&ptr, "texture_coords");
uiLayoutSetPropSep(layout, true);
@@ -484,12 +487,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(col, &ptr, "strength", 0, NULL, ICON_NONE);
uiItemR(col, &ptr, "mid_level", 0, NULL, ICON_NONE);
- row = uiLayoutRow(col, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutColumn(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(col, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index 0d40b684b39..f8a100f1f0a 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -189,7 +189,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
- modifier_panel_buttons(C, panel);
uiItemL(layout, IFACE_("Settings are inside the Physics tab"), ICON_NONE);
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index 42ea46d299a..0134b5c9d64 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -145,7 +145,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 6a51c8dd90a..0c1eedd429a 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -1187,14 +1187,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row;
+ uiLayout *row;
uiLayout *layout = panel->layout;
int toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
@@ -1213,12 +1212,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, &ptr, "use_edge_cut", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "use_size", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropDecorate(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
row = uiLayoutRow(layout, false);
uiLayoutSetActive(row, has_vertex_group);
diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c
index cf97ccc3b75..0ef062d72d5 100644
--- a/source/blender/modifiers/intern/MOD_fluid.c
+++ b/source/blender/modifiers/intern/MOD_fluid.c
@@ -211,7 +211,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
- modifier_panel_buttons(C, panel);
uiItemL(layout, IFACE_("Settings are inside the Physics tab"), ICON_NONE);
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index 6dd9734a1bd..2eff026c040 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -401,16 +401,14 @@ static void deformVertsEM(struct ModifierData *md,
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row, *col;
+ uiLayout *row, *col;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
PointerRNA hook_object_ptr = RNA_pointer_get(&ptr, "object");
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -422,13 +420,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemPointerR(
col, &ptr, "subtarget", &hook_object_data_ptr, "bones", IFACE_("Bone"), ICON_NONE);
}
- col = uiLayoutColumn(layout, false);
- row = uiLayoutRow(col, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
uiItemR(layout, &ptr, "strength", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index 320293ea9e5..b7975bec77a 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -39,6 +39,7 @@
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_lib_id.h"
+#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h"
#include "BKE_particle.h"
@@ -794,6 +795,11 @@ static void deformVertsEM(ModifierData *md,
Mesh *mesh_src = MOD_deform_mesh_eval_get(
ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
LaplacianDeformModifier_do(
(LaplacianDeformModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts);
@@ -815,13 +821,12 @@ static void freeData(ModifierData *md)
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row;
+ uiLayout *row;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
bool is_bind = RNA_boolean_get(&ptr, "is_bind");
bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
@@ -830,20 +835,14 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, &ptr, "iterations", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiLayoutSetEnabled(row, !is_bind);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
uiItemS(layout);
row = uiLayoutRow(layout, true);
uiLayoutSetEnabled(row, has_vertex_group);
uiItemO(row,
- (RNA_boolean_get(&ptr, "is_bind") ? IFACE_("Unbind") : IFACE_("Bind")),
+ is_bind ? IFACE_("Unbind") : IFACE_("Bind"),
ICON_NONE,
"OBJECT_OT_laplaciandeform_bind");
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index 1cb3145d9f3..130c280c5f2 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -570,6 +570,11 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
laplaciansmoothModifier_do(
(LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts);
@@ -580,16 +585,13 @@ static void deformVertsEM(ModifierData *md,
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row;
+ uiLayout *row;
uiLayout *layout = panel->layout;
int toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -606,12 +608,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, &ptr, "use_volume_preserve", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "use_normalized", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropDecorate(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index cd1be8d8a8e..31cfe3bb407 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -136,6 +136,11 @@ static void deformVertsEM(ModifierData *md,
struct Mesh *mesh_src = MOD_deform_mesh_eval_get(
ctx->object, em, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
deformVerts(md, ctx, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
@@ -145,26 +150,17 @@ static void deformVertsEM(ModifierData *md,
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
uiItemR(layout, &ptr, "object", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
uiItemR(layout, &ptr, "strength", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc
index 76b5690a316..c6de980d674 100644
--- a/source/blender/modifiers/intern/MOD_mask.cc
+++ b/source/blender/modifiers/intern/MOD_mask.cc
@@ -411,10 +411,8 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
int mode = RNA_enum_get(&ptr, "mode");
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiItemR(layout, &ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
@@ -428,12 +426,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
}
else if (mode == MOD_MASK_MODE_VGROUP) {
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropDecorate(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr);
}
uiItemR(layout, &ptr, "threshold", 0, NULL, ICON_NONE);
diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c
index 0a88106a724..2d104e1e0c2 100644
--- a/source/blender/modifiers/intern/MOD_meshcache.c
+++ b/source/blender/modifiers/intern/MOD_meshcache.c
@@ -303,7 +303,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index fde143b331b..c24515e01eb 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -490,6 +490,11 @@ static void deformVertsEM(ModifierData *md,
Mesh *mesh_src = MOD_deform_mesh_eval_get(
ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
meshdeformModifier_do(md, ctx, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
@@ -566,16 +571,14 @@ void BKE_modifier_mdef_compact_influences(ModifierData *md)
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row, *col;
+ uiLayout *col;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
bool is_bound = RNA_boolean_get(&ptr, "is_bound");
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -583,12 +586,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiLayoutSetEnabled(col, !is_bound);
uiItemR(col, &ptr, "object", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropDecorate(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
col = uiLayoutColumn(layout, false);
uiLayoutSetEnabled(col, !is_bound);
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index 5834b78f145..801badc382c 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -204,7 +204,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
PointerRNA cache_file_ptr = RNA_pointer_get(&ptr, "cache_file");
bool has_cache_file = !RNA_pointer_is_null(&cache_file_ptr);
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 808ddf235f1..949b115a25f 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -134,7 +134,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
col = uiLayoutColumn(layout, false);
uiLayoutSetPropSep(col, true);
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index 4ef4b952ff8..75ec5eb5be7 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -294,7 +294,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
MultiresModifierData *mmd = (MultiresModifierData *)ptr.data;
- modifier_panel_buttons(C, panel);
PointerRNA op_ptr;
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index 1f5c261bf40..c1901a97cda 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -708,7 +708,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
@@ -724,10 +723,10 @@ static void panel_draw(const bContext *C, Panel *panel)
modifier_panel_end(layout, &ptr);
}
+/* This panel could be open by default, but it isn't currently. */
static void mix_mode_panel_draw(const bContext *C, Panel *panel)
{
- /* This panel could be open by default. */
- uiLayout *row, *sub;
+ uiLayout *row;
uiLayout *layout = panel->layout;
PointerRNA ptr;
@@ -736,17 +735,10 @@ static void mix_mode_panel_draw(const bContext *C, Panel *panel)
uiLayoutSetPropSep(layout, true);
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
-
uiItemR(layout, &ptr, "mix_mode", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "mix_factor", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutColumn(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
row = uiLayoutRow(layout, true);
uiItemR(row, &ptr, "mix_limit", 0, NULL, ICON_NONE);
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index e8d2ed13c45..e16a23f54c6 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -517,7 +517,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
@@ -542,6 +541,7 @@ static void panel_draw(const bContext *C, Panel *panel)
#else /* WITH_OCEANSIM */
uiItemL(layout, IFACE_("Built without Ocean modifier"), ICON_NONE);
+ UNUSED_VARS(C);
#endif /* WITH_OCEANSIM */
}
@@ -669,6 +669,8 @@ static void panelRegister(ARegionType *region_type)
modifier_subpanel_register(
region_type, "spectrum", "Spectrum", NULL, spectrum_panel_draw, panel_type);
modifier_subpanel_register(region_type, "bake", "Bake", NULL, bake_panel_draw, panel_type);
+#else
+ UNUSED_VARS(panel_type);
#endif /* WITH_OCEANSIM */
}
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index dc96e2fb9e4..0a9fb964281 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -567,7 +567,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
PointerRNA particle_obj_ptr = RNA_pointer_get(&ptr, "object");
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index 4edb3c34895..b63fb18de69 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -227,7 +227,7 @@ static void deformVerts(ModifierData *md,
if (DEG_is_active(ctx->depsgraph)) {
Object *object_orig = DEG_get_original_object(ctx->object);
- ModifierData *md_orig = BKE_modifiers_findny_name(object_orig, psmd->modifier.name);
+ ModifierData *md_orig = BKE_modifiers_findby_name(object_orig, psmd->modifier.name);
BLI_assert(md_orig != NULL);
ParticleSystemModifierData *psmd_orig = (ParticleSystemModifierData *)md_orig;
psmd_orig->flag = psmd->flag;
@@ -263,10 +263,30 @@ static void panel_draw(const bContext *C, Panel *panel)
uiLayout *layout = panel->layout;
PointerRNA ptr;
- modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
+ PointerRNA ob_ptr;
+ modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
+
+ Object *ob = ob_ptr.data;
+ ModifierData *md = (ModifierData *)ptr.data;
+ ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
uiItemL(layout, IFACE_("Settings are in the particle tab"), ICON_NONE);
+ if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
+ if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB)) {
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"),
+ ICON_NONE,
+ "OBJECT_OT_duplicates_make_real");
+ }
+ else if (psys->part->ren_as == PART_DRAW_PATH) {
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"),
+ ICON_NONE,
+ "OBJECT_OT_modifier_convert");
+ }
+ }
+
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c
index cbc64989f55..a76b3acb783 100644
--- a/source/blender/modifiers/intern/MOD_remesh.c
+++ b/source/blender/modifiers/intern/MOD_remesh.c
@@ -246,7 +246,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
int mode = RNA_enum_get(&ptr, "mode");
@@ -277,6 +276,7 @@ static void panel_draw(const bContext *C, Panel *panel)
#else /* WITH_MOD_REMESH */
uiItemL(layout, IFACE_("Built without Remesh modifier"), ICON_NONE);
+ UNUSED_VARS(C);
#endif /* WITH_MOD_REMESH */
}
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 5a478438ef9..b1c49ba2fec 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -1176,7 +1176,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
- modifier_panel_buttons(C, panel);
PointerRNA screw_obj_ptr = RNA_pointer_get(&ptr, "object");
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index fcd11904d2b..c0f7a0a7db0 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -153,6 +153,11 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
}
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
struct MDeformVert *dvert = NULL;
int defgrp_index = -1;
if (swmd->vgroup_name[0] != '\0') {
@@ -211,18 +216,16 @@ static bool dependsOnNormals(ModifierData *md)
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row, *col;
+ uiLayout *row, *col;
uiLayout *layout = panel->layout;
int toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
int wrap_method = RNA_enum_get(&ptr, "wrap_method");
uiItemR(layout, &ptr, "wrap_method", 0, NULL, ICON_NONE);
@@ -260,12 +263,7 @@ static void panel_draw(const bContext *C, Panel *panel)
}
uiItemR(layout, &ptr, "offset", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutColumn(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 103e2a3685d..3a3b3a4f3ce 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -451,6 +451,11 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
}
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
@@ -466,7 +471,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
int deform_method = RNA_enum_get(&ptr, "deform_method");
@@ -490,7 +494,7 @@ static void panel_draw(const bContext *C, Panel *panel)
static void restrictions_panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *col, *row, *sub;
+ uiLayout *row;
uiLayout *layout = panel->layout;
int toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE;
@@ -499,7 +503,6 @@ static void restrictions_panel_draw(const bContext *C, Panel *panel)
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
int deform_method = RNA_enum_get(&ptr, "deform_method");
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -523,13 +526,7 @@ static void restrictions_panel_draw(const bContext *C, Panel *panel)
}
}
- col = uiLayoutColumn(layout, true);
- row = uiLayoutRow(col, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
}
static void panelRegister(ARegionType *region_type)
diff --git a/source/blender/modifiers/intern/MOD_simulation.cc b/source/blender/modifiers/intern/MOD_simulation.cc
index 54d07bbc178..a9af48b682f 100644
--- a/source/blender/modifiers/intern/MOD_simulation.cc
+++ b/source/blender/modifiers/intern/MOD_simulation.cc
@@ -97,7 +97,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiItemR(layout, &ptr, "simulation", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "data_path", 0, NULL, ICON_NONE);
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 673407cf2d5..38d7b31a335 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -935,7 +935,13 @@ static Mesh *subdivide_base(Mesh *orig)
u = e->v1;
radrat = (half_v2(outnode[e->v2].radius) / half_v2(outnode[e->v1].radius));
- radrat = (radrat + 1) / 2;
+ if (isfinite(radrat)) {
+ radrat = (radrat + 1) / 2;
+ }
+ else {
+ /* Happens when skin is scaled to zero. */
+ radrat = 1.0f;
+ }
/* Add vertices and edge segments */
for (j = 0; j < edge_subd[i]; j++, v++, outedge++) {
@@ -1950,7 +1956,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
PointerRNA op_ptr;
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index d3a2da6ace4..21313746ce3 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -227,6 +227,9 @@ static void deformVertsEM(ModifierData *md,
/* mesh_src is needed for vgroups, and taking edges into account. */
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(campbell): use edit-mode data only (remove this line). */
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+
smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
@@ -236,16 +239,13 @@ static void deformVertsEM(ModifierData *md,
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row, *col;
+ uiLayout *row, *col;
uiLayout *layout = panel->layout;
int toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -258,12 +258,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(col, &ptr, "factor", 0, NULL, ICON_NONE);
uiItemR(col, &ptr, "iterations", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropDecorate(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index c9a3e780040..09351450d3b 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -105,7 +105,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
int solidify_mode = RNA_enum_get(&ptr, "solidify_mode");
bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
@@ -134,12 +133,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemS(layout);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetPropDecorate(sub, false);
- uiLayoutSetActive(sub, has_vertex_group);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
row = uiLayoutRow(layout, false);
uiLayoutSetActive(row, has_vertex_group);
uiItemR(row, &ptr, "thickness_vertex_group", 0, IFACE_("Factor"), ICON_NONE);
@@ -228,6 +222,7 @@ static void clamp_panel_draw(const bContext *C, Panel *panel)
static void vertex_group_panel_draw(const bContext *C, Panel *panel)
{
+ uiLayout *col;
uiLayout *layout = panel->layout;
PointerRNA ptr;
@@ -236,8 +231,9 @@ static void vertex_group_panel_draw(const bContext *C, Panel *panel)
uiLayoutSetPropSep(layout, true);
- uiItemPointerR(layout, &ptr, "shell_vertex_group", &ob_ptr, "vertex_groups", "Shell", ICON_NONE);
- uiItemPointerR(layout, &ptr, "rim_vertex_group", &ob_ptr, "vertex_groups", "Rim", ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemPointerR(col, &ptr, "shell_vertex_group", &ob_ptr, "vertex_groups", "Shell", ICON_NONE);
+ uiItemPointerR(col, &ptr, "rim_vertex_group", &ob_ptr, "vertex_groups", "Rim", ICON_NONE);
}
static void panelRegister(ARegionType *region_type)
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index 9e3d13432a0..affd3eece0a 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -328,22 +328,22 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- PointerRNA scene_ptr;
- Scene *scene = CTX_data_scene(C);
- RNA_id_pointer_create(&scene->id, &scene_ptr);
/* Only test for adaptive subdivision if built with cycles. */
bool show_adaptive_options = false;
bool ob_use_adaptive_subdivision = false;
PointerRNA cycles_ptr = {NULL};
PointerRNA ob_cycles_ptr = {NULL};
#ifdef WITH_CYCLES
- cycles_ptr = RNA_pointer_get(&scene_ptr, "cycles");
- ob_cycles_ptr = RNA_pointer_get(&ob_ptr, "cycles");
- if (!RNA_pointer_is_null(&ob_cycles_ptr)) {
- ob_use_adaptive_subdivision = RNA_boolean_get(&ob_cycles_ptr, "use_adaptive_subdivision");
- show_adaptive_options = get_show_adaptive_options(C, panel);
+ PointerRNA scene_ptr;
+ Scene *scene = CTX_data_scene(C);
+ RNA_id_pointer_create(&scene->id, &scene_ptr);
+ if (BKE_scene_uses_cycles(scene)) {
+ cycles_ptr = RNA_pointer_get(&scene_ptr, "cycles");
+ ob_cycles_ptr = RNA_pointer_get(&ob_ptr, "cycles");
+ if (!RNA_pointer_is_null(&ob_cycles_ptr)) {
+ ob_use_adaptive_subdivision = RNA_boolean_get(&ob_cycles_ptr, "use_adaptive_subdivision");
+ show_adaptive_options = get_show_adaptive_options(C, panel);
+ }
}
#endif
@@ -358,30 +358,27 @@ static void panel_draw(const bContext *C, Panel *panel)
0,
IFACE_("Adaptive Subdivision"),
ICON_NONE);
- if (ob_use_adaptive_subdivision) {
- uiItemR(layout, &ob_cycles_ptr, "dicing_rate", 0, NULL, ICON_NONE);
- float render = MAX2(RNA_float_get(&cycles_ptr, "dicing_rate") *
- RNA_float_get(&ob_cycles_ptr, "dicing_rate"),
- 0.1f);
- float preview = MAX2(RNA_float_get(&cycles_ptr, "preview_dicing_rate") *
- RNA_float_get(&ob_cycles_ptr, "dicing_rate"),
- 0.1f);
- char output[64];
- snprintf(output, 64, "Final Scale: Render %.2f px, Viewport %.2f px", render, preview);
- uiItemL(layout, output, ICON_NONE);
-
- uiItemS(layout);
-
- uiItemR(layout, &ptr, "levels", 0, IFACE_("Levels Viewport"), ICON_NONE);
- }
- else {
- uiItemR(layout, &ptr, "render_levels", 0, IFACE_("Levels Viewport"), ICON_NONE);
- uiItemR(layout, &ptr, "levels", 0, IFACE_("Viewport"), ICON_NONE);
- }
}
- else {
+ if (ob_use_adaptive_subdivision && show_adaptive_options) {
+ uiItemR(layout, &ob_cycles_ptr, "dicing_rate", 0, NULL, ICON_NONE);
+ float render = MAX2(RNA_float_get(&cycles_ptr, "dicing_rate") *
+ RNA_float_get(&ob_cycles_ptr, "dicing_rate"),
+ 0.1f);
+ float preview = MAX2(RNA_float_get(&cycles_ptr, "preview_dicing_rate") *
+ RNA_float_get(&ob_cycles_ptr, "dicing_rate"),
+ 0.1f);
+ char output[64];
+ snprintf(output, 64, "Final Scale: Render %.2f px, Viewport %.2f px", render, preview);
+ uiItemL(layout, output, ICON_NONE);
+
+ uiItemS(layout);
+
uiItemR(layout, &ptr, "levels", 0, IFACE_("Levels Viewport"), ICON_NONE);
- uiItemR(layout, &ptr, "render_levels", 0, IFACE_("Render"), ICON_NONE);
+ }
+ else {
+ uiLayout *col = uiLayoutColumn(layout, true);
+ uiItemR(col, &ptr, "levels", 0, IFACE_("Levels Viewport"), ICON_NONE);
+ uiItemR(col, &ptr, "render_levels", 0, IFACE_("Render"), ICON_NONE);
}
uiItemR(layout, &ptr, "show_only_control_edges", 0, NULL, ICON_NONE);
@@ -400,10 +397,13 @@ static void advanced_panel_draw(const bContext *C, Panel *panel)
bool ob_use_adaptive_subdivision = false;
bool show_adaptive_options = false;
#ifdef WITH_CYCLES
- PointerRNA ob_cycles_ptr = RNA_pointer_get(&ob_ptr, "cycles");
- if (!RNA_pointer_is_null(&ob_cycles_ptr)) {
- ob_use_adaptive_subdivision = RNA_boolean_get(&ob_cycles_ptr, "use_adaptive_subdivision");
- show_adaptive_options = get_show_adaptive_options(C, panel);
+ Scene *scene = CTX_data_scene(C);
+ if (BKE_scene_uses_cycles(scene)) {
+ PointerRNA ob_cycles_ptr = RNA_pointer_get(&ob_ptr, "cycles");
+ if (!RNA_pointer_is_null(&ob_cycles_ptr)) {
+ ob_use_adaptive_subdivision = RNA_boolean_get(&ob_cycles_ptr, "use_adaptive_subdivision");
+ show_adaptive_options = get_show_adaptive_options(C, panel);
+ }
}
#endif
@@ -413,6 +413,8 @@ static void advanced_panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, &ptr, "quality", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "uv_smooth", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "use_creases", 0, NULL, ICON_NONE);
+
+ modifier_panel_end(layout, &ptr);
}
static void panelRegister(ARegionType *region_type)
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index 6be321eaa4e..4a2ed1d71db 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -1397,18 +1397,16 @@ static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *row, *col, *sub;
+ uiLayout *col;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
PointerRNA target_ptr = RNA_pointer_get(&ptr, "target");
bool is_bound = RNA_boolean_get(&ptr, "is_bound");
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -1419,13 +1417,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(col, &ptr, "falloff", 0, NULL, ICON_NONE);
uiItemR(col, &ptr, "strength", 0, NULL, ICON_NONE);
- row = uiLayoutRow(col, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetPropDecorate(sub, false);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
uiItemS(layout);
diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c
index 1857744512d..351a1016a35 100644
--- a/source/blender/modifiers/intern/MOD_triangulate.c
+++ b/source/blender/modifiers/intern/MOD_triangulate.c
@@ -133,7 +133,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
diff --git a/source/blender/modifiers/intern/MOD_ui_common.c b/source/blender/modifiers/intern/MOD_ui_common.c
index 58906c02c98..973afe5fef6 100644
--- a/source/blender/modifiers/intern/MOD_ui_common.c
+++ b/source/blender/modifiers/intern/MOD_ui_common.c
@@ -33,6 +33,7 @@
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "ED_object.h"
@@ -49,13 +50,24 @@
#include "MOD_modifiertypes.h"
#include "MOD_ui_common.h" /* Self include */
+static Object *get_modifier_object(const bContext *C)
+{
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ if (sbuts != NULL && (sbuts->pinid != NULL) && GS(sbuts->pinid->name) == ID_OB) {
+ return (Object *)sbuts->pinid;
+ }
+ else {
+ return CTX_data_active_object(C);
+ }
+}
+
/**
* Poll function so these modifier panels don't show for other object types with modifiers (only
* grease pencil currently).
*/
static bool modifier_ui_poll(const bContext *C, PanelType *UNUSED(pt))
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = get_modifier_object(C);
return (ob != NULL) && (ob->type != OB_GPENCIL);
}
@@ -69,7 +81,7 @@ static bool modifier_ui_poll(const bContext *C, PanelType *UNUSED(pt))
*/
static void modifier_reorder(bContext *C, Panel *panel, int new_index)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = get_modifier_object(C);
ModifierData *md = BLI_findlink(&ob->modifiers, panel->runtime.list_index);
PointerRNA props_ptr;
@@ -83,14 +95,14 @@ static void modifier_reorder(bContext *C, Panel *panel, int new_index)
static short get_modifier_expand_flag(const bContext *C, Panel *panel)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = get_modifier_object(C);
ModifierData *md = BLI_findlink(&ob->modifiers, panel->runtime.list_index);
return md->ui_expand_flag;
}
static void set_modifier_expand_flag(const bContext *C, Panel *panel, short expand_flag)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = get_modifier_object(C);
ModifierData *md = BLI_findlink(&ob->modifiers, panel->runtime.list_index);
md->ui_expand_flag = expand_flag;
}
@@ -114,14 +126,17 @@ void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
}
/**
- * Gets RNA pointers for the active object and the panel's modifier data.
+ * Gets RNA pointers for the active object and the panel's modifier data. Also locks
+ * the layout if the modifer is from a linked object, and sets the context pointer.
*/
+#define ERROR_LIBDATA_MESSAGE TIP_("External library data")
void modifier_panel_get_property_pointers(const bContext *C,
Panel *panel,
PointerRNA *r_ob_ptr,
PointerRNA *r_md_ptr)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = get_modifier_object(C);
+
ModifierData *md = BLI_findlink(&ob->modifiers, panel->runtime.list_index);
RNA_pointer_create(&ob->id, &RNA_Modifier, md, r_md_ptr);
@@ -130,86 +145,41 @@ void modifier_panel_get_property_pointers(const bContext *C,
RNA_pointer_create(&ob->id, &RNA_Object, ob, r_ob_ptr);
}
- uiLayoutSetContextPointer(panel->layout, "modifier", r_md_ptr);
-}
-
-#define ERROR_LIBDATA_MESSAGE TIP_("Can't edit external library data")
-void modifier_panel_buttons(const bContext *C, Panel *panel)
-{
- uiLayout *row, *sub;
- uiBlock *block;
- uiLayout *layout = panel->layout;
-
- row = uiLayoutRow(layout, false);
-
- uiLayoutSetScaleY(row, 0.8f);
-
- Object *ob = CTX_data_active_object(C);
- ModifierData *md = BLI_findlink(&ob->modifiers, panel->runtime.list_index);
-
- block = uiLayoutGetBlock(row);
+ uiBlock *block = uiLayoutGetBlock(panel->layout);
UI_block_lock_set(
block, BKE_object_obdata_is_libdata(ob) || ID_IS_LINKED(ob), ERROR_LIBDATA_MESSAGE);
- if (md->type == eModifierType_ParticleSystem) {
- ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
-
- if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
- if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB)) {
- uiItemO(row,
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"),
- ICON_NONE,
- "OBJECT_OT_duplicates_make_real");
- }
- else if (psys->part->ren_as == PART_DRAW_PATH) {
- uiItemO(row,
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"),
- ICON_NONE,
- "OBJECT_OT_modifier_convert");
- }
- }
- }
- else {
- uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
+ uiLayoutSetContextPointer(panel->layout, "modifier", r_md_ptr);
+}
- sub = uiLayoutRow(row, false);
- uiItemEnumO(sub,
- "OBJECT_OT_modifier_apply",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
- 0,
- "apply_as",
- MODIFIER_APPLY_DATA);
-
- if (BKE_modifier_is_same_topology(md) && !BKE_modifier_is_non_geometrical(md)) {
- uiItemEnumO(sub,
- "OBJECT_OT_modifier_apply",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Shape"),
- 0,
- "apply_as",
- MODIFIER_APPLY_SHAPE);
- }
+/**
+ * Helper function for modifier layouts to draw vertex group settings.
+ */
+void modifier_vgroup_ui(uiLayout *layout,
+ PointerRNA *ptr,
+ PointerRNA *ob_ptr,
+ const char *vgroup_prop,
+ const char *invert_vgroup_prop,
+ const char *text)
+{
+ bool has_vertex_group = RNA_string_length(ptr, vgroup_prop) != 0;
+
+ uiLayout *row = uiLayoutRow(layout, true);
+ uiItemPointerR(row, ptr, vgroup_prop, ob_ptr, "vertex_groups", text, ICON_NONE);
+ if (invert_vgroup_prop != NULL) {
+ uiLayout *sub = uiLayoutRow(row, true);
+ uiLayoutSetActive(sub, has_vertex_group);
+ uiLayoutSetPropDecorate(sub, false);
+ uiItemR(sub, ptr, invert_vgroup_prop, 0, "", ICON_ARROW_LEFTRIGHT);
}
-
- if (!ELEM(md->type,
- eModifierType_Fluidsim,
- eModifierType_Softbody,
- eModifierType_ParticleSystem,
- eModifierType_Cloth,
- eModifierType_Fluid)) {
- uiItemO(row,
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Duplicate"),
- 0,
- "OBJECT_OT_modifier_copy");
-
- row = uiLayoutRow(layout, false);
- uiLayoutSetScaleY(row, 0.2f);
- uiItemS(row);
+ if (uiLayoutGetPropDecorate(layout)) {
+ uiItemL(row, "", ICON_BLANK1);
}
}
/**
- * Check whether Modifier is a simulation or not.Used for switching to the physics/particles
- * context tab.
+ * Check whether Modifier is a simulation or not. Used for switching to the
+ * physics/particles context tab.
*/
static int modifier_is_simulation(ModifierData *md)
{
@@ -255,18 +225,63 @@ static bool modifier_can_delete(ModifierData *md)
return true;
}
+static void modifier_ops_extra_draw(bContext *UNUSED(C), uiLayout *layout, void *md_v)
+{
+ ModifierData *md = (ModifierData *)md_v;
+
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+
+ uiItemEnumO(layout,
+ "OBJECT_OT_modifier_apply",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
+ 0,
+ "apply_as",
+ MODIFIER_APPLY_DATA);
+
+ if (BKE_modifier_is_same_topology(md) && !BKE_modifier_is_non_geometrical(md)) {
+ uiItemEnumO(layout,
+ "OBJECT_OT_modifier_apply",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply As Shapekey"),
+ ICON_SHAPEKEY_DATA,
+ "apply_as",
+ MODIFIER_APPLY_SHAPE);
+ }
+
+ if (!ELEM(md->type,
+ eModifierType_Fluidsim,
+ eModifierType_Softbody,
+ eModifierType_ParticleSystem,
+ eModifierType_Cloth,
+ eModifierType_Fluid)) {
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Duplicate"),
+ ICON_DUPLICATE,
+ "OBJECT_OT_modifier_copy");
+ }
+
+ if (modifier_can_delete(md) && !modifier_is_simulation(md)) {
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete"),
+ ICON_X,
+ "OBJECT_OT_modifier_remove");
+ }
+}
+
static void modifier_panel_header(const bContext *C, Panel *panel)
{
uiLayout *row, *sub;
uiLayout *layout = panel->layout;
PointerRNA ptr;
- modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
+ Object *ob = get_modifier_object(C);
+
+ /* Don't use #modifier_panel_get_property_pointers, we don't want to lock the header. */
+ ModifierData *md = BLI_findlink(&ob->modifiers, panel->runtime.list_index);
+ RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
+ uiLayoutSetContextPointer(panel->layout, "modifier", &ptr);
- ModifierData *md = ptr.data;
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
int index = panel->runtime.list_index;
bool narrow_panel = (panel->sizex < UI_UNIT_X * 8 && panel->sizex != 0);
@@ -292,6 +307,7 @@ static void modifier_panel_header(const bContext *C, Panel *panel)
layout, "", ICON_PROPERTIES, "WM_OT_properties_context_change", "context", "PARTICLES");
}
+ /* Mode switching buttons. */
row = uiLayoutRow(layout, true);
if (ob->type == OB_MESH) {
int last_cage_index;
@@ -323,12 +339,9 @@ static void modifier_panel_header(const bContext *C, Panel *panel)
}
row = uiLayoutRow(layout, false);
- uiLayoutSetEmboss(row, UI_EMBOSS_NONE);
- if (modifier_can_delete(md) && !modifier_is_simulation(md)) {
- uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
- }
+ uiItemMenuF(row, "", ICON_DOWNARROW_HLT, modifier_ops_extra_draw, md);
- /* Some extra padding at the end, so 'x' icon isn't too close to drag button. */
+ /* Some padding at the end, so the buttons aren't too close to the drag button. */
uiItemS(layout);
}
@@ -343,7 +356,6 @@ static void modifier_panel_header(const bContext *C, Panel *panel)
*/
PanelType *modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
{
-
/* Get the name for the modifier's panel. */
char panel_idname[BKE_ST_MAXNAME];
BKE_modifier_type_panel_id(type, panel_idname);
@@ -372,7 +384,7 @@ PanelType *modifier_panel_register(ARegionType *region_type, ModifierType type,
}
/**
- * Add a child panel to the parent.
+ * Add a shild panel to the parent.
*
* \note To create the panel type's idname, it appends the \a name argument to the \a parent's
* idname.
diff --git a/source/blender/modifiers/intern/MOD_ui_common.h b/source/blender/modifiers/intern/MOD_ui_common.h
index cb18fb93973..59c0fe1c413 100644
--- a/source/blender/modifiers/intern/MOD_ui_common.h
+++ b/source/blender/modifiers/intern/MOD_ui_common.h
@@ -34,10 +34,17 @@ struct ARegionType;
struct bContext;
struct PanelType;
struct uiLayout;
-typedef void (*PanelDrawFn)(const bContext *, Panel *);
+typedef void (*PanelDrawFn)(const bContext *, struct Panel *);
void modifier_panel_buttons(const struct bContext *C, struct Panel *panel);
+void modifier_vgroup_ui(struct uiLayout *layout,
+ struct PointerRNA *ptr,
+ struct PointerRNA *ob_ptr,
+ const char *vgroup_prop,
+ const char *invert_vgroup_prop,
+ const char *text);
+
void modifier_panel_end(struct uiLayout *layout, PointerRNA *ptr);
void modifier_panel_get_property_pointers(const bContext *C,
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index bd453c24a31..4999c77c355 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -196,7 +196,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
}
else if (ob->type == OB_MESH) {
if (em) {
- mesh = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL, ob->data);
+ mesh = BKE_mesh_wrapper_from_editmesh_with_coords(em, NULL, vertexCos, ob->data);
}
else {
/* TODO(sybren): after modifier conversion of DM to Mesh is done, check whether
@@ -209,9 +209,12 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
mesh->runtime.deformed_only = 1;
}
+ if (em != NULL) {
+ /* pass */
+ }
/* TODO(sybren): after modifier conversion of DM to Mesh is done, check whether
* we really need vertexCos here. */
- if (vertexCos) {
+ else if (vertexCos) {
BKE_mesh_vert_coords_apply(mesh, vertexCos);
mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
}
@@ -241,7 +244,9 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
}
}
- BLI_assert(mesh == NULL || mesh->totvert == num_verts);
+ if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
+ BLI_assert(mesh->totvert == num_verts);
+ }
return mesh;
}
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 32aaa4992e3..07a57806f87 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -332,7 +332,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index 9f4e8b76a0f..a8321cdc26a 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -258,17 +258,15 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row, *col;
+ uiLayout *col;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
PointerRNA warp_obj_ptr;
PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -296,13 +294,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemPointerR(col, &ptr, "bone_to", &warp_obj_data_ptr, "bones", NULL, ICON_NONE);
}
- col = uiLayoutColumn(layout, true);
- row = uiLayoutRow(col, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index fb9908c8455..eab8ba478aa 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -392,6 +392,11 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
}
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
warpModifier_do(wmd, ctx, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
@@ -401,15 +406,12 @@ static void deformVertsEM(ModifierData *md,
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row, *col;
+ uiLayout *col;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -432,16 +434,9 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, &ptr, "use_volume_preserve", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemR(row, &ptr, "strength", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "strength", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetPropDecorate(sub, false);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index c07f6cf8ba8..48aca9284eb 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -364,6 +364,11 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
}
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
waveModifier_do(wmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
@@ -379,9 +384,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -405,12 +407,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(col, &ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
uiItemR(col, &ptr, "narrowness", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
index 0bd8751fcb2..dc1b7ba8a75 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.c
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -713,15 +713,11 @@ static bool dependsOnNormals(ModifierData *UNUSED(md))
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
@@ -733,12 +729,7 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, &ptr, "keep_sharp", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "face_influence", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutColumn(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c
index 5ef6ee8b41d..54d3aa46344 100644
--- a/source/blender/modifiers/intern/MOD_weightvg_util.c
+++ b/source/blender/modifiers/intern/MOD_weightvg_util.c
@@ -52,6 +52,7 @@
#include "DEG_depsgraph_query.h"
#include "MEM_guardedalloc.h"
+#include "MOD_ui_common.h"
#include "MOD_util.h"
#include "MOD_weightvg_util.h"
#include "RE_shader_ext.h" /* Texture masking. */
@@ -280,16 +281,45 @@ void weightvg_update_vg(MDeformVert *dvert,
const bool do_add,
const float add_thresh,
const bool do_rem,
- const float rem_thresh)
+ const float rem_thresh,
+ const bool do_normalize)
{
int i;
+ float min_w = weights[0];
+ float norm_fac = 1.0f;
+ if (do_normalize) {
+ float max_w = weights[0];
+ for (i = 1; i < num; i++) {
+ const float w = weights[i];
+
+ /* No need to clamp here, normalization will ensure we stay within [0.0, 1.0] range. */
+ if (w < min_w) {
+ min_w = w;
+ }
+ else if (w > max_w) {
+ max_w = w;
+ }
+ }
+
+ const float range = max_w - min_w;
+ if (fabsf(range) > FLT_EPSILON) {
+ norm_fac = 1.0f / range;
+ }
+ else {
+ min_w = 0.0f;
+ }
+ }
+
for (i = 0; i < num; i++) {
float w = weights[i];
MDeformVert *dv = &dvert[indices ? indices[i] : i];
MDeformWeight *dw = dws ? dws[i] :
((defgrp_idx >= 0) ? BKE_defvert_find_index(dv, defgrp_idx) : NULL);
+ if (do_normalize) {
+ w = (w - min_w) * norm_fac;
+ }
/* Never allow weights out of [0.0, 1.0] range. */
CLAMP(w, 0.0f, 1.0f);
@@ -313,8 +343,6 @@ void weightvg_update_vg(MDeformVert *dvert,
*/
void weightvg_ui_common(const bContext *C, PointerRNA *ob_ptr, PointerRNA *ptr, uiLayout *layout)
{
- uiLayout *sub, *row;
-
PointerRNA mask_texture_ptr = RNA_pointer_get(ptr, "mask_texture");
bool has_mask_texture = !RNA_pointer_is_null(&mask_texture_ptr);
bool has_mask_vertex_group = RNA_string_length(ptr, "mask_vertex_group") != 0;
@@ -325,12 +353,7 @@ void weightvg_ui_common(const bContext *C, PointerRNA *ob_ptr, PointerRNA *ptr,
uiItemR(layout, ptr, "mask_constant", UI_ITEM_R_SLIDER, IFACE_("Global Influence:"), ICON_NONE);
if (!has_mask_texture) {
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, ptr, "mask_vertex_group", ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutColumn(row, true);
- uiLayoutSetPropSep(sub, false);
- uiLayoutSetActive(sub, has_mask_vertex_group);
- uiItemR(sub, ptr, "invert_mask_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, ptr, ob_ptr, "mask_vertex_group", "invert_mask_vertex_group", NULL);
}
if (!has_mask_vertex_group) {
diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.h b/source/blender/modifiers/intern/MOD_weightvg_util.h
index 8be608410be..725574dc0a5 100644
--- a/source/blender/modifiers/intern/MOD_weightvg_util.h
+++ b/source/blender/modifiers/intern/MOD_weightvg_util.h
@@ -88,7 +88,8 @@ void weightvg_update_vg(struct MDeformVert *dvert,
const bool do_add,
const float add_thresh,
const bool do_rem,
- const float rem_thresh);
+ const float rem_thresh,
+ const bool do_normalize);
void weightvg_ui_common(const bContext *C, PointerRNA *ob_ptr, PointerRNA *ptr, uiLayout *layout);
#endif /* __MOD_WEIGHTVG_UTIL_H__ */
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index 317e61e286d..9a9ab55a835 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -250,6 +250,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Do mapping. */
const bool do_invert_mapping = (wmd->edit_flags & MOD_WVG_INVERT_FALLOFF) != 0;
+ const bool do_normalize = (wmd->edit_flags & MOD_WVG_EDIT_WEIGHTS_NORMALIZE) != 0;
if (do_invert_mapping || wmd->falloff_type != MOD_WVG_MAPPING_NONE) {
RNG *rng = NULL;
@@ -294,7 +295,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
do_add,
wmd->add_threshold,
do_rem,
- wmd->rem_threshold);
+ wmd->rem_threshold,
+ do_normalize);
/* If weight preview enabled... */
#if 0 /* XXX Currently done in mod stack :/ */
@@ -320,7 +322,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
@@ -351,6 +352,8 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(sub, &ptr, "remove_threshold", UI_ITEM_R_SLIDER, "Threshold", ICON_NONE);
uiItemDecoratorR(row, &ptr, "remove_threshold", 0);
+ uiItemR(layout, &ptr, "normalize", 0, NULL, ICON_NONE);
+
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index a8189a460d1..e089720b3e3 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -235,6 +235,17 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
int numIdx = 0;
int i;
const bool invert_vgroup_mask = (wmd->flag & MOD_WVG_MIX_INVERT_VGROUP_MASK) != 0;
+ const bool do_normalize = (wmd->flag & MOD_WVG_MIX_WEIGHTS_NORMALIZE) != 0;
+
+ /*
+ * Note that we only invert the weight values within provided vgroups, the selection based on
+ * which vertice is affected because it belongs or not to a group remains unchanged.
+ * In other words, vertices not belonging to a group won't be affected, even though their
+ * inverted 'virtual' weight would be 1.0f.
+ */
+ const bool invert_vgroup_a = (wmd->flag & MOD_WVG_MIX_INVERT_VGROUP_A) != 0;
+ const bool invert_vgroup_b = (wmd->flag & MOD_WVG_MIX_INVERT_VGROUP_B) != 0;
+
/* Flags. */
#if 0
const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0;
@@ -389,8 +400,18 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Mix weights. */
for (i = 0; i < numIdx; i++) {
float weight2;
- org_w[i] = dw1[i] ? dw1[i]->weight : wmd->default_weight_a;
- weight2 = dw2[i] ? dw2[i]->weight : wmd->default_weight_b;
+ if (invert_vgroup_a) {
+ org_w[i] = 1.0f - (dw1[i] ? dw1[i]->weight : wmd->default_weight_a);
+ }
+ else {
+ org_w[i] = dw1[i] ? dw1[i]->weight : wmd->default_weight_a;
+ }
+ if (invert_vgroup_b) {
+ weight2 = 1.0f - (dw2[i] ? dw2[i]->weight : wmd->default_weight_b);
+ }
+ else {
+ weight2 = dw2[i] ? dw2[i]->weight : wmd->default_weight_b;
+ }
new_w[i] = mix_weight(org_w[i], weight2, wmd->mix_mode);
}
@@ -419,7 +440,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
* XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup.
*/
weightvg_update_vg(
- dvert, defgrp_index, dw1, numIdx, indices, org_w, true, -FLT_MAX, false, 0.0f);
+ dvert, defgrp_index, dw1, numIdx, indices, org_w, true, -FLT_MAX, false, 0.0f, do_normalize);
/* If weight preview enabled... */
#if 0 /* XXX Currently done in mod stack :/ */
@@ -446,21 +467,25 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
- uiItemPointerR(layout, &ptr, "vertex_group_a", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- uiItemR(layout, &ptr, "default_weight_a", 0, NULL, ICON_NONE);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group_a", "invert_vertex_group_a", NULL);
+ modifier_vgroup_ui(
+ layout, &ptr, &ob_ptr, "vertex_group_b", "invert_vertex_group_b", IFACE_("B"));
+
+ uiItemS(layout);
- uiItemPointerR(layout, &ptr, "vertex_group_b", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- uiItemR(layout, &ptr, "default_weight_b", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "default_weight_a", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "default_weight_b", 0, IFACE_("B"), ICON_NONE);
uiItemS(layout);
uiItemR(layout, &ptr, "mix_set", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "mix_mode", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "normalize", 0, NULL, ICON_NONE);
+
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index a9aafd01843..02d1f7a94aa 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -440,6 +440,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
int i;
const bool invert_vgroup_mask = (wmd->proximity_flags & MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK) !=
0;
+ const bool do_normalize = (wmd->proximity_flags & MOD_WVG_PROXIMITY_WEIGHTS_NORMALIZE) != 0;
/* Flags. */
#if 0
const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0;
@@ -615,7 +616,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
invert_vgroup_mask);
/* Update vgroup. Note we never add nor remove vertices from vgroup here. */
- weightvg_update_vg(dvert, defgrp_index, dw, numIdx, indices, org_w, false, 0.0f, false, 0.0f);
+ weightvg_update_vg(
+ dvert, defgrp_index, dw, numIdx, indices, org_w, false, 0.0f, false, 0.0f, do_normalize);
/* If weight preview enabled... */
#if 0 /* XXX Currently done in mod stack :/ */
@@ -647,7 +649,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
@@ -674,6 +675,10 @@ static void panel_draw(const bContext *C, Panel *panel)
uiLayoutSetPropSep(sub, false);
uiItemR(row, &ptr, "invert_falloff", 0, "", ICON_ARROW_LEFTRIGHT);
modifier_panel_end(layout, &ptr);
+
+ uiItemS(layout);
+
+ uiItemR(layout, &ptr, "normalize", 0, NULL, ICON_NONE);
}
static void influence_panel_draw(const bContext *C, Panel *panel)
diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c
index acef6b3e20d..76ca85163d9 100644
--- a/source/blender/modifiers/intern/MOD_weld.c
+++ b/source/blender/modifiers/intern/MOD_weld.c
@@ -1688,8 +1688,18 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
/* Get overlap map. */
/* TODO: For a better performanse use KD-Tree. */
struct BVHTreeFromMesh treedata;
- BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(
- &treedata, mvert, totvert, false, v_mask, v_mask_act, wmd->merge_dist / 2, 2, 6, 0, NULL);
+ BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(&treedata,
+ mvert,
+ totvert,
+ false,
+ v_mask,
+ v_mask_act,
+ wmd->merge_dist / 2,
+ 2,
+ 6,
+ 0,
+ NULL,
+ NULL);
if (v_mask) {
MEM_freeN(v_mask);
@@ -1942,26 +1952,17 @@ static void requiredDataMask(Object *UNUSED(ob),
static void panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *sub, *row;
uiLayout *layout = panel->layout;
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
-
- bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetPropSep(layout, true);
uiItemR(layout, &ptr, "merge_threshold", 0, IFACE_("Distance"), ICON_NONE);
uiItemR(layout, &ptr, "max_interactions", 0, NULL, ICON_NONE);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropSep(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
modifier_panel_end(layout, &ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c
index c8c372513d0..66a03ee5d71 100644
--- a/source/blender/modifiers/intern/MOD_wireframe.c
+++ b/source/blender/modifiers/intern/MOD_wireframe.c
@@ -125,7 +125,6 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ptr;
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
- modifier_panel_buttons(C, panel);
uiLayoutSetPropSep(layout, true);
@@ -153,7 +152,7 @@ static void panel_draw(const bContext *C, Panel *panel)
static void vertex_group_panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *row, *sub;
+ uiLayout *row;
uiLayout *layout = panel->layout;
PointerRNA ptr;
@@ -164,12 +163,7 @@ static void vertex_group_panel_draw(const bContext *C, Panel *panel)
uiLayoutSetPropSep(layout, true);
- row = uiLayoutRow(layout, true);
- uiItemPointerR(row, &ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
- sub = uiLayoutRow(row, true);
- uiLayoutSetActive(sub, has_vertex_group);
- uiLayoutSetPropDecorate(sub, false);
- uiItemR(sub, &ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
+ modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
row = uiLayoutRow(layout, true);
uiLayoutSetActive(row, has_vertex_group);
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.c b/source/blender/nodes/shader/nodes/node_shader_output_material.c
index 4b7bd964052..578262e9f17 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_material.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_material.c
@@ -45,9 +45,18 @@ static int node_shader_gpu_output_material(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- GPUNodeLink *outlink;
+ GPUNodeLink *outlink, *alpha_threshold_link;
- GPU_stack_link(mat, node, "node_output_material", in, out, &outlink);
+ Material *ma = GPU_material_get_material(mat);
+ if (ma && ma->blend_method == MA_BM_CLIP) {
+ alpha_threshold_link = GPU_uniform(&ma->alpha_threshold);
+ }
+ else {
+ static float no_alpha_threshold = -1.0f;
+ alpha_threshold_link = GPU_uniform(&no_alpha_threshold);
+ }
+
+ GPU_stack_link(mat, node, "node_output_material", in, out, alpha_threshold_link, &outlink);
GPU_material_output_link(mat, outlink);
return true;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index fd4efb1b7ec..0cf4b51f307 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -19,6 +19,8 @@
#include "../node_shader_util.h"
+#include "GPU_draw.h"
+
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_tex_environment_in[] = {
@@ -56,6 +58,10 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
bNode *node_original = node->original ? node->original : node;
NodeTexImage *tex_original = node_original->storage;
ImageUser *iuser = &tex_original->iuser;
+ eGPUSamplerState sampler = GPU_SAMPLER_REPEAT | GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER;
+ if (GPU_get_mipmap()) {
+ sampler |= GPU_SAMPLER_MIPMAP;
+ }
GPUNodeLink *outalpha;
@@ -72,49 +78,41 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
/* Compute texture coordinate. */
if (tex->projection == SHD_PROJ_EQUIRECTANGULAR) {
- /* To fix pole issue we clamp the v coordinate. The clamp value depends on the filter size. */
- float clamp_size = (ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART)) ? 1.5 : 0.5;
- GPU_link(mat,
- "node_tex_environment_equirectangular",
- in[0].link,
- GPU_constant(&clamp_size),
- GPU_image(mat, ima, iuser),
- &in[0].link);
+ GPU_link(mat, "node_tex_environment_equirectangular", in[0].link, &in[0].link);
+ /* To fix pole issue we clamp the v coordinate. */
+ sampler &= ~GPU_SAMPLER_REPEAT_T;
+ /* Force the highest mipmap and don't do anisotropic filtering.
+ * This is to fix the artifact caused by derivatives discontinuity. */
+ sampler &= ~(GPU_SAMPLER_MIPMAP | GPU_SAMPLER_ANISO);
}
else {
GPU_link(mat, "node_tex_environment_mirror_ball", in[0].link, &in[0].link);
+ /* Fix pole issue. */
+ sampler &= ~GPU_SAMPLER_REPEAT;
}
- /* Sample texture with correct interpolation. */
+ const char *gpufunc;
+ static const char *names[] = {
+ "node_tex_image_linear",
+ "node_tex_image_cubic",
+ };
+
switch (tex->interpolation) {
case SHD_INTERP_LINEAR:
- /* Force the highest mipmap and don't do anisotropic filtering.
- * This is to fix the artifact caused by derivatives discontinuity. */
- GPU_link(mat,
- "node_tex_image_linear_no_mip",
- in[0].link,
- GPU_image(mat, ima, iuser),
- &out[0].link,
- &outalpha);
+ gpufunc = names[0];
break;
case SHD_INTERP_CLOSEST:
- GPU_link(mat,
- "node_tex_image_nearest",
- in[0].link,
- GPU_image(mat, ima, iuser),
- &out[0].link,
- &outalpha);
+ sampler &= ~(GPU_SAMPLER_FILTER | GPU_SAMPLER_MIPMAP);
+ gpufunc = names[0];
break;
default:
- GPU_link(mat,
- "node_tex_image_cubic",
- in[0].link,
- GPU_image(mat, ima, iuser),
- &out[0].link,
- &outalpha);
+ gpufunc = names[1];
break;
}
+ /* Sample texture with correct interpolation. */
+ GPU_link(mat, gpufunc, in[0].link, GPU_image(mat, ima, iuser, sampler), &out[0].link, &outalpha);
+
if (out[0].hasoutput) {
if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) ||
IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) {
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index bfef9341913..cbda72cd228 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -19,6 +19,8 @@
#include "../node_shader_util.h"
+#include "GPU_draw.h"
+
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_tex_image_in[] = {
@@ -57,31 +59,6 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- static const char *names[] = {
- "node_tex_image_linear",
- "node_tex_image_nearest",
- "node_tex_image_cubic",
- "node_tex_image_smart",
- };
- static const char *names_tiled[] = {
- "node_tex_tile_linear",
- "node_tex_tile_nearest",
- "node_tex_tile_cubic",
- "node_tex_tile_smart",
- };
- static const char *names_box[] = {
- "tex_box_sample_linear",
- "tex_box_sample_nearest",
- "tex_box_sample_cubic",
- "tex_box_sample_smart",
- };
- static const char *names_clip[] = {
- "tex_clip_linear",
- "tex_clip_nearest",
- "tex_clip_cubic",
- "tex_clip_smart",
- };
-
Image *ima = (Image *)node->id;
NodeTexImage *tex = node->storage;
@@ -91,26 +68,11 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
NodeTexImage *tex_original = node_original->storage;
ImageUser *iuser = &tex_original->iuser;
- const char *gpu_node_name = (tex->projection == SHD_PROJ_BOX) ? names_box[tex->interpolation] :
- names[tex->interpolation];
- bool do_texco_extend = (tex->extension != SHD_IMAGE_EXTENSION_REPEAT);
- const bool do_texco_clip = (tex->extension == SHD_IMAGE_EXTENSION_CLIP);
-
- if (do_texco_extend && (tex->projection != SHD_PROJ_BOX) &&
- ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART)) {
- gpu_node_name = "node_tex_image_cubic_extend";
- /* We do it inside the sampling function */
- do_texco_extend = false;
- }
-
- GPUNodeLink *norm, *col1, *col2, *col3, *input_coords, *gpu_image;
- GPUNodeLink *vnor, *ob_mat, *blend;
- GPUNodeLink **texco = &in[0].link;
-
if (!ima) {
return GPU_stack_link(mat, node, "node_tex_image_empty", in, out);
}
+ GPUNodeLink **texco = &in[0].link;
if (!*texco) {
*texco = GPU_attribute(mat, CD_MTFACE, "");
node_shader_gpu_bump_tex_coord(mat, node, texco);
@@ -118,88 +80,73 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
node_shader_gpu_tex_mapping(mat, node, in, out);
+ eGPUSamplerState sampler_state = 0;
+
+ switch (tex->extension) {
+ case SHD_IMAGE_EXTENSION_REPEAT:
+ sampler_state |= GPU_SAMPLER_REPEAT;
+ break;
+ case SHD_IMAGE_EXTENSION_CLIP:
+ sampler_state |= GPU_SAMPLER_CLAMP_BORDER;
+ break;
+ default:
+ break;
+ }
+
+ if (tex->interpolation != SHD_INTERP_CLOSEST) {
+ sampler_state |= GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER;
+ sampler_state |= GPU_get_mipmap() ? GPU_SAMPLER_MIPMAP : 0;
+ }
+ const bool use_cubic = ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART);
+
if (ima->source == IMA_SRC_TILED) {
+ const char *gpu_node_name = use_cubic ? "node_tex_tile_cubic" : "node_tex_tile_linear";
+ GPUNodeLink *gpu_image = GPU_image_tiled(mat, ima, iuser, sampler_state);
+ GPUNodeLink *gpu_image_tile_mapping = GPU_image_tiled_mapping(mat, ima, iuser);
/* UDIM tiles needs a samper2DArray and sampler1DArray for tile mapping. */
- GPU_stack_link(mat,
- node,
- names_tiled[tex->interpolation],
- in,
- out,
- GPU_image_tiled(mat, ima, iuser),
- GPU_image_tiled_mapping(mat, ima, iuser));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image, gpu_image_tile_mapping);
}
else {
+ const char *gpu_node_name = use_cubic ? "node_tex_image_cubic" : "node_tex_image_linear";
+
switch (tex->projection) {
- case SHD_PROJ_FLAT:
- if (do_texco_clip) {
- /* This seems redundant, but is required to ensure the texco link
- * is not freed by GPU_link, as it is still needed for GPU_stack_link.
- * Intermediate links like this can only be used once and are then
- * freed immediately, but if we make it the output link of a set_rgb
- * node it will be kept and can be used multiple times. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- }
- if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
- }
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
+ case SHD_PROJ_FLAT: {
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
break;
-
- case SHD_PROJ_BOX:
- vnor = GPU_builtin(GPU_WORLD_NORMAL);
- ob_mat = GPU_builtin(GPU_OBJECT_MATRIX);
- blend = GPU_uniform(&tex->projection_blend);
- gpu_image = GPU_image(mat, ima, iuser);
-
+ }
+ case SHD_PROJ_BOX: {
+ gpu_node_name = use_cubic ? "tex_box_sample_cubic" : "tex_box_sample_linear";
+ GPUNodeLink *wnor, *col1, *col2, *col3;
+ GPUNodeLink *vnor = GPU_builtin(GPU_WORLD_NORMAL);
+ GPUNodeLink *ob_mat = GPU_builtin(GPU_OBJECT_MATRIX);
+ GPUNodeLink *blend = GPU_uniform(&tex->projection_blend);
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
/* equivalent to normal_world_to_object */
- GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &norm);
- {
- /* See SHD_PROJ_FLAT for explanation. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- in[0].link = input_coords;
- }
- GPU_link(
- mat, gpu_node_name, *texco, norm, GPU_image(mat, ima, iuser), &col1, &col2, &col3);
- GPU_stack_link(
- mat, node, "node_tex_image_box", in, out, norm, col1, col2, col3, gpu_image, blend);
+ GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &wnor);
+ GPU_link(mat, gpu_node_name, in[0].link, wnor, gpu_image, &col1, &col2, &col3);
+ GPU_link(mat, "tex_box_blend", wnor, col1, col2, col3, blend, &out[0].link, &out[1].link);
break;
-
- case SHD_PROJ_SPHERE:
+ }
+ case SHD_PROJ_SPHERE: {
+ /* This projection is known to have a derivative discontinuity.
+ * Hide it by turning off mipmapping. */
+ sampler_state &= ~GPU_SAMPLER_MIPMAP;
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
GPU_link(mat, "point_texco_remap_square", *texco, texco);
GPU_link(mat, "point_map_to_sphere", *texco, texco);
- if (do_texco_clip) {
- /* See SHD_PROJ_FLAT for explanation. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- }
- if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
- }
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
break;
-
- case SHD_PROJ_TUBE:
+ }
+ case SHD_PROJ_TUBE: {
+ /* This projection is known to have a derivative discontinuity.
+ * Hide it by turning off mipmapping. */
+ sampler_state &= ~GPU_SAMPLER_MIPMAP;
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
GPU_link(mat, "point_texco_remap_square", *texco, texco);
GPU_link(mat, "point_map_to_tube", *texco, texco);
- if (do_texco_clip) {
- /* See SHD_PROJ_FLAT for explanation. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- }
- if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
- }
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
break;
- }
-
- if (tex->projection != SHD_PROJ_BOX) {
- if (do_texco_clip) {
- gpu_node_name = names_clip[tex->interpolation];
- in[0].link = input_coords;
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser), out[0].link);
}
}
}
diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c
index 280f09d67c9..311cf2b8c73 100644
--- a/source/blender/python/gpu/gpu_py_offscreen.c
+++ b/source/blender/python/gpu/gpu_py_offscreen.c
@@ -40,6 +40,7 @@
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
+#include "GPU_context.h"
#include "GPU_framebuffer.h"
#include "GPU_texture.h"
@@ -84,7 +85,7 @@ static PyObject *bpygpu_offscreen_new(PyTypeObject *UNUSED(self), PyObject *args
{
BPYGPU_IS_INIT_OR_ERROR_OBJ;
- GPUOffScreen *ofs;
+ GPUOffScreen *ofs = NULL;
int width, height, samples = 0;
char err_out[256];
@@ -94,7 +95,12 @@ static PyObject *bpygpu_offscreen_new(PyTypeObject *UNUSED(self), PyObject *args
return NULL;
}
- ofs = GPU_offscreen_create(width, height, samples, true, false, err_out);
+ if (GPU_context_active_get()) {
+ ofs = GPU_offscreen_create(width, height, samples, true, false, err_out);
+ }
+ else {
+ strncpy(err_out, "No active GPU context found", 256);
+ }
if (ofs == NULL) {
PyErr_Format(PyExc_RuntimeError,
diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c
index 38a5629a2cc..165286c3661 100644
--- a/source/blender/python/gpu/gpu_py_shader.c
+++ b/source/blender/python/gpu/gpu_py_shader.c
@@ -78,7 +78,7 @@ static int bpygpu_uniform_location_get(GPUShader *shader,
const char *name,
const char *error_prefix)
{
- int uniform = GPU_shader_get_uniform_ensure(shader, name);
+ int uniform = GPU_shader_get_uniform(shader, name);
if (uniform == -1) {
PyErr_Format(PyExc_ValueError, "%s: uniform %.32s not found", error_prefix, name);
@@ -524,7 +524,7 @@ PyDoc_STRVAR(bpygpu_shader_calc_format_doc,
static PyObject *bpygpu_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg))
{
BPyGPUVertFormat *ret = (BPyGPUVertFormat *)BPyGPUVertFormat_CreatePyObject(NULL);
- GPU_vertformat_from_interface(&ret->fmt, GPU_shader_get_interface(self->shader));
+ GPU_vertformat_from_shader(&ret->fmt, self->shader);
return (PyObject *)ret;
}
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 9d0ee0bb500..de8fd87db58 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -380,10 +380,7 @@ void BPy_init_modules(void)
PyModule_AddObject(mod, "types", BPY_rna_types());
/* needs to be first so bpy_types can run */
- BPY_library_load_module(mod);
- BPY_library_write_module(mod);
-
- BPY_rna_id_collection_module(mod);
+ BPY_library_load_type_ready();
BPY_rna_gizmo_module(mod);
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index a9bdef1c3e4..957d49eb04e 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -82,10 +82,10 @@ extern char build_system[];
static PyTypeObject BlenderAppType;
static PyStructSequence_Field app_info_fields[] = {
- {"version", "The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)"},
+ {"version", "The Blender version as a tuple of 3 numbers. eg. (2, 83, 1)"},
{"version_string", "The Blender version formatted as a string"},
- {"version_char", "The Blender version character (for minor releases)"},
{"version_cycle", "The release status of this build alpha/beta/rc/release"},
+ {"version_char", "Deprecated, always an empty string"},
{"binary_path",
"The location of Blender's executable, useful for utilities that open new instances"},
{"background",
@@ -160,12 +160,12 @@ static PyObject *make_app_info(void)
#define SetBytesItem(str) PyStructSequence_SET_ITEM(app_info, pos++, PyBytes_FromString(str))
#define SetObjItem(obj) PyStructSequence_SET_ITEM(app_info, pos++, obj)
- SetObjItem(PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
- SetObjItem(PyUnicode_FromFormat(
- "%d.%02d (sub %d)", BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
+ SetObjItem(
+ PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_VERSION_PATCH));
+ SetStrItem(BKE_blender_version_string());
- SetStrItem(STRINGIFY(BLENDER_VERSION_CHAR));
SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE));
+ SetStrItem("");
SetStrItem(BKE_appdir_program_path());
SetObjItem(PyBool_FromLong(G.background));
SetObjItem(PyBool_FromLong(G.factory_startup));
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 28498e116df..dde1d13477f 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -44,8 +44,16 @@ void bpy_app_generic_callback(struct Main *main,
static PyTypeObject BlenderAppCbType;
static PyStructSequence_Field app_cb_info_fields[] = {
- {"frame_change_pre", "on frame change for playback and rendering (before)"},
- {"frame_change_post", "on frame change for playback and rendering (after)"},
+ {"frame_change_pre",
+ "Called after frame change for playback and rendering, before any data is evaluated for the "
+ "new frame. This makes it possible to change data and relations (for example swap an object "
+ "to another mesh) for the new frame. Note that this handler is **not** to be used as 'before "
+ "the frame changes' event. The dependency graph is not available in this handler, as data "
+ "and relations may have been altered and the dependency graph has not yet been updated for "
+ "that."},
+ {"frame_change_post",
+ "Called after frame change for playback and rendering, after the data has been evaluated "
+ "for the new frame."},
{"render_pre", "on render (before)"},
{"render_post", "on render (after)"},
{"render_write", "on writing a render frame (directly after the frame is written)"},
diff --git a/source/blender/python/intern/bpy_library.h b/source/blender/python/intern/bpy_library.h
index 3fd116d7028..6840807d2b0 100644
--- a/source/blender/python/intern/bpy_library.h
+++ b/source/blender/python/intern/bpy_library.h
@@ -21,7 +21,9 @@
#ifndef __BPY_LIBRARY_H__
#define __BPY_LIBRARY_H__
-int BPY_library_load_module(PyObject *mod_par);
-int BPY_library_write_module(PyObject *mod_par);
+int BPY_library_load_type_ready(void);
+extern PyMethodDef BPY_library_load_method_def;
+
+extern PyMethodDef BPY_library_write_method_def;
#endif /* __BPY_LIBRARY_H__ */
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index 989b7931444..05cbc9af601 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -459,15 +459,15 @@ static PyObject *bpy_lib_dir(BPy_Library *self)
return PyDict_Keys(self->dict);
}
-int BPY_library_load_module(PyObject *mod_par)
+PyMethodDef BPY_library_load_method_def = {
+ "load",
+ (PyCFunction)bpy_lib_load,
+ METH_STATIC | METH_VARARGS | METH_KEYWORDS,
+ bpy_lib_load_doc,
+};
+
+int BPY_library_load_type_ready(void)
{
- static PyMethodDef load_meth = {
- "load",
- (PyCFunction)bpy_lib_load,
- METH_STATIC | METH_VARARGS | METH_KEYWORDS,
- bpy_lib_load_doc,
- };
- PyModule_AddObject(mod_par, "_library_load", PyCFunction_New(&load_meth, NULL));
/* some compilers don't like accessing this directly, delay assignment */
bpy_lib_Type.tp_getattro = PyObject_GenericGetAttr;
diff --git a/source/blender/python/intern/bpy_library_write.c b/source/blender/python/intern/bpy_library_write.c
index 6c8f1deb126..fec0cef7b05 100644
--- a/source/blender/python/intern/bpy_library_write.c
+++ b/source/blender/python/intern/bpy_library_write.c
@@ -204,16 +204,9 @@ finally:
return ret;
}
-int BPY_library_write_module(PyObject *mod_par)
-{
- static PyMethodDef write_meth = {
- "write",
- (PyCFunction)bpy_lib_write,
- METH_STATIC | METH_VARARGS | METH_KEYWORDS,
- bpy_lib_write_doc,
- };
-
- PyModule_AddObject(mod_par, "_library_write", PyCFunction_New(&write_meth, NULL));
-
- return 0;
-}
+PyMethodDef BPY_library_write_method_def = {
+ "write",
+ (PyCFunction)bpy_lib_write,
+ METH_STATIC | METH_VARARGS | METH_KEYWORDS,
+ bpy_lib_write_doc,
+};
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 39485f322d4..179daad2f60 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -9040,32 +9040,41 @@ void pyrna_struct_type_extend_capi(struct StructRNA *srna,
struct PyMethodDef *method,
struct PyGetSetDef *getset)
{
- PyObject *cls = pyrna_srna_Subtype(srna);
+ /* See 'add_methods' in Python's 'typeobject.c'. */
+ PyTypeObject *type = (PyTypeObject *)pyrna_srna_Subtype(srna);
+ PyObject *dict = type->tp_dict;
if (method != NULL) {
for (; method->ml_name != NULL; method++) {
- PyObject *func = PyCFunction_New(method, NULL);
- PyObject *args = PyTuple_New(1);
- PyTuple_SET_ITEM(args, 0, func);
- PyObject *classmethod = PyObject_CallObject((PyObject *)&PyClassMethod_Type, args);
+ PyObject *py_method;
- PyObject_SetAttrString(cls, method->ml_name, classmethod);
+ if (method->ml_flags & METH_CLASS) {
+ PyObject *cfunc = PyCFunction_New(method, (PyObject *)type);
+ py_method = PyClassMethod_New(cfunc);
+ Py_DECREF(cfunc);
+ }
+ else {
+ /* Currently only static and class methods are used. */
+ BLI_assert(method->ml_flags & METH_STATIC);
+ py_method = PyCFunction_New(method, NULL);
+ }
- Py_DECREF(classmethod);
- Py_DECREF(args); /* Clears 'func' too. */
+ int err = PyDict_SetItemString(dict, method->ml_name, py_method);
+ Py_DECREF(py_method);
+ BLI_assert(!(err < 0));
+ UNUSED_VARS_NDEBUG(err);
}
}
if (getset != NULL) {
- PyObject *dict = ((PyTypeObject *)cls)->tp_dict;
for (; getset->name != NULL; getset++) {
- PyObject *descr = PyDescr_NewGetSet((PyTypeObject *)cls, getset);
+ PyObject *descr = PyDescr_NewGetSet(type, getset);
/* Ensure we're not overwriting anything that already exists. */
BLI_assert(PyDict_GetItem(dict, PyDescr_NAME(descr)) == NULL);
PyDict_SetItem(dict, PyDescr_NAME(descr), descr);
Py_DECREF(descr);
}
}
- Py_DECREF(cls);
+ Py_DECREF(type);
}
/* Access to 'owner_id' internal global. */
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index d8043ee2fdf..d792b2032b5 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -354,7 +354,7 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
if (prop) {
NlaStrip *strip = ptr.data;
- FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
+ FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), index);
result = insert_keyframe_direct(&reports, ptr, prop, fcu, cfra, keytype, NULL, options);
}
@@ -462,7 +462,7 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb
if (prop) {
ID *id = ptr.owner_id;
NlaStrip *strip = ptr.data;
- FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
+ FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), index);
/* NOTE: This should be true, or else we wouldn't be able to get here. */
BLI_assert(fcu != NULL);
@@ -577,13 +577,13 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
if (index == -1) { /* all, use a list */
int i = 0;
ret = PyList_New(0);
- while ((fcu = list_find_fcurve(&adt->drivers, path_full, i++))) {
+ while ((fcu = BKE_fcurve_find(&adt->drivers, path_full, i++))) {
RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr);
PyList_APPEND(ret, pyrna_struct_CreatePyObject(&tptr));
}
}
else {
- fcu = list_find_fcurve(&adt->drivers, path_full, index);
+ fcu = BKE_fcurve_find(&adt->drivers, path_full, index);
RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr);
ret = pyrna_struct_CreatePyObject(&tptr);
}
diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c
index cc9f5746bba..f9bcb8943f4 100644
--- a/source/blender/python/intern/bpy_rna_callback.c
+++ b/source/blender/python/intern/bpy_rna_callback.c
@@ -324,10 +324,8 @@ PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args)
return NULL;
}
- bContext *C = BPy_GetContext();
- struct wmWindowManager *wm = CTX_wm_manager(C);
handle = WM_paint_cursor_activate(
- wm, params.space_type, params.region_type, NULL, cb_wm_cursor_draw, (void *)args);
+ params.space_type, params.region_type, NULL, cb_wm_cursor_draw, (void *)args);
}
else if (RNA_struct_is_a(srna, &RNA_Space)) {
const char *error_prefix = "Space.draw_handler_add";
@@ -424,9 +422,7 @@ PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *ar
args, "OO!:WindowManager.draw_cursor_remove", &cls, &PyCapsule_Type, &py_handle)) {
return NULL;
}
- bContext *C = BPy_GetContext();
- struct wmWindowManager *wm = CTX_wm_manager(C);
- WM_paint_cursor_end(wm, handle);
+ WM_paint_cursor_end(handle);
capsule_clear = true;
}
else if (RNA_struct_is_a(srna, &RNA_Space)) {
diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c
index 6b6ffa97995..b607f1635e6 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.c
+++ b/source/blender/python/intern/bpy_rna_id_collection.c
@@ -385,32 +385,21 @@ static PyObject *bpy_orphans_purge(PyObject *UNUSED(self),
return Py_None;
}
-int BPY_rna_id_collection_module(PyObject *mod_par)
-{
- static PyMethodDef user_map = {
- "user_map", (PyCFunction)bpy_user_map, METH_VARARGS | METH_KEYWORDS, bpy_user_map_doc};
-
- PyModule_AddObject(mod_par, "_rna_id_collection_user_map", PyCFunction_New(&user_map, NULL));
-
- static PyMethodDef batch_remove = {
- "batch_remove",
- (PyCFunction)bpy_batch_remove,
- METH_VARARGS | METH_KEYWORDS,
- bpy_batch_remove_doc,
- };
-
- PyModule_AddObject(
- mod_par, "_rna_id_collection_batch_remove", PyCFunction_New(&batch_remove, NULL));
-
- static PyMethodDef orphans_purge = {
- "orphans_purge",
- (PyCFunction)bpy_orphans_purge,
- METH_VARARGS | METH_KEYWORDS,
- bpy_orphans_purge_doc,
- };
-
- PyModule_AddObject(
- mod_par, "_rna_id_collection_orphans_purge", PyCFunction_New(&orphans_purge, NULL));
-
- return 0;
-}
+PyMethodDef BPY_rna_id_collection_user_map_method_def = {
+ "user_map",
+ (PyCFunction)bpy_user_map,
+ METH_STATIC | METH_VARARGS | METH_KEYWORDS,
+ bpy_user_map_doc,
+};
+PyMethodDef BPY_rna_id_collection_batch_remove_method_def = {
+ "batch_remove",
+ (PyCFunction)bpy_batch_remove,
+ METH_STATIC | METH_VARARGS | METH_KEYWORDS,
+ bpy_batch_remove_doc,
+};
+PyMethodDef BPY_rna_id_collection_orphans_purge_method_def = {
+ "orphans_purge",
+ (PyCFunction)bpy_orphans_purge,
+ METH_STATIC | METH_VARARGS | METH_KEYWORDS,
+ bpy_orphans_purge_doc,
+};
diff --git a/source/blender/python/intern/bpy_rna_id_collection.h b/source/blender/python/intern/bpy_rna_id_collection.h
index 8cb375960a9..ee8f4c666a8 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.h
+++ b/source/blender/python/intern/bpy_rna_id_collection.h
@@ -21,6 +21,8 @@
#ifndef __BPY_RNA_ID_COLLECTION_H__
#define __BPY_RNA_ID_COLLECTION_H__
-int BPY_rna_id_collection_module(PyObject *);
+extern PyMethodDef BPY_rna_id_collection_user_map_method_def;
+extern PyMethodDef BPY_rna_id_collection_batch_remove_method_def;
+extern PyMethodDef BPY_rna_id_collection_orphans_purge_method_def;
#endif /* __BPY_RNA_ID_COLLECTION_H__ */
diff --git a/source/blender/python/intern/bpy_rna_types_capi.c b/source/blender/python/intern/bpy_rna_types_capi.c
index cfd6b7f54a8..5a2ba4a5cdb 100644
--- a/source/blender/python/intern/bpy_rna_types_capi.c
+++ b/source/blender/python/intern/bpy_rna_types_capi.c
@@ -33,8 +33,10 @@
#include "BLI_utildefines.h"
+#include "bpy_library.h"
#include "bpy_rna.h"
#include "bpy_rna_callback.h"
+#include "bpy_rna_id_collection.h"
#include "bpy_rna_types_capi.h"
#include "../generic/py_capi_utils.h"
@@ -46,6 +48,31 @@
#include "WM_api.h"
/* -------------------------------------------------------------------- */
+/** \name Blend Data
+ * \{ */
+
+static struct PyMethodDef pyrna_blenddata_methods[] = {
+ {NULL, NULL, 0, NULL}, /* #BPY_rna_id_collection_user_map_method_def */
+ {NULL, NULL, 0, NULL}, /* #BPY_rna_id_collection_batch_remove_method_def */
+ {NULL, NULL, 0, NULL}, /* #BPY_rna_id_collection_orphans_purge_method_def */
+ {NULL, NULL, 0, NULL},
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Blend Data Libraries
+ * \{ */
+
+static struct PyMethodDef pyrna_blenddatalibraries_methods[] = {
+ {NULL, NULL, 0, NULL}, /* #BPY_library_load_method_def */
+ {NULL, NULL, 0, NULL}, /* #BPY_library_write_method_def */
+ {NULL, NULL, 0, NULL},
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Window Manager Clipboard Property
*
* Avoid using the RNA API because this value may change between checking it's length
@@ -86,11 +113,11 @@ static int pyrna_WindowManager_clipboard_set(PyObject *UNUSED(self),
static struct PyMethodDef pyrna_windowmanager_methods[] = {
{"draw_cursor_add",
(PyCFunction)pyrna_callback_classmethod_add,
- METH_VARARGS | METH_STATIC,
+ METH_VARARGS | METH_CLASS,
""},
{"draw_cursor_remove",
(PyCFunction)pyrna_callback_classmethod_remove,
- METH_VARARGS | METH_STATIC,
+ METH_VARARGS | METH_CLASS,
""},
{NULL, NULL, 0, NULL},
};
@@ -147,11 +174,11 @@ PyDoc_STRVAR(pyrna_draw_handler_remove_doc,
static struct PyMethodDef pyrna_space_methods[] = {
{"draw_handler_add",
(PyCFunction)pyrna_callback_classmethod_add,
- METH_VARARGS | METH_STATIC,
+ METH_VARARGS | METH_CLASS,
pyrna_draw_handler_add_doc},
{"draw_handler_remove",
(PyCFunction)pyrna_callback_classmethod_remove,
- METH_VARARGS | METH_STATIC,
+ METH_VARARGS | METH_CLASS,
pyrna_draw_handler_remove_doc},
{NULL, NULL, 0, NULL},
};
@@ -164,7 +191,24 @@ static struct PyMethodDef pyrna_space_methods[] = {
void BPY_rna_types_extend_capi(void)
{
+ /* BlendData */
+ ARRAY_SET_ITEMS(pyrna_blenddata_methods,
+ BPY_rna_id_collection_user_map_method_def,
+ BPY_rna_id_collection_batch_remove_method_def,
+ BPY_rna_id_collection_orphans_purge_method_def);
+ BLI_assert(ARRAY_SIZE(pyrna_blenddata_methods) == 4);
+ pyrna_struct_type_extend_capi(&RNA_BlendData, pyrna_blenddata_methods, NULL);
+
+ /* BlendDataLibraries */
+ ARRAY_SET_ITEMS(
+ pyrna_blenddatalibraries_methods, BPY_library_load_method_def, BPY_library_write_method_def);
+ BLI_assert(ARRAY_SIZE(pyrna_blenddatalibraries_methods) == 3);
+ pyrna_struct_type_extend_capi(&RNA_BlendDataLibraries, pyrna_blenddatalibraries_methods, NULL);
+
+ /* Space */
pyrna_struct_type_extend_capi(&RNA_Space, pyrna_space_methods, NULL);
+
+ /* WindowManager */
pyrna_struct_type_extend_capi(
&RNA_WindowManager, pyrna_windowmanager_methods, pyrna_windowmanager_getset);
}
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index b963021dfd9..f9d2e915fad 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -160,8 +160,7 @@ typedef struct RenderResult {
typedef struct RenderStats {
int cfra;
- int totface, totvert, totstrand, tothalo, totlamp, totpart;
- short curfield, curblur, curpart, partsdone, convertdone, curfsa;
+ int totface, totvert, totlamp, totpart;
bool localview;
double starttime, lastframetime;
const char *infostr, *statstr;
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index cc685610886..af3a6fdd384 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -674,7 +674,7 @@ bool RE_bake_engine(Render *re,
/* set render info */
re->i.cfra = re->scene->r.cfra;
BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name) - 2);
- re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
+ re->i.totface = re->i.totvert = re->i.totlamp = 0;
/* render */
engine = re->engine;
@@ -812,7 +812,7 @@ int RE_engine_render(Render *re, int do_all)
/* set render info */
re->i.cfra = re->scene->r.cfra;
BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
- re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
+ re->i.totface = re->i.totvert = re->i.totlamp = 0;
/* render */
engine = re->engine;
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index 138d95af055..2e9f30397db 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -270,8 +270,6 @@ void RE_parts_init(Render *re)
/* this is render info for caller, is not reset when parts are freed! */
re->i.totpart = 0;
- re->i.curpart = 0;
- re->i.partsdone = 0;
/* just for readable code.. */
xminb = re->disprect.xmin;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index e0c59596c2a..c66c43ec467 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -203,13 +203,6 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs)
megs_used_memory,
megs_peak_memory);
- if (rs->curfield) {
- fprintf(stdout, TIP_("Field %d "), rs->curfield);
- }
- if (rs->curblur) {
- fprintf(stdout, TIP_("Blur %d "), rs->curblur);
- }
-
BLI_timecode_string_from_time_simple(
info_time_str, sizeof(info_time_str), PIL_check_seconds_timer() - rs->starttime);
fprintf(stdout, TIP_("| Time:%s | "), info_time_str);
@@ -218,23 +211,12 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs)
fprintf(stdout, "%s", rs->infostr);
}
else {
- if (rs->tothalo) {
- fprintf(stdout,
- TIP_("Sce: %s Ve:%d Fa:%d Ha:%d La:%d"),
- rs->scene_name,
- rs->totvert,
- rs->totface,
- rs->tothalo,
- rs->totlamp);
- }
- else {
- fprintf(stdout,
- TIP_("Sce: %s Ve:%d Fa:%d La:%d"),
- rs->scene_name,
- rs->totvert,
- rs->totface,
- rs->totlamp);
- }
+ fprintf(stdout,
+ TIP_("Sce: %s Ve:%d Fa:%d La:%d"),
+ rs->scene_name,
+ rs->totvert,
+ rs->totface,
+ rs->totlamp);
}
/* Flush stdout to be sure python callbacks are printing stuff after blender. */
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index ffa5bc15876..802780b37f1 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -106,6 +106,17 @@ void WM_reinit_gizmomap_all(struct Main *bmain);
void WM_script_tag_reload(void);
+bool WM_window_find_under_cursor(const wmWindowManager *wm,
+ const wmWindow *win_ignore,
+ const wmWindow *win,
+ const int mval[2],
+ wmWindow **r_win,
+ int r_mval[2]);
+void WM_window_pixel_sample_read(const wmWindowManager *wm,
+ const wmWindow *win,
+ const int pos[2],
+ float r_col[3]);
+
uint *WM_window_pixels_read(struct wmWindowManager *wm, struct wmWindow *win, int r_size[2]);
int WM_window_pixels_x(const struct wmWindow *win);
@@ -198,14 +209,13 @@ void WM_cursor_grab_disable(struct wmWindow *win, const int mouse_ungrab_xy[2]);
void WM_cursor_time(struct wmWindow *win, int nr);
struct wmPaintCursor *WM_paint_cursor_activate(
- struct wmWindowManager *wm,
short space_type,
short region_type,
bool (*poll)(struct bContext *C),
void (*draw)(struct bContext *C, int, int, void *customdata),
void *customdata);
-bool WM_paint_cursor_end(struct wmWindowManager *wm, struct wmPaintCursor *handle);
+bool WM_paint_cursor_end(struct wmPaintCursor *handle);
void WM_paint_cursor_tag_redraw(struct wmWindow *win, struct ARegion *region);
void WM_cursor_warp(struct wmWindow *win, int x, int y);
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index ae2810dfb4d..53a3fd5ebda 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -82,7 +82,7 @@ wmKeyMap *WM_keymap_find_all_spaceid_or_empty(struct wmWindowManager *wm,
const char *idname,
int spaceid,
int regionid);
-wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *keymap);
+wmKeyMap *WM_keymap_active(const struct wmWindowManager *wm, struct wmKeyMap *keymap);
bool WM_keymap_remove(struct wmKeyConfig *keyconfig, struct wmKeyMap *keymap);
bool WM_keymap_poll(struct bContext *C, struct wmKeyMap *keymap);
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
index 955fb959e92..346ed131c59 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
@@ -67,28 +67,33 @@ typedef enum eWM_GizmoFlag {
WM_GIZMO_DRAW_VALUE = (1 << 2),
WM_GIZMO_HIDDEN = (1 << 3),
WM_GIZMO_HIDDEN_SELECT = (1 << 4),
+ /** Ignore the key-map for this gizmo. */
+ WM_GIZMO_HIDDEN_KEYMAP = (1 << 5),
/**
* When set 'scale_final' value also scales the offset.
* Use when offset is to avoid screen-space overlap instead of absolute positioning. */
- WM_GIZMO_DRAW_OFFSET_SCALE = (1 << 5),
+ WM_GIZMO_DRAW_OFFSET_SCALE = (1 << 6),
/**
* User should still use 'scale_final' for any handles and UI elements.
* This simply skips scale when calculating the final matrix.
* Needed when the gizmo needs to align with the interface underneath it. */
- WM_GIZMO_DRAW_NO_SCALE = (1 << 6),
+ WM_GIZMO_DRAW_NO_SCALE = (1 << 7),
/**
* Hide the cursor and lock it's position while interacting with this gizmo.
*/
- WM_GIZMO_MOVE_CURSOR = (1 << 7),
+ WM_GIZMO_MOVE_CURSOR = (1 << 8),
/** Don't write into the depth buffer when selecting. */
- WM_GIZMO_SELECT_BACKGROUND = (1 << 8),
+ WM_GIZMO_SELECT_BACKGROUND = (1 << 9),
/** Use the active tools operator properties when running as an operator. */
- WM_GIZMO_OPERATOR_TOOL_INIT = (1 << 9),
+ WM_GIZMO_OPERATOR_TOOL_INIT = (1 << 10),
/** Don't pass through events to other handlers
* (allows click/drag not to have it's events stolen by press events in other keymaps). */
- WM_GIZMO_EVENT_HANDLE_ALL = (1 << 10),
+ WM_GIZMO_EVENT_HANDLE_ALL = (1 << 11),
+
+ /** Don't use tool-tips for this gizmo (can be distracting). */
+ WM_GIZMO_NO_TOOLTIP = (1 << 12),
} eWM_GizmoFlag;
/**
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 9aaaa0e2c81..0032a341610 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -388,7 +388,7 @@ void wm_add_default(Main *bmain, bContext *C)
win->scene = CTX_data_scene(C);
STRNCPY(win->view_layer_name, CTX_data_view_layer(C)->name);
BKE_workspace_active_set(win->workspace_hook, workspace);
- BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace, layout);
+ BKE_workspace_active_layout_set(win->workspace_hook, workspace, layout);
screen->winid = win->winid;
wm->winactive = win;
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 58ca3bf1b95..2af68956923 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -145,6 +145,16 @@ void WM_cursor_set(wmWindow *win, int curs)
return; /* Can't set custom cursor before Window init */
}
+ if (curs == WM_CURSOR_DEFAULT && win->modalcursor) {
+ curs = win->modalcursor;
+ }
+
+ if (win->cursor == curs) {
+ return; /* Cursor is already set */
+ }
+
+ win->cursor = curs;
+
if (curs == WM_CURSOR_NONE) {
GHOST_SetCursorVisibility(win->ghostwin, 0);
return;
@@ -152,12 +162,6 @@ void WM_cursor_set(wmWindow *win, int curs)
GHOST_SetCursorVisibility(win->ghostwin, 1);
- if (curs == WM_CURSOR_DEFAULT && win->modalcursor) {
- curs = win->modalcursor;
- }
-
- win->cursor = curs;
-
if (curs < 0 || curs >= WM_CURSOR_NUM) {
BLI_assert(!"Invalid cursor number");
return;
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 4cc9f4ee7d1..fa12d6cf974 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -574,13 +574,13 @@ void wm_draw_region_blend(ARegion *region, int view, bool blend)
alpha = 1.0f;
}
- glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0);
- glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"),
+ glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"),
rect_tex.xmin,
rect_tex.ymin,
rect_tex.xmax,
rect_tex.ymax);
- glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"),
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"),
rect_geo.xmin,
rect_geo.ymin,
rect_geo.xmax,
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index c7bda0bdae0..53d6df915d6 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1,4 +1,4 @@
-/*
+/*
* 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
@@ -563,7 +563,7 @@ void wm_event_do_notifiers(bContext *C)
static int wm_event_always_pass(const wmEvent *event)
{
/* some events we always pass on, to ensure proper communication */
- return ISTIMER(event->type) || (event->type == WINDEACTIVATE) || (event->type == EVT_FILESELECT);
+ return ISTIMER(event->type) || (event->type == WINDEACTIVATE);
}
/** \} */
@@ -602,6 +602,12 @@ static int wm_handler_ui_call(bContext *C,
}
}
+ /* Don't block file-select events. Those are triggered by a separate file browser window.
+ * See T75292. */
+ if (event->type == EVT_FILESELECT) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+
/* we set context to where ui handler came from */
if (handler->context.area) {
CTX_wm_area_set(C, handler->context.area);
@@ -2584,7 +2590,7 @@ static int wm_handlers_do_gizmo_handler(bContext *C,
if (wm_gizmomap_highlight_set(gzmap, C, gz, part)) {
if (gz != NULL) {
- if (U.flag & USER_TOOLTIPS) {
+ if ((U.flag & USER_TOOLTIPS) && (gz->flag & WM_GIZMO_NO_TOOLTIP) == 0) {
WM_tooltip_timer_init(C, CTX_wm_window(C), area, region, WM_gizmomap_tooltip_init);
}
}
@@ -2596,7 +2602,7 @@ static int wm_handlers_do_gizmo_handler(bContext *C,
if (handle_keymap) {
/* Handle highlight gizmo. */
- if (gz != NULL) {
+ if ((gz != NULL) && (gz->flag & WM_GIZMO_HIDDEN_KEYMAP) == 0) {
bool keymap_poll = false;
wmGizmoGroup *gzgroup = gz->parent_gzgroup;
wmKeyMap *keymap = WM_keymap_active(wm, gz->keymap ? gz->keymap : gzgroup->type->keymap);
@@ -4248,7 +4254,7 @@ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *g
/* imperfect but probably usable... draw/enable drags to other windows */
static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *event)
{
- int mx = event->x, my = event->y;
+ int mval[2] = {event->x, event->y};
if (wm->windows.first == wm->windows.last) {
return NULL;
@@ -4257,7 +4263,8 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
/* in order to use window size and mouse position (pixels), we have to use a WM function */
/* check if outside, include top window bar... */
- if (mx < 0 || my < 0 || mx > WM_window_pixels_x(win) || my > WM_window_pixels_y(win) + 30) {
+ if (mval[0] < 0 || mval[1] < 0 || mval[0] > WM_window_pixels_x(win) ||
+ mval[1] > WM_window_pixels_y(win) + 30) {
wmWindow *owin;
wmEventHandler *handler;
@@ -4270,25 +4277,10 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
}
}
- /* to desktop space */
- mx += (int)(U.pixelsize * win->posx);
- my += (int)(U.pixelsize * win->posy);
-
- /* check other windows to see if it has mouse inside */
- for (owin = wm->windows.first; owin; owin = owin->next) {
-
- if (owin != win) {
- int posx = (int)(U.pixelsize * owin->posx);
- int posy = (int)(U.pixelsize * owin->posy);
-
- if (mx - posx >= 0 && owin->posy >= 0 && mx - posx <= WM_window_pixels_x(owin) &&
- my - posy <= WM_window_pixels_y(owin)) {
- event->x = mx - (int)(U.pixelsize * owin->posx);
- event->y = my - (int)(U.pixelsize * owin->posy);
-
- return owin;
- }
- }
+ if (WM_window_find_under_cursor(wm, win, win, mval, &owin, mval)) {
+ event->x = mval[0];
+ event->y = mval[1];
+ return owin;
}
}
return NULL;
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index cc81e4f2715..ed1b29d61ce 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -141,11 +141,37 @@ static void wm_history_file_free(RecentFile *recent);
static void wm_history_file_update(void);
static void wm_history_file_write(void);
-/* To be able to read files without windows closing, opening, moving
+/* -------------------------------------------------------------------- */
+/** \name Misc Utility Functions
+ * \{ */
+
+void WM_file_tag_modified(void)
+{
+ wmWindowManager *wm = G_MAIN->wm.first;
+ if (wm->file_saved) {
+ wm->file_saved = 0;
+ /* notifier that data changed, for save-over warning or header */
+ WM_main_add_notifier(NC_WM | ND_DATACHANGED, NULL);
+ }
+}
+
+bool wm_file_or_image_is_modified(const Main *bmain, const wmWindowManager *wm)
+{
+ return !wm->file_saved || ED_image_should_save_modified(bmain);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Window Matching for File Reading
+ * \{ */
+
+/**
+ * To be able to read files without windows closing, opening, moving
* we try to prepare for worst case:
* - active window gets active screen from file
* - restoring the screens from non-active windows
- * Best case is all screens match, in that case they get assigned to proper window
+ * Best case is all screens match, in that case they get assigned to proper window.
*/
static void wm_window_match_init(bContext *C, ListBase *wmlist)
{
@@ -355,6 +381,12 @@ static void wm_window_match_do(bContext *C,
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Preferences Initialization & Versioning
+ * \{ */
+
/* in case UserDef was read, we re-initialize all, and do versioning */
static void wm_init_userdef(Main *bmain)
{
@@ -389,6 +421,15 @@ static void wm_init_userdef(Main *bmain)
# define BKE_READ_EXOTIC_OK_OTHER 1 /* other supported formats */
#endif
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Exotic File Formats
+ *
+ * Currently only supports '.blend' files,
+ * we could support registering other file formats and their loaders.
+ * \{ */
+
/* intended to check for non-blender formats but for now it only reads blends */
static int wm_read_exotic(const char *name)
{
@@ -441,6 +482,12 @@ static int wm_read_exotic(const char *name)
return retval;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Blend-File Shared Utilities
+ * \{ */
+
void WM_file_autoexec_init(const char *filepath)
{
if (G.f & G_FLAG_SCRIPT_OVERRIDE_PREF) {
@@ -486,6 +533,24 @@ void wm_file_read_report(bContext *C, Main *bmain)
/**
* Logic shared between #WM_file_read & #wm_homefile_read,
+ * call before loading a file.
+ * \note In the case of #WM_file_read the file may fail to load.
+ * Change here shouldn't cause user-visible changes in that case.
+ */
+static void wm_file_read_pre(bContext *C, bool use_data, bool UNUSED(use_userdef))
+{
+ if (use_data) {
+ BKE_callback_exec_null(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE);
+ BLI_timer_on_file_load();
+ }
+
+ /* Always do this as both startup and preferences may have loaded in many font's
+ * at a different zoom level to the file being loaded. */
+ UI_view2d_zoom_cache_reset();
+}
+
+/**
+ * Logic shared between #WM_file_read & #wm_homefile_read,
* updates to make after reading a file.
*/
static void wm_file_read_post(bContext *C,
@@ -510,12 +575,16 @@ static void wm_file_read_post(bContext *C,
if (is_startup_file) {
/* possible python hasn't been initialized */
if (CTX_py_init_get(C)) {
- if (reset_app_template) {
+ bool reset_all = use_userdef;
+ if (use_userdef || reset_app_template) {
/* Only run when we have a template path found. */
if (BKE_appdir_app_template_any()) {
BPY_execute_string(
C, (const char *[]){"bl_app_template_utils", NULL}, "bl_app_template_utils.reset()");
+ reset_all = true;
}
+ }
+ if (reset_all) {
/* sync addons, these may have changed from the defaults */
BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()");
}
@@ -601,21 +670,27 @@ static void wm_file_read_post(bContext *C,
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Main Blend-File API
+ * \{ */
+
bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
{
/* assume automated tasks with background, don't write recent file list */
const bool do_history = (G.background == false) && (CTX_wm_manager(C)->op_undo_depth == 0);
bool success = false;
+ const bool use_data = true;
+ const bool use_userdef = false;
+
/* so we can get the error message */
errno = 0;
WM_cursor_wait(1);
- BKE_callback_exec_null(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE);
- BLI_timer_on_file_load();
-
- UI_view2d_zoom_cache_reset();
+ wm_file_read_pre(C, use_data, use_userdef);
/* first try to append data from exotic file formats... */
/* it throws error box when file doesn't exist and returns -1 */
@@ -675,8 +750,6 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
}
- const bool use_data = true;
- const bool use_userdef = false;
wm_file_read_post(C, false, false, use_data, use_userdef, false);
}
#if 0
@@ -746,6 +819,12 @@ const char *WM_init_state_app_template_get(void)
return wm_init_state_app_template.override ? wm_init_state_app_template.app_template : NULL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Startup & Preferences Blend-File API
+ * \{ */
+
/**
* Called on startup, (context entirely filled with NULLs)
* or called for 'New File' both startup.blend and userpref.blend are checked.
@@ -802,6 +881,23 @@ void wm_homefile_read(bContext *C,
* or use app-template startup.blend which the user hasn't saved. */
bool is_factory_startup = true;
+ const char *app_template = NULL;
+ bool update_defaults = false;
+
+ if (filepath_startup_override != NULL) {
+ /* pass */
+ }
+ else if (app_template_override) {
+ /* This may be clearing the current template by setting to an empty string. */
+ app_template = app_template_override;
+ }
+ else if (!use_factory_settings && U.app_template[0]) {
+ app_template = U.app_template;
+ }
+
+ const bool reset_app_template = ((!app_template && U.app_template[0]) ||
+ (app_template && !STREQ(app_template, U.app_template)));
+
/* options exclude eachother */
BLI_assert((use_factory_settings && filepath_startup_override) == 0);
@@ -809,18 +905,30 @@ void wm_homefile_read(bContext *C,
SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_FLAG_SCRIPT_AUTOEXEC);
}
- if (use_data) {
- BKE_callback_exec_null(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE);
- BLI_timer_on_file_load();
+ if (use_userdef || reset_app_template) {
+#ifdef WITH_PYTHON
+ /* This only runs once Blender has already started. */
+ if (CTX_py_init_get(C)) {
+ /* This is restored by 'wm_file_read_post', disable before loading any preferences
+ * so an add-on can read their own preferences when un-registering,
+ * and use new preferences if/when re-registering, see T67577.
+ *
+ * Note that this fits into 'wm_file_read_pre' function but gets messy
+ * since we need to know if 'reset_app_template' is true. */
+ BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.disable_all()");
+ }
+#endif /* WITH_PYTHON */
+ }
+
+ wm_file_read_pre(C, use_data, use_userdef);
+ if (use_data) {
G.relbase_valid = 0;
/* put aside screens to match with persistent windows later */
wm_window_match_init(C, &wmbase);
}
- UI_view2d_zoom_cache_reset();
-
filepath_startup[0] = '\0';
filepath_userdef[0] = '\0';
app_template_system[0] = '\0';
@@ -861,28 +969,6 @@ void wm_homefile_read(bContext *C,
}
}
- const char *app_template = NULL;
- bool update_defaults = false;
- bool reset_app_template = false;
-
- if (filepath_startup_override != NULL) {
- /* pass */
- }
- else if (app_template_override) {
- /* This may be clearing the current template by setting to an empty string. */
- app_template = app_template_override;
- }
- else if (!use_factory_settings && U.app_template[0]) {
- app_template = U.app_template;
- }
-
- if ((!app_template && U.app_template[0]) ||
- (app_template && !STREQ(app_template, U.app_template))) {
- /* Always load UI when switching to another template. */
- G.fileflags &= ~G_FILE_NO_UI;
- reset_app_template = true;
- }
-
if ((app_template != NULL) && (app_template[0] != '\0')) {
if (!BKE_appdir_app_template_id_search(
app_template, app_template_system, sizeof(app_template_system))) {
@@ -1028,6 +1114,11 @@ void wm_homefile_read(bContext *C,
* Screws up autosaves otherwise can remove this eventually,
* only in a 2.53 and older, now its not written. */
G.fileflags &= ~G_FILE_RELATIVE_REMAP;
+
+ if (reset_app_template) {
+ /* Always load UI when switching to another template. */
+ G.fileflags &= ~G_FILE_NO_UI;
+ }
}
bmain = CTX_data_main(C);
@@ -1035,7 +1126,6 @@ void wm_homefile_read(bContext *C,
if (use_userdef) {
/* check userdef before open window, keymaps etc */
wm_init_userdef(bmain);
- reset_app_template = true;
}
if (use_data) {
@@ -1070,7 +1160,7 @@ void wm_homefile_read(bContext *C,
}
/* -------------------------------------------------------------------- */
-/** \name WM History File API
+/** \name Blend-File History API
* \{ */
void wm_history_file_read(void)
@@ -1199,7 +1289,7 @@ static void wm_history_file_update(void)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Save Main .blend File (internal)
+/** \name Save Main Blend-File (internal)
* \{ */
/* screen can be NULL */
@@ -1623,18 +1713,8 @@ void wm_open_init_use_scripts(wmOperator *op, bool use_prefs)
/** \} */
-void WM_file_tag_modified(void)
-{
- wmWindowManager *wm = G_MAIN->wm.first;
- if (wm->file_saved) {
- wm->file_saved = 0;
- /* notifier that data changed, for save-over warning or header */
- WM_main_add_notifier(NC_WM | ND_DATACHANGED, NULL);
- }
-}
-
/* -------------------------------------------------------------------- */
-/** \name Preferences/startup save & load.
+/** \name Startup File Save Operator
* \{ */
/**
@@ -1699,48 +1779,11 @@ void WM_OT_save_homefile(wmOperatorType *ot)
ot->exec = wm_homefile_write_exec;
}
-static int wm_userpref_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
-{
- bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare");
- BLI_addtail(&U.autoexec_paths, path_cmp);
- U.runtime.is_dirty = true;
- return OPERATOR_FINISHED;
-}
-
-void WM_OT_userpref_autoexec_path_add(wmOperatorType *ot)
-{
- ot->name = "Add Autoexec Path";
- ot->idname = "WM_OT_userpref_autoexec_path_add";
- ot->description = "Add path to exclude from autoexecution";
-
- ot->exec = wm_userpref_autoexec_add_exec;
-
- ot->flag = OPTYPE_INTERNAL;
-}
-
-static int wm_userpref_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op)
-{
- const int index = RNA_int_get(op->ptr, "index");
- bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index);
- if (path_cmp) {
- BLI_freelinkN(&U.autoexec_paths, path_cmp);
- U.runtime.is_dirty = true;
- }
- return OPERATOR_FINISHED;
-}
-
-void WM_OT_userpref_autoexec_path_remove(wmOperatorType *ot)
-{
- ot->name = "Remove Autoexec Path";
- ot->idname = "WM_OT_userpref_autoexec_path_remove";
- ot->description = "Remove path to exclude from autoexecution";
-
- ot->exec = wm_userpref_autoexec_remove_exec;
-
- ot->flag = OPTYPE_INTERNAL;
+/** \} */
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
-}
+/* -------------------------------------------------------------------- */
+/** \name Write Preferences Operator
+ * \{ */
/* Only save the prefs block. operator entry */
static int wm_userpref_write_exec(bContext *C, wmOperator *op)
@@ -1765,6 +1808,12 @@ void WM_OT_save_userpref(wmOperatorType *ot)
ot->exec = wm_userpref_write_exec;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Preferences Operator
+ * \{ */
+
/**
* When reading preferences, there are some exceptions for values which are reset.
*/
@@ -1828,10 +1877,6 @@ static void wm_userpref_update_when_changed(bContext *C,
rna_struct_update_when_changed(C, bmain, &ptr_a, &ptr_b);
-#ifdef WITH_PYTHON
- BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()");
-#endif
-
WM_reinit_gizmomap_all(bmain);
WM_keyconfig_reload(C);
@@ -1897,6 +1942,12 @@ void WM_OT_read_factory_userpref(wmOperatorType *ot)
ot->exec = wm_userpref_read_exec;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read File History Operator
+ * \{ */
+
static int wm_history_file_read_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
{
ED_file_read_bookmarks();
@@ -1917,6 +1968,14 @@ void WM_OT_read_history(wmOperatorType *ot)
ot->flag = OPTYPE_INTERNAL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Startup & Preferences Operator
+ *
+ * Both #WM_OT_read_homefile & #WM_OT_read_factory_settings.
+ * \{ */
+
static int wm_homefile_read_exec(bContext *C, wmOperator *op)
{
const bool use_factory_settings = (STREQ(op->type->idname, "WM_OT_read_factory_settings"));
@@ -2442,7 +2501,7 @@ void WM_OT_revert_mainfile(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Recover last session & auto-save.
+/** \name Recover Last Session Operator
* \{ */
void WM_recover_last_session(bContext *C, ReportList *reports)
@@ -2486,6 +2545,12 @@ void WM_OT_recover_last_session(wmOperatorType *ot)
ot->exec = wm_recover_last_session_exec;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Auto-Save Main .blend File Operator
+ * \{ */
+
static int wm_recover_auto_save_exec(bContext *C, wmOperator *op)
{
char filepath[FILE_MAX];
@@ -2540,6 +2605,8 @@ void WM_OT_recover_auto_save(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
/** \name Save Main .blend File Operator
+ *
+ * Both #WM_OT_save_as_mainfile & #WM_OT_save_mainfile.
* \{ */
static void wm_filepath_default(char *filepath)
@@ -2766,7 +2833,7 @@ void WM_OT_save_mainfile(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Auto-execution of scripts warning popup
+/** \name Auto Script Execution Warning Dialog
* \{ */
static void wm_block_autorun_warning_ignore(bContext *C, void *arg_block, void *UNUSED(arg))
@@ -2968,8 +3035,11 @@ void wm_test_autorun_warning(bContext *C)
}
}
-/* Close File Dialog
- *************************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Close File Dialog
+ * \{ */
static char save_images_when_file_is_closed = true;
@@ -3235,9 +3305,4 @@ void wm_close_file_dialog(bContext *C, wmGenericCallback *post_action)
}
}
-bool wm_file_or_image_is_modified(const Main *bmain, const wmWindowManager *wm)
-{
- return !wm->file_saved || ED_image_should_save_modified(bmain);
-}
-
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 9aa401722b7..6b2a74138c9 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -365,7 +365,7 @@ static void draw_filled_lasso(wmGesture *gt)
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_bind(state.shader);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
immDrawPixelsTex(&state,
rect.xmin,
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index fc3f0c87b69..001acc459c2 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -187,7 +187,7 @@ void WM_init_opengl(Main *bmain)
GPU_init();
GPU_set_mipmap(bmain, true);
GPU_set_linear_mipmap(true);
- GPU_set_anisotropic(bmain, U.anisotropic_filter);
+ GPU_set_anisotropic(U.anisotropic_filter);
GPU_pass_cache_init();
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 5f2b492088e..d7102a1e8af 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -1936,7 +1936,7 @@ void WM_keyconfig_update(wmWindowManager *wm)
* During event handling this function is called to get the keymap from the final configuration.
* \{ */
-wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap)
+wmKeyMap *WM_keymap_active(const wmWindowManager *wm, wmKeyMap *keymap)
{
wmKeyMap *km;
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 39811d67b9a..f99f47bc3ad 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -2059,13 +2059,14 @@ static void WM_OT_console_toggle(wmOperatorType *ot)
*
* \{ */
-wmPaintCursor *WM_paint_cursor_activate(wmWindowManager *wm,
- short space_type,
+wmPaintCursor *WM_paint_cursor_activate(short space_type,
short region_type,
bool (*poll)(bContext *C),
wmPaintCursorDraw draw,
void *customdata)
{
+ wmWindowManager *wm = G_MAIN->wm.first;
+
wmPaintCursor *pc = MEM_callocN(sizeof(wmPaintCursor), "paint cursor");
BLI_addtail(&wm->paintcursors, pc);
@@ -2080,11 +2081,10 @@ wmPaintCursor *WM_paint_cursor_activate(wmWindowManager *wm,
return pc;
}
-bool WM_paint_cursor_end(wmWindowManager *wm, wmPaintCursor *handle)
+bool WM_paint_cursor_end(wmPaintCursor *handle)
{
- wmPaintCursor *pc;
-
- for (pc = wm->paintcursors.first; pc; pc = pc->next) {
+ wmWindowManager *wm = G_MAIN->wm.first;
+ for (wmPaintCursor *pc = wm->paintcursors.first; pc; pc = pc->next) {
if (pc == (wmPaintCursor *)handle) {
BLI_remlink(&wm->paintcursors, pc);
MEM_freeN(pc);
@@ -2759,7 +2759,7 @@ static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *eve
/* add radial control paint cursor */
rc->cursor = WM_paint_cursor_activate(
- wm, SPACE_TYPE_ANY, RGN_TYPE_ANY, op->type->poll, radial_control_paint_cursor, rc);
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, op->type->poll, radial_control_paint_cursor, rc);
WM_event_add_modal_handler(C, op);
@@ -2793,7 +2793,7 @@ static void radial_control_cancel(bContext *C, wmOperator *op)
ED_area_status_text(area, NULL);
- WM_paint_cursor_end(wm, rc->cursor);
+ WM_paint_cursor_end(rc->cursor);
/* restore original paint cursors */
wm->paintcursors = rc->orig_paintcursors;
@@ -3778,8 +3778,6 @@ void wm_operatortypes_register(void)
WM_operatortype_append(WM_OT_save_userpref);
WM_operatortype_append(WM_OT_read_userpref);
WM_operatortype_append(WM_OT_read_factory_userpref);
- WM_operatortype_append(WM_OT_userpref_autoexec_path_add);
- WM_operatortype_append(WM_OT_userpref_autoexec_path_remove);
WM_operatortype_append(WM_OT_window_fullscreen_toggle);
WM_operatortype_append(WM_OT_quit_blender);
WM_operatortype_append(WM_OT_open_mainfile);
diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c
index 8445fac0498..b75609fd28f 100644
--- a/source/blender/windowmanager/intern/wm_splash_screen.c
+++ b/source/blender/windowmanager/intern/wm_splash_screen.c
@@ -96,39 +96,7 @@ static void wm_block_splash_add_label(uiBlock *block, const char *label, int x,
UI_block_emboss_set(block, UI_EMBOSS);
}
-static void get_version_string(char *ver, const int max_length)
-{
- /* Version number. */
- const char *version_cycle = NULL;
-
- if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) {
- version_cycle = " Alpha";
- }
- else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "beta")) {
- version_cycle = " Beta";
- }
- else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "rc")) {
- version_cycle = " Release Candidate";
- }
- else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) {
- version_cycle = STRINGIFY(BLENDER_VERSION_CHAR);
- }
-
- const char *version_cycle_number = "";
- if (strlen(STRINGIFY(BLENDER_VERSION_CYCLE_NUMBER))) {
- version_cycle_number = " " STRINGIFY(BLENDER_VERSION_CYCLE_NUMBER);
- }
-
- BLI_snprintf(ver,
- max_length,
- "%d.%d.%d%s%s",
- BLENDER_VERSION / 100,
- BLENDER_VERSION % 100,
- BLENDER_SUBVERSION,
- version_cycle,
- version_cycle_number);
-}
-
+#ifndef WITH_HEADLESS
static void wm_block_splash_image_roundcorners_add(ImBuf *ibuf)
{
uchar *rct = (uchar *)ibuf->rect;
@@ -179,6 +147,7 @@ static void wm_block_splash_image_roundcorners_add(ImBuf *ibuf)
}
}
}
+#endif /* WITH_HEADLESS */
static ImBuf *wm_block_splash_image(int width, int *r_height)
{
@@ -219,6 +188,7 @@ static ImBuf *wm_block_splash_image(int width, int *r_height)
return ibuf;
#else
+ UNUSED_VARS(width, r_height);
return NULL;
#endif
}
@@ -249,9 +219,8 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *region, void *UNUSE
UI_but_func_set(but, wm_block_close, block, NULL);
UI_block_func_set(block, wm_block_splash_refreshmenu, block, NULL);
- char version_buf[256] = "\0";
- get_version_string(version_buf, sizeof(version_buf));
- wm_block_splash_add_label(block, version_buf, splash_width, splash_height - 13.0 * U.dpi_fac);
+ wm_block_splash_add_label(
+ block, BKE_blender_version_string(), splash_width, splash_height - 13.0 * U.dpi_fac);
const int layout_margin_x = U.dpi_fac * 26;
uiLayout *layout = UI_block_layout(block,
@@ -329,9 +298,7 @@ static uiBlock *wm_block_create_about(bContext *C, ARegion *region, void *UNUSED
uiItemL_ex(layout, "Blender", ICON_NONE, true, false);
/* Version. */
- char str_buf[256] = "\0";
- get_version_string(str_buf, sizeof(str_buf));
- uiItemL(layout, str_buf, ICON_NONE);
+ uiItemL(layout, BKE_blender_version_string(), ICON_NONE);
uiItemS_ex(layout, 3.0f);
@@ -339,6 +306,7 @@ static uiBlock *wm_block_create_about(bContext *C, ARegion *region, void *UNUSED
extern char build_hash[], build_commit_date[], build_commit_time[], build_branch[];
+ char str_buf[256] = "\0";
BLI_snprintf(str_buf, sizeof(str_buf), "Date: %s %s", build_commit_date, build_commit_time);
uiItemL(layout, str_buf, ICON_NONE);
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index fcb2be0a0bb..1ba22652157 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -326,7 +326,7 @@ wmWindow *wm_window_copy(Main *bmain,
layout_new = duplicate_layout ?
ED_workspace_layout_duplicate(bmain, workspace, layout_old, win_dst) :
layout_old;
- BKE_workspace_hook_layout_for_workspace_set(win_dst->workspace_hook, workspace, layout_new);
+ BKE_workspace_active_layout_set(win_dst->workspace_hook, workspace, layout_new);
*win_dst->stereo3d_format = *win_src->stereo3d_format;
@@ -1984,6 +1984,90 @@ bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Find Window Utility
+ *
+ * \{ */
+static void wm_window_desktop_pos_get(const wmWindow *win,
+ const int screen_pos[2],
+ int r_desk_pos[2])
+{
+ /* To desktop space. */
+ r_desk_pos[0] = screen_pos[0] + (int)(U.pixelsize * win->posx);
+ r_desk_pos[1] = screen_pos[1] + (int)(U.pixelsize * win->posy);
+}
+
+static void wm_window_screen_pos_get(const wmWindow *win,
+ const int desktop_pos[2],
+ int r_scr_pos[2])
+{
+ /* To window space. */
+ r_scr_pos[0] = desktop_pos[0] - (int)(U.pixelsize * win->posx);
+ r_scr_pos[1] = desktop_pos[1] - (int)(U.pixelsize * win->posy);
+}
+
+bool WM_window_find_under_cursor(const wmWindowManager *wm,
+ const wmWindow *win_ignore,
+ const wmWindow *win,
+ const int mval[2],
+ wmWindow **r_win,
+ int r_mval[2])
+{
+ int desk_pos[2];
+ wm_window_desktop_pos_get(win, mval, desk_pos);
+
+ /* TODO: This should follow the order of the activated windows.
+ * The current solution is imperfect but usable in most cases. */
+ LISTBASE_FOREACH (wmWindow *, win_iter, &wm->windows) {
+ if (win_iter == win_ignore) {
+ continue;
+ }
+
+ if (win_iter->windowstate == GHOST_kWindowStateMinimized) {
+ continue;
+ }
+
+ int scr_pos[2];
+ wm_window_screen_pos_get(win_iter, desk_pos, scr_pos);
+
+ if (scr_pos[0] >= 0 && win_iter->posy >= 0 && scr_pos[0] <= WM_window_pixels_x(win_iter) &&
+ scr_pos[1] <= WM_window_pixels_y(win_iter)) {
+
+ *r_win = win_iter;
+ copy_v2_v2_int(r_mval, scr_pos);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void WM_window_pixel_sample_read(const wmWindowManager *wm,
+ const wmWindow *win,
+ const int pos[2],
+ float r_col[3])
+{
+ bool setup_context = wm->windrawable != win;
+
+ if (setup_context) {
+ GHOST_ActivateWindowDrawingContext(win->ghostwin);
+ GPU_context_active_set(win->gpuctx);
+ }
+
+ glReadBuffer(GL_FRONT);
+ glReadPixels(pos[0], pos[1], 1, 1, GL_RGB, GL_FLOAT, r_col);
+ glReadBuffer(GL_BACK);
+
+ if (setup_context) {
+ if (wm->windrawable) {
+ GHOST_ActivateWindowDrawingContext(wm->windrawable->ghostwin);
+ GPU_context_active_set(wm->windrawable->gpuctx);
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Window Screen Shot Utility
*
* Include here since it can involve low level buffer switching.
@@ -2359,7 +2443,7 @@ WorkSpaceLayout *WM_window_get_active_layout(const wmWindow *win)
}
void WM_window_set_active_layout(wmWindow *win, WorkSpace *workspace, WorkSpaceLayout *layout)
{
- BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace, layout);
+ BKE_workspace_active_layout_set(win->workspace_hook, workspace, layout);
}
/**
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index e081742b904..42eab35cdb9 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -45,8 +45,6 @@ void wm_close_file_dialog(bContext *C, struct wmGenericCallback *post_action);
bool wm_file_or_image_is_modified(const Main *bmain, const wmWindowManager *wm);
void WM_OT_save_homefile(struct wmOperatorType *ot);
-void WM_OT_userpref_autoexec_path_add(struct wmOperatorType *ot);
-void WM_OT_userpref_autoexec_path_remove(struct wmOperatorType *ot);
void WM_OT_save_userpref(struct wmOperatorType *ot);
void WM_OT_read_userpref(struct wmOperatorType *ot);
void WM_OT_read_factory_userpref(struct wmOperatorType *ot);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr.c b/source/blender/windowmanager/xr/intern/wm_xr.c
index 69c9034d51f..90f30809136 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr.c
@@ -126,7 +126,12 @@ void wm_xr_exit(wmWindowManager *wm)
bool wm_xr_events_handle(wmWindowManager *wm)
{
if (wm->xr.runtime && wm->xr.runtime->context) {
- return GHOST_XrEventsHandle(wm->xr.runtime->context);
+ GHOST_XrEventsHandle(wm->xr.runtime->context);
+
+ /* wm_window_process_events() uses the return value to determine if it can put the main thread
+ * to sleep for some milliseconds. We never want that to happen while the VR session runs on
+ * the main thread. So always return true. */
+ return true;
}
return false;
}